Changes for 2.0.0:

Bulk updates relating to the 2.0.0 public release of GLUM.
This commit is contained in:
lopeznr1
2024-09-17 20:43:19 -04:00
parent 8c8523a851
commit 1727820320
323 changed files with 18557 additions and 10432 deletions

View File

@@ -1,11 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-16"/>
<classpathentry kind="lib" path="lib/guava-18.0.jar" sourcepath="lib/guava-18.0-sources.jar">
<attributes>
<attribute name="module" value="true"/>
@@ -16,7 +12,7 @@
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/miglayout-3.7.2-swing.jar">
<classpathentry kind="lib" path="lib/miglayout-3.7.2-swing.jar" sourcepath="lib/miglayout-3.7.2-sources.jar">
<attributes>
<attribute name="module" value="true"/>
</attributes>

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
bin/
doc/
unused/

View File

@@ -0,0 +1,460 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=16
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=16
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=16
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false
org.eclipse.jdt.core.formatter.align_with_spaces=false
org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false
org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.indent_tag_description=false
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=120
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert
org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false
org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false
org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false
org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
org.eclipse.jdt.core.formatter.lineSplit=120
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=3
org.eclipse.jdt.core.formatter.use_on_off_tags=true
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter

View File

@@ -0,0 +1,63 @@
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_NobesFormat-2019Aug
formatter_settings_version=16
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.make_local_variable_final=true
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=true
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_redundant_modifiers=false
sp_cleanup.remove_redundant_semicolons=false
sp_cleanup.remove_redundant_type_arguments=false
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_anonymous_class_creation=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_lambda=true
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

202
LICENSE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

50
README.md Normal file
View File

@@ -0,0 +1,50 @@
# GLUM: Great Library of User Modules
## Description
GLUM is a Java library that provides a collection of generic components, modules, and utilities which aid in development of Java software applications.
It provides the following high level capabilities:
- various components and utilities to simplify the development (creation, layout, organization, setup) of a Swing based user interface (UI)
- a data model focused framework for the display, editing, filtering, and searching of tabular data
- capability to monitor, query, or alter a “task” (mechanism to allow an end user to get information, track progress, and abort a process)
- serialization mechanism for saving and loading of application state
- capability to configure the output of data values (numeric, textual, date/time, etc)
- framework to allow retrieval (start, pause, resume) and management of data (local and/or remote) resources
## Usage
The latest release of GLUM is 2.0.0 and is distributed as a binary jar (glum-2.0.0.jar) and the corresponding source jar (glum-2.0.0-src.jar). These will need to be added to your class path.
It is intended that support via Maven mechanism will be provided in a future release.
## Dependencies
The GLUM library has the following (linking) dependencies utilized while developing the GLUM library:
- Java 17
- Guava: 18.0
- MigLayout: 3.7.2
- DockingFrames: 1.1.3
In addition, to compile GLUM the following software packages are needed:
- JDK 17+
- Python 3.6+
- Apache Ant 1.10.8+
Note the following:
- In theory GLUM should work with later versions of the above listed software, but these were the ones utilized during the primary development phase.
- The DockingFrames dependency is only necessary if gui docking capabilities are desired.
## Building GLUM
To build GLUM from the console, run the following command:
&nbsp;&nbsp;&nbsp;&nbsp;./tools/buildRelease

BIN
release/glum-2.0.0-src.jar Normal file

Binary file not shown.

BIN
release/glum-2.0.0.jar Normal file

Binary file not shown.

32
src/glum/app/AppGlum.java Normal file
View File

@@ -0,0 +1,32 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.app;
/**
* Provides the main entry point.
* <p>
* Currently this will just print the library name and the version.
*/
public class AppGlum
{
/**
* Main entry point that will print out the version of Glum to stdout.
*/
public static void main(String[] aArgArr)
{
System.out.println("Glum Library. Version: " + AppInfo.getVersion());
System.exit(0);
}
}

39
src/glum/app/AppInfo.java Normal file
View File

@@ -0,0 +1,39 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.app;
/**
* Immutable class that provides information related to the build.
*
* @author lopeznr1
*/
public class AppInfo
{
/**
* Defines the version of the Glum library.
* <p>
* Note we do not make the Version directly visible and final so other classes will not utilized a cached version
* when built via Ant.
*/
private static String Version = "2.0.0";
/**
* Returns the version of the application
*/
public static String getVersion()
{
return Version;
}
}

View File

@@ -0,0 +1,121 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.color;
import java.awt.Color;
/**
* Immutable object which provides access to attributes of a color.
* <p>
* The attributes are: hue, saturation, brightness, luminance
*
* @author lopeznr1
*/
public class ColorHSBL
{
// Attributes
private final Color refColor;
private final float hue;
private final float saturation;
private final float brightness;
private final float luminance;
/** Standard Constructor */
public ColorHSBL(Color aColor)
{
refColor = aColor;
float[] tmpArr = convertColorToHSBL(aColor);
hue = tmpArr[0];
saturation = tmpArr[1];
brightness = tmpArr[2];
luminance = tmpArr[3];
}
/**
* Returns the associated {@link Color}.
*/
public Color getColor()
{
return refColor;
}
/**
* Returns the hue component.
*/
public float getHue()
{
return hue;
}
/**
* Returns the saturation component.
*/
public float getSaturation()
{
return saturation;
}
/**
* Returns the brightness component.
*/
public float getBrightness()
{
return brightness;
}
/**
* Returns the luminance component.
*/
public float getLuminance()
{
return luminance;
}
/**
* Utility method that returns a 4 element array that has the following in the elements
* <ul>
* <li>hue
* <li>saturation
* <li>brightness
* <li>luminosity
* </ul>
* The source for this conversion originated from:</br>
* https://stackoverflow.com/questions/596216/formula-to-determine-perceived-brightness-of-rgb-color
* <p>
* Note the above source has changed overtime and the conversion below is not authoritative.
*/
public static float[] convertColorToHSBL(Color aColor)
{
int rI = aColor.getRed();
int gI = aColor.getGreen();
int bI = aColor.getBlue();
float rF = rI / 255.0f;
float gF = gI / 255.0f;
float bF = bI / 255.0f;
// Formula: broken
// float lum = (float) Math.sqrt(0.241f * rF + 0.691f * gF + 0.068f * bF);
// Formula: corrected
// float lum = (0.299f * rF + 0.587f * gF + 0.114f * bF);
float lum = (float) Math.sqrt(0.299f * rF * rF + 0.587f * gF * gF + 0.114f * bF * bF);
float[] hsblArr = new float[4];
Color.RGBtoHSB(rI, gI, bI, hsblArr);
hsblArr[3] = lum;
return hsblArr;
}
}

View File

@@ -0,0 +1,125 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.color;
import java.util.Comparator;
import java.util.List;
import com.google.common.collect.ImmutableList;
/**
* Flexible Color Comparator that provides color comparisons using any combination of the attributes HLSB (hue, lumance,
* saturation, brightness) rather than RGB (red,green, blue).
*
* @author lopeznr1
*/
public class ColorHSBLCompartor implements Comparator<ColorHSBL>
{
// Constants
private static ImmutableList<KeyAttr> SortKey_HLB = ImmutableList.of(KeyAttr.Hue, KeyAttr.Luminance,
KeyAttr.Brightness);
// Attributes
private final List<KeyAttr> keyL;
private final int numGroups;
/**
* Standard Constructor
*
* @param aKeyL
* Defines an ordered list of {@link KeyAttr}s that will define how colors are sorted.
* @param aNumGroups
* Defines the number of groups for which the various color attributes will be grouped to.
*/
public ColorHSBLCompartor(List<KeyAttr> aKeyL, int aNumGroups)
{
keyL = ImmutableList.copyOf(aKeyL);
numGroups = aNumGroups;
}
/**
* Simplified Constructor
*
* Colors will be sorted by the following ordered attributes: hue, lumance, and brightness.
*
* @param aNumGroups
* Defines the number of groups for which the various color attributes will be grouped to.
*/
public ColorHSBLCompartor(int aNumGroups)
{
this(SortKey_HLB, aNumGroups);
}
@Override
public int compare(ColorHSBL aHsbl1, ColorHSBL aHsbl2)
{
int prevStep = 0;
// Iterate through all of the keys
int tmpIdx = -1;
for (KeyAttr aKey : keyL)
{
tmpIdx++;
double fVal1, fVal2;
switch (aKey)
{
case Hue:
fVal1 = aHsbl1.getHue();
fVal2 = aHsbl2.getHue();
break;
case Saturation:
fVal1 = aHsbl1.getSaturation();
fVal2 = aHsbl2.getSaturation();
break;
case Brightness:
fVal1 = aHsbl1.getBrightness();
fVal2 = aHsbl2.getBrightness();
break;
case Luminance:
fVal1 = aHsbl1.getLuminance();
fVal2 = aHsbl2.getLuminance();
break;
default:
throw new UnsupportedOperationException("Unrecognized key: " + aKey);
}
// Compare the corresponding normalized (group) values
int iVal1 = (int) (fVal1 * numGroups);
int iVal2 = (int) (fVal2 * numGroups);
int cmpVal = Integer.compare(iVal1, iVal2);
// If we are at the last key - do not use the normalize (group) values
// but rather utilize the non-normalized raw float values so as to
// reduce (eliminate?) ambiguities due to values being in the same bin.
if (tmpIdx == keyL.size() - 1)
cmpVal = Double.compare(fVal1, fVal2);
// Note we flip the comparison if the previous (key) comparison
// resulted in an odd value. We do this so that rather than having
// a number of step function we get more of an oscillating smooth
// transition between the comparison keys.
if (prevStep % 2 == 1)
cmpVal = -cmpVal;
if (cmpVal != 0)
return cmpVal;
prevStep = iVal1;
}
return 0;
}
}

View File

@@ -0,0 +1,261 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.color;
import java.awt.Color;
import java.util.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.google.common.collect.ImmutableList;
import glum.gui.misc.BooleanCellEditor;
import glum.gui.misc.BooleanCellRenderer;
import glum.gui.panel.itemList.*;
import glum.gui.panel.itemList.query.QueryComposer;
import glum.gui.table.ColorHSBLCellRenderer;
import glum.gui.table.PrePendRenderer;
import net.miginfocom.swing.MigLayout;
/**
* Demo application that demonstrates a number of features:
* <ul>
* <li>Showing color attributes via a table
* <li>Alternative color sorting
* <li>Multicolmun sorting
* </ul>
*
* @author lopeznr1
*/
public class ColorTestApp
{
// Constants
private static final int DefNumGroups = 8;
// private static final int DefNumItems = 100; // 3100
private static final int DefNumItems = 3100;
/**
* Main entry point.
*/
public static void main(String[] args)
{
JFrame frame = new JFrame("TableColorTest");
frame.setContentPane(formTestPanel(DefNumGroups, DefNumItems));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static JPanel formTestPanel(int aNumGroups, int aNumItems)
{
ItemListPanel<TestItem, LookUp> tmpILP;
JPanel retPanel = new JPanel(new MigLayout());
// Table Content
QueryComposer<LookUp> tmpComposer = new QueryComposer<>();
tmpComposer.addAttribute(LookUp.IsVisible, Boolean.class, "Show", 50);
tmpComposer.addAttribute(LookUp.Index, Integer.class, "ID", "Trk: 99");
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "HBL", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "HLB", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "HLS", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "HSB", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "HSL", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "SBH", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "SBL", 50);
tmpComposer.addAttribute(LookUp.HSBL, Color.class, "SLB", 50);
tmpComposer.addAttribute(LookUp.Message, String.class, "Message", null);
tmpComposer.addAttribute(LookUp.Red, Integer.class, "Red", 40);
tmpComposer.addAttribute(LookUp.Green, Integer.class, "Green", 40);
tmpComposer.addAttribute(LookUp.Blue, Integer.class, "Blue", 40);
tmpComposer.addAttribute(LookUp.Hue, Integer.class, "Hue:" + aNumGroups, 60);
tmpComposer.addAttribute(LookUp.Sat, Integer.class, "Sat:" + aNumGroups, 60);
tmpComposer.addAttribute(LookUp.Lum, Integer.class, "Lum:" + aNumGroups, 60);
tmpComposer.addAttribute(LookUp.Bri, Integer.class, "Bri:" + aNumGroups, 60);
tmpComposer.setEditor(LookUp.IsVisible, new BooleanCellEditor());
tmpComposer.setRenderer(LookUp.IsVisible, new BooleanCellRenderer());
tmpComposer.setRenderer(LookUp.Index, new PrePendRenderer("Trk: "));
tmpComposer.setRenderer(LookUp.HSBL, new ColorHSBLCellRenderer(false));
// KeyType[] sortKeyArr = {KeyType.Hue, KeyType.Saturation, KeyType.Luminance};
List<KeyAttr> sortKeyL_HBL = ImmutableList.of(KeyAttr.Hue, KeyAttr.Brightness, KeyAttr.Luminance);
List<KeyAttr> sortKeyL_HLB = ImmutableList.of(KeyAttr.Hue, KeyAttr.Luminance, KeyAttr.Brightness);
List<KeyAttr> sortKeyL_HLS = ImmutableList.of(KeyAttr.Hue, KeyAttr.Luminance, KeyAttr.Saturation);
List<KeyAttr> sortKeyL_HSB = ImmutableList.of(KeyAttr.Hue, KeyAttr.Saturation, KeyAttr.Brightness);
List<KeyAttr> sortKeyL_HSL = ImmutableList.of(KeyAttr.Hue, KeyAttr.Saturation, KeyAttr.Luminance);
List<KeyAttr> sortKeyL_SBH = ImmutableList.of(KeyAttr.Saturation, KeyAttr.Brightness, KeyAttr.Hue);
List<KeyAttr> sortKeyL_SBL = ImmutableList.of(KeyAttr.Saturation, KeyAttr.Brightness, KeyAttr.Luminance);
List<KeyAttr> sortKeyL_SLB = ImmutableList.of(KeyAttr.Saturation, KeyAttr.Luminance, KeyAttr.Brightness);
ItemHandler<TestItem, LookUp> tmpIH = new TestItemHandler(aNumGroups);
StaticItemProcessor<TestItem> tmpIP = new StaticItemProcessor<>(formTestItemList(aNumItems));
tmpILP = new ItemListPanel<>(tmpIH, tmpIP, tmpComposer, true);
tmpILP.setSortingEnabled(true);
// tmpILP.setSortComparator(ColorHSBL.class, new ColorStepSortCompartor(numGroups));
tmpILP.setSortComparator(2, new ColorHSBLCompartor(sortKeyL_HBL, aNumGroups));
tmpILP.setSortComparator(3, new ColorHSBLCompartor(sortKeyL_HLB, aNumGroups));
tmpILP.setSortComparator(4, new ColorHSBLCompartor(sortKeyL_HLS, aNumGroups));
tmpILP.setSortComparator(5, new ColorHSBLCompartor(sortKeyL_HSB, aNumGroups));
tmpILP.setSortComparator(6, new ColorHSBLCompartor(sortKeyL_HSL, aNumGroups));
tmpILP.setSortComparator(7, new ColorHSBLCompartor(sortKeyL_SBH, aNumGroups));
tmpILP.setSortComparator(8, new ColorHSBLCompartor(sortKeyL_SBL, aNumGroups));
tmpILP.setSortComparator(9, new ColorHSBLCompartor(sortKeyL_SLB, aNumGroups));
// JTable tmpTable = lidarILP.getTable();
// tmpTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// retPanel.add(new JScrollPane(tmpTable), "growx,growy,pushx,pushy,span,wrap");
retPanel.add(tmpILP, "growx,growy,pushx,pushy,span,wrap");
tmpIP.setItems(formTestItemList(aNumItems));
return retPanel;
}
/**
* Helper method that forms the list of TestItems.
*/
private static List<TestItem> formTestItemList(int aNumItems)
{
List<TestItem> retL = new ArrayList<>();
Random tmpRandom = new Random(100);
for (int c1 = 0; c1 < aNumItems; c1++)
{
int r = tmpRandom.nextInt(256);
int g = tmpRandom.nextInt(256);
int b = tmpRandom.nextInt(256);
Color tmpColor = new Color(r, g, b);
String tmpMsg = String.format("Color: %3d %3d %3d", r, g, b);
retL.add(new TestItem(c1, tmpColor, tmpMsg));
}
return retL;
}
enum LookUp
{
IsVisible,
Index,
Color,
HSBL,
Message,
Red,
Green,
Blue,
Hue,
Sat,
Lum,
Bri
}
static class TestItem
{
// Attributes
private final int index;
private final Color color;
private final String message;
// Cache vars
private final ColorHSBL cHSBL;
// State vars
private boolean isVisible;
public TestItem(int aIndex, Color aColor, String aMessage)
{
index = aIndex;
color = aColor;
message = aMessage;
cHSBL = new ColorHSBL(color);
isVisible = true;
}
}
static class TestItemHandler implements ItemHandler<TestItem, LookUp>
{
// Attributes
private final int numGroups;
/** Standard Constructor */
public TestItemHandler(int aNumGroups)
{
numGroups = aNumGroups;
}
@Override
public Object getValue(TestItem aItem, LookUp aEnum)
{
switch (aEnum)
{
case IsVisible:
return aItem.isVisible;
case Index:
return aItem.index;
case Color:
return aItem.color;
case HSBL:
return aItem.cHSBL;
case Message:
return aItem.message;
case Red:
return aItem.color.getRed();
case Green:
return aItem.color.getGreen();
case Blue:
return aItem.color.getBlue();
case Hue:
return (int) (aItem.cHSBL.getHue() * numGroups);
case Sat:
return (int) (aItem.cHSBL.getSaturation() * numGroups);
case Bri:
return (int) (aItem.cHSBL.getBrightness() * numGroups);
case Lum:
return (int) (aItem.cHSBL.getLuminance() * numGroups);
default:
break;
}
throw new UnsupportedOperationException("Column is not supported. Enum: " + aEnum);
}
@Override
public void setValue(TestItem aItem, LookUp aEnum, Object aValue)
{
if (aEnum == LookUp.IsVisible)
aItem.isVisible = (Boolean) aValue;
else
throw new UnsupportedOperationException("Column is not supported. Enum: " + aEnum);
}
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.color;
/**
* Enum that defines the different attributes associated with Colors.
*
* @author lopeznr1
*/
public enum KeyAttr
{
Hue,
Saturation,
Brightness,
Luminance,
}

View File

@@ -1,95 +0,0 @@
package glum.coord;
/**
* Contains conversion multipliers to/from feet, yards, meters, data miles, and nautical miles, as well as angular
* values to/from degrees and radians. To convert a value <code>X</code> in units of <code>U</code> to units of
* <code>V</code>, use <code>X * Convert.U_TO_V</code>.
*/
public class Convert
{
public static final double FEET_TO_METERS = 0.3048;
public static final double DM_TO_METERS = 1828.8;
public static final double NM_TO_METERS = 1852.0;
public static final double MILES_TO_METERS = 1609.344;
public static final double YARDS_TO_METERS = 0.9144; // 3 * FEET_TO_METERS
public static final double METERS_TO_FEET = 1.0 / FEET_TO_METERS;
public static final double DM_TO_FEET = 6000.0;
public static final double NM_TO_FEET = NM_TO_METERS * METERS_TO_FEET;
public static final double MILES_TO_FEET = 5280.0;
public static final double YARDS_TO_FEET = 3.0;
public static final double METERS_TO_DM = 1.0 / DM_TO_METERS;
public static final double FEET_TO_DM = FEET_TO_METERS * METERS_TO_DM;
public static final double NM_TO_DM = NM_TO_METERS * METERS_TO_DM;
public static final double MILES_TO_DM = MILES_TO_METERS * METERS_TO_DM;
public static final double YARDS_TO_DM = YARDS_TO_METERS * METERS_TO_DM;
public static final double METERS_TO_NM = 1.0 / NM_TO_METERS;
public static final double FEET_TO_NM = FEET_TO_METERS * METERS_TO_NM;
public static final double DM_TO_NM = DM_TO_METERS * METERS_TO_NM;
public static final double MILES_TO_NM = MILES_TO_METERS * METERS_TO_NM;
public static final double YARDS_TO_NM = YARDS_TO_METERS * NM_TO_METERS;
public static final double METERS_TO_MILES = 1.0 / MILES_TO_METERS;
public static final double FEET_TO_MILES = FEET_TO_METERS * METERS_TO_MILES;
public static final double DM_TO_MILES = DM_TO_METERS * METERS_TO_MILES;
public static final double NM_TO_MILES = NM_TO_METERS * METERS_TO_MILES;
public static final double YARDS_TO_MILES = YARDS_TO_METERS * METERS_TO_MILES;
public static final double METERS_TO_YARDS = 1.0 / YARDS_TO_METERS;
public static final double FEET_TO_YARDS = 1.0 / 3.0;
public static final double DM_TO_YARDS = 2000.0;
public static final double NM_TO_YARDS = NM_TO_METERS * METERS_TO_YARDS;
public static final double MILES_TO_YARDS = 1760.0;
public static final double RAD_TO_DEG = 180.0 / Math.PI;
public static final double DEG_TO_RAD = Math.PI / 180.0;
public static final double SECS_TO_MSECS = 1000.0;
public static final double MSECS_TO_SECS = 1.0 / SECS_TO_MSECS;
public static final int MINS_TO_SECS = 60;
public static final int HOURS_TO_MINS = 60;
public static final int HOURS_TO_SECS = HOURS_TO_MINS * MINS_TO_SECS;
public static final double SECS_TO_MINS = 1 / MINS_TO_SECS;
public static final double MINS_TO_HOURS = 1 / HOURS_TO_MINS;
public static final double SECS_TO_HOURS = 1 / HOURS_TO_SECS;
/**
* Constructor
*/
private Convert()
{
}
/**
* Converts an angle to a bearing
*/
public static double angleToBearing(double aAngle)
{
double bearing;
bearing = 180 - (aAngle + 90);
if (bearing < 0)
bearing += 360;
return bearing;
}
/**
* Converts a bearing to an angle
*/
public static double bearingToAngle(double aBearing)
{
double angle;
angle = 180 - (aBearing + 90);
if (angle < 0)
angle += 360;
return angle;
}
}

View File

@@ -1,197 +0,0 @@
package glum.coord;
/** Provides a few useful functions on coordinates, such as converting
* to a user-presentable string.
*/
public class CoordUtil
{
/** Convert a Lat/Lon to a pair of DEG:MM:SS H strings. H is the
* hemisphere, N or S for lat, E or W for lon. The default separator
* string LL_SEP is used.
*/
public static String LatLonToString (LatLon ll)
{
return ll == null ? "" : LatLonToString (ll, LL_SEP);
}
/** Same as the other LatLonToString, excepts this one uses the
* given <code>sep</code> string to separate the Lat and Lon.
*/
public static String LatLonToString (LatLon ll, String sep)
{
return ll == null ? "" :
LatToString (ll.lat) + LL_SEP + LonToString (ll.lon);
}
/** Converts the given <code>lat</code> to DD:MM:SS H. */
public static String LatToString (double lat)
{
return LatToString (lat, true);
}
/** Converts the given <code>lat</code> to DD:MM:SS H if
* <code>include_seconds</code> is true. If it's false, then the
* :SS part is left off.
*/
public static String LatToString (double lat, boolean include_seconds)
{
DMS dms = new DMS (lat);
StringBuffer s = new StringBuffer();
if ( dms.degrees < 10 )
s.append ("0");
s.append (dms.degrees);
s.append (":");
if ( dms.minutes < 10 )
s.append ("0");
s.append (dms.minutes);
if ( include_seconds )
{
s.append (":");
if ( dms.seconds < 10 )
s.append ("0");
s.append (dms.seconds);
}
s.append (lat >= 0 ? " N" : " S");
return s.toString();
}
/** Similar to <code>LatToString</code> except that the degrees
* part is DDD instead of DD. */
public static String LonToString (double lon)
{
return LonToString (lon, true);
}
/** Similar to <code>LatToString</code> except that the degrees
* part is DDD instead of DD. */
public static String LonToString (double lon, boolean include_seconds)
{
DMS dms = new DMS (lon);
StringBuffer s = new StringBuffer();
if ( dms.degrees < 100 )
s.append ("0");
if ( dms.degrees < 10 )
s.append ("0");
s.append (dms.degrees);
s.append (":");
if ( dms.minutes < 10 )
s.append ("0");
s.append (dms.minutes);
if ( include_seconds )
{
s.append (":");
if ( dms.seconds < 10 )
s.append ("0");
s.append (dms.seconds);
}
s.append (lon >= 0 ? " E" : " W");
return s.toString();
}
/** Converts <code>dmsh_string</code> to a double value.
* The string format should match the output of the
* LatToString formats, including hemisphere.
* If a hemisphere character is not part of the string, the
* returned value will be non-negative.
*/
public static double StringToLat (String dmsh_string)
{
if ( dmsh_string == null || dmsh_string.length() == 0 )
return 0.0;
int dms [] = StringToDMS (dmsh_string);
if ( dms.length == 3 )
return new Degrees (dms[0], dms[1], dms[2]).degrees;
else return 0.0;
}
/** {@see StringToLat} */
public static double StringToLon (String dmsh_string)
{
// Because we aren't doing any range or hemisphere error
// checking, a lon value is identical to a lat value.
return StringToLat (dmsh_string);
}
/** Converts <code>dmsh_string</code> to a an array of
* 3 ints representing degrees, minutes, and seconds.
* if a hemisphere character is present (one of NSEW or
* nsew), and it represents a souther or western hemisphere,
* then the degrees value, in index 0 of the returned array,
* will be a non-positive number.
*/
public static int [] StringToDMS (String dmsh_string)
{
if ( dmsh_string == null || dmsh_string.length() == 0 )
return null;
char chars [] = dmsh_string.toCharArray();
int dms [] = new int [ 3 ];
dms[0] = 0;
for ( int i = 0, j = 0; i < chars.length; i++ )
{
char c = chars[i];
if ( c == ' ' || c == ' ' ) // Space or tab.
continue;
else if ( c >= '0' && c <= '9' && j < 3 )
dms[j] = dms[j] * 10 + c - '0';
else if ( c == ':' )
{
j++;
dms[j] = 0;
}
else if ( c == 'S' || c == 's' || c == 'W' || c == 'w' )
dms[0] = -dms[0];
}
return dms;
}
public static class DMS
{
public DMS (double deg)
{
if ( deg < 0 ) deg = -deg;
degrees = (int) deg;
minutes = (int) (deg * 60) % 60;
seconds = (int) (deg * 3600) % 60;
}
public int degrees, minutes, seconds;
}
public static class Degrees
{
public Degrees (int deg, int min, int sec)
{
degrees = Math.abs (deg) +
Math.abs(min) / 60.0 +
Math.abs(sec) / 3600.0;
if ( deg < 0 || min < 0 || sec < 0 )
degrees = -degrees;
}
public Degrees (int deg, int min, int sec, char hemisphere)
{
this (deg, min, sec);
if ( hemisphere == 'N' || hemisphere == 'n' ||
hemisphere == 'E' || hemisphere == 'e' )
degrees = Math.abs (degrees);
else if ( hemisphere == 'S' || hemisphere == 's' ||
hemisphere == 'W' || hemisphere == 'w' )
degrees = -Math.abs (degrees);
}
public double degrees;
}
public static String LL_SEP = " / ";
}

View File

@@ -1,43 +0,0 @@
package glum.coord;
/** Determines if two numbers are close, usually as a way to say
* that they are equal. Close is defined to mean that their difference
* is less than some small number, which is either supplied by the caller
* or is EPSILON.
* <p>For longitude near the equator, a difference of EPSILON is about
* 3.65 feet (where the earth's circumference is about 21913.3 DM, or
* about 60.87 DM per degree longitude). For DataMile measurements, it's
* about 0.72 inches.
*/
public class Epsilon
{
/** The measure of closeness; set to 0.00001. */
public static final double EPSILON = 0.00001;
public static boolean close (float a, float b)
{
float diff = a - b;
return diff < EPSILON && diff > -EPSILON;
}
public static boolean close (float a, float b, float epsilon)
{
float diff = a - b;
return diff < epsilon && diff > -epsilon;
}
public static boolean close (double a, double b)
{
double diff = a - b;
return diff < EPSILON && diff > -EPSILON;
}
public static boolean close (double a, double b, float epsilon)
{
double diff = a - b;
return diff < EPSILON && diff > -EPSILON;
}
private Epsilon () { }
}

View File

@@ -1,97 +0,0 @@
package glum.coord;
/**
* Contains a collection of utility methods to perform linear algebra using the objects from this package.
*/
public class GeoUtil
{
/**
* realSqr returns aNum*aNum
*/
public static double realSqr(double aNum)
{
return aNum * aNum;
}
/**
* computeDotProduct - Returns the dot product of vector1 and vector2
*/
public static double computeDotProduct(Point3D vector1, Point3D vector2)
{
return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z;
}
/**
* computeDistance - Returns the distance between pt1 and pt2
*/
public static double computeDistance(Point3D pt1, Point3D pt2)
{
return Math.sqrt(realSqr(pt1.x - pt2.x) + realSqr(pt1.y - pt2.y) + realSqr(pt1.z - pt2.z));
}
/**
* computeDistanceSquare - Returns the squared distance between pt1 and pt2
*/
public static double computeDistanceSquare(Point3D pt1, Point3D pt2)
{
return realSqr(pt1.x - pt2.x) + realSqr(pt1.y - pt2.y) + realSqr(pt1.z - pt2.z);
}
/**
* computeLength - Returns the magnitude of aVector
*/
public static double computeLength(Point3D aVector)
{
return Math.sqrt(realSqr(aVector.x) + realSqr(aVector.y) + realSqr(aVector.z));
}
/**
* computeNormal - Returns the R.H.R normal defined by the 3 points
*/
public static void computeNormal(Point3D pt1, Point3D pt2, Point3D pt3, Point3D aNormal)
{
Point3D vector1, vector2;
vector1 = new Point3D();
vector2 = new Point3D();
computeVector(pt1, pt3, vector1);
computeVector(pt3, pt2, vector2);
// ! Not sure why I have to negate all the values; Need to refer to linear alg.
//! aNormal.x = vector1.y*vector2.z - vector1.z*vector2.y;
//! aNormal.y = vector1.z*vector2.x - vector1.x*vector2.z;
//! aNormal.z = vector1.x*vector2.y - vector1.y*vector2.x;
aNormal.x = -(vector1.y * vector2.z - vector1.z * vector2.y);
aNormal.y = -(vector1.z * vector2.x - vector1.x * vector2.z);
aNormal.z = -(vector1.x * vector2.y - vector1.y * vector2.x);
// Normalize the vector
normalizeVector(aNormal);
}
/**
* computeVector - Returns the vector defined by the 2 points
*/
public static void computeVector(Point3D pt1, Point3D pt2, Point3D aVector)
{
aVector.x = pt2.x - pt1.x;
aVector.y = pt2.y - pt1.y;
aVector.z = pt2.z - pt1.z;
}
/**
* normalizeVector - Normalizes aVector so that its length is 1
*/
public static void normalizeVector(Point3D aVector)
{
double length;
length = computeLength(aVector);
// Normalize the vector
aVector.x = aVector.x / length;
aVector.y = aVector.y / length;
aVector.z = aVector.z / length;
}
}

View File

@@ -1,111 +0,0 @@
package glum.coord;
/** Simple class for Lat/Lon values. */
public class LatLon
{
public double lat;
public double lon;
public LatLon()
{
}
public LatLon(LatLon latlon)
{
if (latlon != null)
{
lat = latlon.lat;
lon = latlon.lon;
}
}
public LatLon(double lat, double lon)
{
this.lat = lat;
this.lon = lon;
}
public LatLon(String lat_string, String lon_string)
{
set(lat_string, lon_string);
}
public void set(double lat, double lon)
{
this.lat = lat;
this.lon = lon;
}
public void set(LatLon latlon)
{
if (latlon != null)
{
lat = latlon.lat;
lon = latlon.lon;
}
}
public void set(String lat_string, String lon_string)
{
lat = CoordUtil.StringToLat(lat_string);
lon = CoordUtil.StringToLon(lon_string);
}
public void normalize()
{
if (lat > 90)
lat = 90;
else if (lat < -90)
lat = -90;
if (lon > 180)
lon -= 360;
else if (lon < -180)
lon += 360;
}
/**
* Tests to see if the given object is the same lat/lon as this position.
* "Same" really means "very, very close," as defined by {@link Epsilon}.
*
* @return True if obj is a LatLon and is very close to our lat/lon position.
* False otherwise.
*/
@Override
public boolean equals(Object obj)
{
return (obj instanceof LatLon) && Epsilon.close(lat, ((LatLon)obj).lat) && Epsilon.close(lon, ((LatLon)obj).lon);
}
@Override
public String toString()
{
return CoordUtil.LatLonToString(this);
}
/**
* Returns the change in latitude
*/
static public double computeDeltaLat(double lat1, double lat2)
{
return lat2 - lat1;
}
/**
* Returns the change in longitude
*/
static public double computeDeltaLon(double lon1, double lon2)
{
double dLon;
dLon = lon2 - lon1;
if (Math.abs(dLon) < 180)
return dLon;
if (dLon > 180)
return dLon - 360;
else
return dLon + 360;
}
}

View File

@@ -1,37 +0,0 @@
package glum.coord;
public class Point2D
{
public double x;
public double y;
public Point2D () { }
public Point2D (Point2D pt)
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
public Point2D (double x, double y)
{ this.x = x; this.y = y; }
public void set (double x, double y)
{ this.x = x; this.y = y; }
public void set (Point2D pt)
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
public double distance (Point2D aPt)
{
if (aPt == null)
return 0;
return Math.sqrt((aPt.x - x)*(aPt.x - x) + (aPt.y - y)*(aPt.y - y));
}
@Override
public boolean equals (Object obj)
{
return (obj instanceof Point2D) &&
Epsilon.close (x, ((Point2D) obj).x) &&
Epsilon.close (y, ((Point2D) obj).y);
}
}

View File

@@ -1,27 +0,0 @@
package glum.coord;
public class Point2Di
{
public int x;
public int y;
public Point2Di () { }
public Point2Di (Point2Di pt)
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
public Point2Di (int x, int y) { this.x = x; this.y = y; }
public void set (int x, int y) { this.x = x; this.y = y; }
public void set (Point2Di pt)
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
@Override
public boolean equals (Object obj)
{
return (obj instanceof Point2Di) &&
x == ((Point2Di) obj).x &&
y == ((Point2Di) obj).y;
}
}

View File

@@ -1,42 +0,0 @@
package glum.coord;
/** A class for representing any 3-Dimensional vector, which could be
* a position, a velocity, or a rotation. No information about units
* is assumed or implied.
*/
public class Point3D
{
public double x;
public double y;
public double z;
public Point3D () { }
public Point3D (Point3D pt)
{ if ( pt != null ) { x = pt.x; y = pt.y; z = pt.z; } }
public Point3D (double x, double y, double z)
{ this.x = x; this.y = y; this.z = z; }
public void set (double x, double y, double z)
{ this.x = x; this.y = y; this.z = z; }
public void set (Point3D pt)
{ if ( pt != null ) { x = pt.x; y = pt.y; z = pt.z; } }
@Override
public boolean equals (Object obj)
{
return (obj instanceof Point3D) &&
Epsilon.close (x, ((Point3D) obj).x) &&
Epsilon.close (y, ((Point3D) obj).y) &&
Epsilon.close (z, ((Point3D) obj).z);
}
@Override
public String toString()
{
return new String("(" + x + ", " + y + ", " + z + ")");
}
}

View File

@@ -1,47 +0,0 @@
package glum.coord;
public class RngBrg
{
public double rng;
public double brg;
public RngBrg() { }
public RngBrg(RngBrg pt)
{
if ( pt != null )
{
rng = pt.rng;
brg = pt.brg;
}
}
public RngBrg (double rng, double brg)
{
this.rng = rng;
this.brg = brg;
}
public void set (double rng, double brg)
{
this.rng = rng;
this.brg = brg;
}
public void set (RngBrg pt)
{
if ( pt != null )
{
rng = pt.rng;
brg = pt.brg;
}
}
@Override
public boolean equals (Object obj)
{
return (obj instanceof RngBrg) &&
Epsilon.close (rng, ((RngBrg) obj).rng) &&
Epsilon.close (brg, ((RngBrg) obj).brg);
}
}

View File

@@ -1,26 +0,0 @@
package glum.coord;
public class UV extends Point2D
{
public UV ()
{
x = 0;
y = 0;
}
public UV (Point2D pt)
{
if (pt != null)
{
x = pt.x;
y = pt.y;
}
}
public UV (double x, double y)
{
this.x = x;
this.y = y;
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.database;
public abstract interface QueryItem<G1 extends Enum<?>>

View File

@@ -1,11 +1,31 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.database;
import java.util.Comparator;
/**
* {@link Comparable} to sort {@link QueryItem}s based on the provided key.
*
* @author lopeznr1
*/
public class QueryItemComparator<G1 extends QueryItem<G2>, G2 extends Enum<?>> implements Comparator<G1>
{
private G2 sortKey;
// Attributes
private final G2 sortKey;
/** Standard Constructor */
public QueryItemComparator(G2 aSortKey)
{
sortKey = aSortKey;
@@ -15,10 +35,8 @@ public class QueryItemComparator<G1 extends QueryItem<G2>, G2 extends Enum<?>> i
@Override
public int compare(G1 item1, G1 item2)
{
Comparable<Object> value1, value2;
value1 = (Comparable<Object>)item1.getValue(sortKey);
value2 = (Comparable<Object>)item2.getValue(sortKey);
var value1 = (Comparable<Object>) item1.getValue(sortKey);
var value2 = (Comparable<Object>) item2.getValue(sortKey);
if (value1 == null && value2 == null)
return 0;
@@ -34,29 +52,23 @@ public class QueryItemComparator<G1 extends QueryItem<G2>, G2 extends Enum<?>> i
/**
* Utility method to create a QueryItemComparator by specifying the class and sort Enum.
* <P>
* <p>
* This logic is here due to Java's horrible implementation off generics.
*/
public static <G3 extends QueryItem<G4>, G4 extends Enum<?>> Comparator<G3> spawn(Class<G3> aClass, G4 aEnum)
{
QueryItemComparator<G3, G4> retComparator;
retComparator = new QueryItemComparator<G3, G4>(aEnum);
return retComparator;
return new QueryItemComparator<G3, G4>(aEnum);
}
/**
* Utility method to create a QueryItemComparator by specifying just the Enum. Note this method can not be used in a
* argument to another method; instead use: {@link #spawn(Class, Enum)}
* <P>
* <p>
* This logic is here due to Java's horrible implementation off generics.
*/
public static <G3 extends QueryItem<G4>, G4 extends Enum<?>> Comparator<G3> spawn(G4 aEnum)
{
QueryItemComparator<G3, G4> retComparator;
retComparator = new QueryItemComparator<G3, G4>(aEnum);
return retComparator;
return new QueryItemComparator<G3, G4>(aEnum);
}
}

101
src/glum/digest/Digest.java Normal file
View File

@@ -0,0 +1,101 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.digest;
import java.util.Arrays;
/**
* Immutable object that stores a single digest.
*
* @author lopeznr1
*/
public class Digest
{
private final DigestType digestType;
private final byte[] digestValueArr;
public Digest(DigestType aDigestType, byte[] aDigestValueArr)
{
digestType = aDigestType;
digestValueArr = Arrays.copyOf(aDigestValueArr, aDigestValueArr.length);
}
public Digest(DigestType aDigestType, String aHexStr)
{
digestType = aDigestType;
digestValueArr = DigestUtils.hexStr2ByteArr(aHexStr);
}
/**
* Returns a user friendly description (string) of this digest result.
* <p>
* The result will be DigestType:hexDigestValue
*/
public String getDescr()
{
return "" + digestType + ":" + getValueAsString();
}
/**
* Returns the DigestType associated with this Digest.
*/
public DigestType getType()
{
return digestType;
}
/**
* Returns the actual digest (as a string) associated with this Digest.
*/
public byte[] getValue()
{
return Arrays.copyOf(digestValueArr, digestValueArr.length);
}
/**
* Returns the actual digest (as a string) associated with this Digest.
*/
public String getValueAsString()
{
return DigestUtils.byteArr2HexStr(digestValueArr);
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((digestType == null) ? 0 : digestType.hashCode());
result = prime * result + Arrays.hashCode(digestValueArr);
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Digest other = (Digest) obj;
if (digestType != other.digestType)
return false;
if (!Arrays.equals(digestValueArr, other.digestValueArr))
return false;
return true;
}
}

View File

@@ -0,0 +1,64 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.digest;
/**
* Enum that defines the supported digest types.
*
* @author lopeznr1
*/
public enum DigestType
{
// Weak digest - but very fast
MD5("MD5"),
// Fairly strong digest type (with good performance on 32 bit machines)
SHA256("SHA-256"),
// Very strong digest type
SHA512("SHA-512");
// State vars
private String algName;
private DigestType(String aAlgName)
{
algName = aAlgName;
}
/**
* Returns the official digest algorithm name.
*
* @see http://docs.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html#AppA
*/
public String getAlgName()
{
return algName;
}
/**
* Returns the corresponding DigestType.
*/
public static DigestType parse(String aStr)
{
if (aStr.equalsIgnoreCase("MD5") == true)
return MD5;
if (aStr.equalsIgnoreCase("SHA256") == true)
return SHA256;
if (aStr.equalsIgnoreCase("SHA512") == true)
return SHA512;
return null;
}
}

View File

@@ -0,0 +1,83 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.digest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.google.common.io.BaseEncoding;
/**
* Collection of utility methods to ease working with the MessageDigest and associated classes.
*
* @author lopeznr1
*/
public class DigestUtils
{
/**
* Utility method that will throw a RuntimeExcepption if the specified digest function is not found.
* <p>
* Algorithm should be MD5, SHA-256, SHA-512, ...
* <p>
* See: http://docs.oracle.com/javase/1.8.0/docs/guide/security/CryptoSpec.html#AppA
*/
public static MessageDigest getDigest(String aAlgorithm)
{
MessageDigest retDigest;
try
{
retDigest = MessageDigest.getInstance(aAlgorithm);
}
catch (NoSuchAlgorithmException aExp)
{
throw new RuntimeException("Digest not found. Digest algorith not found: " + aAlgorithm);
}
return retDigest;
}
/**
* Utility method that will throw a RuntimeExcepption if the specified digest function is not found.
* <p>
* See: http://docs.oracle.com/javase/1.8.0/docs/guide/security/CryptoSpec.html#AppA
*/
public static MessageDigest getDigest(DigestType aDigestType)
{
return getDigest(aDigestType.getAlgName());
}
/**
* Utility method that returns the (lower case) hex string corresponding to the byte array.
* <p>
* Delegates to {@link BaseEncoding.base16().lowerCase().encode(CharSequence)}
*/
public static String byteArr2HexStr(byte[] aByteArr)
{
String retStr = BaseEncoding.base16().lowerCase().encode(aByteArr);
return retStr;
}
/**
* Utility method that returns a byte array corresponding to the hex string.
* <p>
* Delegates to {@link BaseEncoding.base16().lowerCase().decode(CharSequence)}
*/
public static byte[] hexStr2ByteArr(String aHexStr)
{
byte[] retArr = BaseEncoding.base16().lowerCase().decode(aHexStr);
return retArr;
}
}

View File

@@ -1,35 +1,50 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.filter;
import java.io.IOException;
import java.util.*;
import glum.zio.*;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* A {@link Filter} which performs filtering based on a enam values.
*
* @author lopeznr1
*
* @param <G1>
*/
public abstract class EnumFilter<G1, G2 extends Enum<?>> implements ZioObj, Filter<G1>
{
// Static config vars
private Map<Integer, Enum<?>> fullMap;
// State vars
private Set<Enum<?>> validSet;
private Set<Enum<?>> validS;
private boolean isEnabled;
/** Standard Constructor */
public EnumFilter(Class<? extends Enum<?>> enumClass)
{
fullMap = Maps.newLinkedHashMap();
fullMap = new LinkedHashMap<>();
for (Enum<?> aEnum : enumClass.getEnumConstants())
fullMap.put(aEnum.ordinal(), aEnum);
validSet = Sets.newLinkedHashSet();
validS = new LinkedHashSet<>();
isEnabled = false;
}
/**
* Returns true if the filter is active.
*/
@@ -43,7 +58,7 @@ public abstract class EnumFilter<G1, G2 extends Enum<?>> implements ZioObj, Filt
*/
public List<Enum<?>> getSelectedItems()
{
return Lists.newArrayList(validSet);
return new ArrayList<>(validS);
}
/**
@@ -51,10 +66,10 @@ public abstract class EnumFilter<G1, G2 extends Enum<?>> implements ZioObj, Filt
*/
public void set(EnumFilter<G1, G2> aFilter)
{
validSet = Sets.newLinkedHashSet(aFilter.validSet);
validS = new LinkedHashSet<>(aFilter.validS);
isEnabled = aFilter.getIsEnabled();
}
/**
* Sets whether the filter is active.
*/
@@ -62,57 +77,52 @@ public abstract class EnumFilter<G1, G2 extends Enum<?>> implements ZioObj, Filt
{
isEnabled = aBool;
}
/**
* Sets the list of valid enums for this filter.
*/
public void setSetSelectedItems(List<Enum<?>> selectedItems)
public void setSetSelectedItems(List<Enum<?>> aItemL)
{
validSet.clear();
validSet.addAll(selectedItems);
validS.clear();
validS.addAll(aItemL);
}
@Override
public void zioRead(ZinStream aStream) throws IOException
{
int numItems;
aStream.readVersion(0);
// Read the payload
isEnabled = aStream.readBool();
validSet.clear();
numItems = aStream.readInt();
validS.clear();
var numItems = aStream.readInt();
for (int c1 = 0; c1 < numItems; c1++)
validSet.add(fullMap.get(aStream.readInt()));
validS.add(fullMap.get(aStream.readInt()));
}
@Override
public void zioWrite(ZoutStream aStream) throws IOException
{
int numItems;
aStream.writeVersion(0);
aStream.writeBool(isEnabled);
numItems = validSet.size();
var numItems = validS.size();
aStream.writeInt(numItems);
for (Enum<?> aEnum : validSet)
for (Enum<?> aEnum : validS)
aStream.writeInt(aEnum.ordinal());
}
/**
* Utility method that returns whether aValue is within the constraints
* specified by this filter.
* Utility method that returns whether aValue is within the constraints specified by this filter.
*/
protected boolean testIsValid(G2 aEnum)
{
if (isEnabled == false)
return true;
return validSet.contains(aEnum);
return validS.contains(aEnum);
}
}

View File

@@ -1,7 +1,27 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.filter;
import glum.zio.ZioObj;
/**
* Interface that provides a mechanism for filtering items.
*
* @author lopeznr1
*
* @param <G1>
*/
public interface Filter<G1> extends ZioObj
{
/**

View File

@@ -1,14 +1,31 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.filter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import com.google.common.collect.Lists;
import glum.gui.component.GList;
import glum.gui.component.GNumberField;
/**
* Collection of utility methods used to aide with working with {@link Filter}s and (swing) UI components.
*
* @author lopeznr1
*/
public class FilterUtil
{
/**
@@ -16,16 +33,14 @@ public class FilterUtil
*/
public static <G1> List<G1> applyFilter(List<G1> itemList, Filter<G1> aFilter)
{
List<G1> retList;
retList = Lists.newArrayList();
var retItemL = new ArrayList<G1>();
for (G1 aItem : itemList)
{
if (aFilter.isValid(aItem) == true)
retList.add(aItem);
retItemL.add(aItem);
}
return retList;
return retItemL;
}
/**
@@ -38,18 +53,19 @@ public class FilterUtil
}
/**
* Utility method to synchronize the associated GUI controls with the specified filter.
* Utility method to synchronize the associated GUI controls with the specified filter.
*/
public static void setEnumFilter(EnumFilter<?, Enum<?>> aFilter, JCheckBox mainCB, GList<Enum<?>> mainList)
{
mainCB.setSelected(aFilter.getIsEnabled());
mainList.setSelectedItems(aFilter.getSelectedItems());
}
/**
* Utility method to synchronize the specified filter with the associated GUI controls.
*/
public static void getRangeFilter(RangeFilter<?> aFilter, JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF, GNumberField maxNF)
public static void getRangeFilter(RangeFilter<?> aFilter, JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB,
GNumberField minNF, GNumberField maxNF)
{
aFilter.setIsEnabled(mainCB.isSelected());
aFilter.setUseMin(minCB.isSelected());
@@ -59,9 +75,10 @@ public class FilterUtil
}
/**
* Utility method to synchronize the associated GUI controls with the specified filter.
* Utility method to synchronize the associated GUI controls with the specified filter.
*/
public static void setRangeGui(RangeFilter<?> aFilter, JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF, GNumberField maxNF)
public static void setRangeGui(RangeFilter<?> aFilter, JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB,
GNumberField minNF, GNumberField maxNF)
{
mainCB.setSelected(aFilter.getIsEnabled());
minCB.setSelected(aFilter.getUseMin());
@@ -71,26 +88,23 @@ public class FilterUtil
}
/**
* Utility method to keep the various GUI components associated with an EnumFilter synchronized.
* The mainList will be enabled/disabled based on the selection state of mainCB.
* Utility method to keep the various GUI components associated with an EnumFilter synchronized. The mainList will be
* enabled/disabled based on the selection state of mainCB.
*/
public static void syncEnumGui(JCheckBox mainCB, GList<Enum<?>> mainList)
{
boolean isEnabled;
isEnabled = mainCB.isSelected();
var isEnabled = mainCB.isSelected();
mainList.setEnabled(isEnabled);
}
/**
* Utility method to keep the various GUI components associated with an RangeFilter synchronized.
* Gui components will be enabled/disabled based on the various check boxes.
* Utility method to keep the various GUI components associated with an RangeFilter synchronized. Gui components will
* be enabled/disabled based on the various check boxes.
*/
public static void syncRangeGui(JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF, GNumberField maxNF)
public static void syncRangeGui(JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF,
GNumberField maxNF)
{
boolean isEnabled;
isEnabled = mainCB.isSelected();
var isEnabled = mainCB.isSelected();
minCB.setEnabled(isEnabled);
maxCB.setEnabled(isEnabled);
minNF.setEnabled(isEnabled & minCB.isSelected());

View File

@@ -1,12 +1,29 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.filter;
import java.io.IOException;
import glum.zio.ZinStream;
import glum.zio.ZoutStream;
import java.io.IOException;
/**
* A Filter which does not filter anything. Thus the method isValid() always returns true.
* A {@link Filter} which does not filter anything. Thus the method isValid() always returns true.
*
* @author lopeznr1
*
* @param <G1>
*/
public class NullFilter<G1> implements Filter<G1>
{

View File

@@ -1,25 +1,39 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.filter;
import glum.zio.*;
import java.io.IOException;
import glum.zio.*;
/**
* Abstract filter which is used to filter a single value between the specified min/max ranges. The only code to write
* is the isValid() method and to call the appropriate Constructor. In the isValid() method, you should delegate filter
* logic to the method testIsValid() with the quantity of interest, and return the result from the method call.
* Abstract {@link Filter} which is used to filter a single value between the specified min/max ranges. The only code to
* write is the isValid() method. In the isValid() method, you should delegate filter logic to the method testIsValid()
* with the quantity of interest, and return the result from the method call.
*
* @author lopeznr1
*
* @param <G1>
*/
public abstract class RangeFilter<G1> implements ZioObj, Filter<G1>
public abstract class RangeFilter<G1> implements Filter<G1>, ZioObj
{
// State vars
private boolean isEnabled;
private boolean useMin, useMax;
private double minValue, maxValue;
/**
* @param aBinCode
* Unique identifier used during serialization. The value specified here should not collide with any other
* codes for which there is serialization.
*/
/** Standard Constructor */
public RangeFilter()
{
isEnabled = false;
@@ -38,7 +52,7 @@ public abstract class RangeFilter<G1> implements ZioObj, Filter<G1>
public boolean getUseMax() { return useMax; }
public double getMinValue() { return minValue; }
public double getMaxValue() { return maxValue; }
public void setIsEnabled(boolean aBool) { isEnabled = aBool; }
public void setUseMin(boolean aBool) { useMin = aBool; }
public void setUseMax(boolean aBool) { useMax = aBool; }
@@ -61,11 +75,9 @@ public abstract class RangeFilter<G1> implements ZioObj, Filter<G1>
@Override
public void zioRead(ZinStream aStream) throws IOException
{
byte bSwitch;
aStream.readVersion(0);
bSwitch = aStream.readByte();
byte bSwitch = aStream.readByte();
isEnabled = (bSwitch & 0x1) != 0;
useMin = (bSwitch & 0x2) != 0;
useMax = (bSwitch & 0x4) != 0;
@@ -80,11 +92,9 @@ public abstract class RangeFilter<G1> implements ZioObj, Filter<G1>
@Override
public void zioWrite(ZoutStream aStream) throws IOException
{
byte bSwitch;
aStream.writeVersion(0);
bSwitch = 0;
byte bSwitch = 0;
if (isEnabled == true)
bSwitch |= 0x1;
if (useMin == true)

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui;
import javax.swing.*;

View File

@@ -0,0 +1,48 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui;
import java.awt.Component;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
/**
* Collection of execution utilities used to execute behavior at a specific time frame associated with the life cycle of
* AWT/Swing components.
*
* @author lopeznr1
*/
public class GuiExeUtil
{
/**
* Utility method to execute the Runnable once the specified Component is "showing" on the screen.
*/
public static void executeOnceWhenShowing(Component aComp, Runnable aRunnable)
{
aComp.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent aEvent)
{
if (aComp.isShowing() == false)
return;
aRunnable.run();
aComp.removeHierarchyListener(this);
}
});
}
}

View File

@@ -0,0 +1,91 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui;
import java.awt.Component;
import javax.swing.RootPaneContainer;
import glum.gui.panel.generic.MessagePanel;
import glum.util.ThreadUtil;
/**
* Collection of AWT/Swing utilities for showing various message panes.
*
* @author lopeznr1
*/
public class GuiPaneUtil
{
/**
* Utility method to display an alert messages.
* <p>
* Alert panel will have a nominal size of 750, 300.
*/
public static void showAlertMessage(Component aParent, String aTitle, String aInfoMsg)
{
// Delegate
showFailMessage(aParent, aTitle, aInfoMsg, null, 750, 300);
}
/**
* Utility method to display failure messages.
* <p>
* If a stack trace is specified (not null) then the {@link Throwable} will be displayed below aInfoMsg.
*/
public static void showFailMessage(Component aParent, String aTitle, String aInfoMsg, Throwable aExp, int aMaxW,
int aMaxH)
{
// Compute the panel size
int compW = aMaxW;
int compH = aMaxH;
RootPaneContainer tmpRPC = GuiUtil.getRootPaneContainer(aParent);
if (tmpRPC instanceof Component)
{
Component tmpComp = (Component) tmpRPC;
compW = (int) (tmpComp.getWidth() * 0.80);
compH = (int) (tmpComp.getHeight() * 0.80);
}
if (compW > aMaxW)
compW = aMaxW;
if (compH > aMaxH)
compH = aMaxH;
// Setup the info message
String infoMsg = "";
if (aInfoMsg != null)
infoMsg = aInfoMsg;
if (aExp != null)
infoMsg += "\n" + ThreadUtil.getStackTraceClassic(aExp);
MessagePanel tmpPanel = new MessagePanel(aParent, aTitle, compW, compH);
tmpPanel.setInfo(infoMsg, 0);
tmpPanel.setTabSize(2);
tmpPanel.setVisibleAsModal();
}
/**
* Utility method to display failure messages.
* <p>
* The stack trace of the {@link Throwable} will be displayed below aInfoMsg.
* <p>
* Error panel will have a nominal size of 750, 300.
*/
public static void showFailMessage(Component aParent, String aTitle, String aInfoMsg, Throwable aExp)
{
// Delegate
showFailMessage(aParent, aTitle, aInfoMsg, aExp, 750, 300);
}
}

View File

@@ -1,7 +1,22 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.util.Collection;
import javax.swing.*;
@@ -11,28 +26,29 @@ import javax.swing.event.ChangeListener;
import glum.gui.icon.IconUtil;
import glum.reflect.Function;
/**
* Collection of AWT/Swing utilities.
*
* @author lopeznr1
*/
public class GuiUtil
{
/**
* Method to examine the labels and returns the size of the largest button.
*/
public static Dimension computePreferredJButtonSize(String... labels)
public static Dimension computePreferredJButtonSize(String... aLabelArr)
{
Dimension tmpDim, maxDim;
JButton tmpB;
maxDim = null;
tmpB = new JButton("");
Dimension maxDim = null;
var tmpB = new JButton("");
// Find the label that requires the largest dimension
for (String aStr : labels)
for (String aStr : aLabelArr)
{
if (aStr == null)
aStr = "";
tmpB.setText(aStr);
tmpDim = tmpB.getPreferredSize();
var tmpDim = tmpB.getPreferredSize();
if (maxDim == null || maxDim.getWidth() < tmpDim.getWidth())
maxDim = tmpDim;
}
@@ -45,30 +61,29 @@ public class GuiUtil
*/
public static JButton createJButton(String aTitle, ActionListener aActionListener)
{
JButton tmpB;
tmpB = new JButton(aTitle);
var tmpB = new JButton(aTitle);
tmpB.addActionListener(aActionListener);
return tmpB;
}
/**
* Creates the JRadioButton with the following attributes.
* <p>
* TODO: Do not remove this method until DistMaker has been updated...
*/
public static JButton createJButton(String aTitle, ActionListener aActionListener, Font aFont)
{
JButton tmpB;
tmpB = new JButton(aTitle);
var tmpB = new JButton(aTitle);
tmpB.addActionListener(aActionListener);
if (aFont != null)
tmpB.setFont(aFont);
tmpB.setFont(aFont);
return tmpB;
}
public static JButton createJButton(String aTitle, ActionListener aActionListener, Dimension aDimension)
{
JButton tmpB;
tmpB = new JButton(aTitle);
var tmpB = new JButton(aTitle);
tmpB.addActionListener(aActionListener);
// Force a dimension
@@ -89,9 +104,7 @@ public class GuiUtil
public static JButton createJButton(Icon aIcon, ActionListener aActionListener, String aToolTip)
{
JButton tmpB;
tmpB = new JButton(aIcon);
var tmpB = new JButton(aIcon);
tmpB.addActionListener(aActionListener);
if (aToolTip != null)
@@ -110,9 +123,7 @@ public class GuiUtil
public static JButton createJButtonViaResource(ActionListener aHandler, String aResourcePath, String aToolTip)
{
JButton tmpB;
tmpB = new JButton(IconUtil.loadIcon(aResourcePath));
var tmpB = new JButton(IconUtil.loadIcon(aResourcePath));
tmpB.addActionListener(aHandler);
if (aToolTip != null)
@@ -126,47 +137,12 @@ public class GuiUtil
*/
public static JCheckBox createJCheckBox(String aTitle, ActionListener aActionListener)
{
return createJCheckBox(aTitle, aActionListener, null);
}
public static JCheckBox createJCheckBox(String aTitle, ActionListener aActionListener, Font aFont)
{
JCheckBox tmpCB;
tmpCB = new JCheckBox(aTitle);
var tmpCB = new JCheckBox(aTitle);
tmpCB.addActionListener(aActionListener);
if (aFont != null)
tmpCB.setFont(aFont);
return tmpCB;
}
/**
* Creates a JComboBox with the specified settings
*/
public static <G1> JComboBox<G1> createJComboBox(ActionListener aListener, Font aFont, Collection<G1> aItemL)
{
JComboBox<G1> tmpBox;
tmpBox = new JComboBox<G1>();
for (G1 aItem : aItemL)
tmpBox.addItem(aItem);
if (aFont != null)
tmpBox.setFont(aFont);
tmpBox.addActionListener(aListener);
return tmpBox;
}
// /**
// * Creates a JComboBox with the specified settings
// */
// public static JComboBox createJComboBox(ActionListener aListener, Object... itemArr)
// {
// return createJComboBox(aListener, null, itemArr);
// }
/**
* Creates a JLabel with the specified settings
*/
@@ -177,10 +153,7 @@ public class GuiUtil
public static JLabel createJLabel(String aTitle, int aAlignment, Font aFont)
{
JLabel tmpL;
tmpL = new JLabel(aTitle, aAlignment);
var tmpL = new JLabel(aTitle, aAlignment);
if (aFont != null)
tmpL.setFont(aFont);
@@ -188,48 +161,63 @@ public class GuiUtil
}
/**
* Creates the JRadioButton with the following attributes.
* Creates the {@link JComboBox} with the following attributes.
*/
public static JRadioButton createJRadioButton(String aLabel, ActionListener aListener)
public static <G1> JComboBox<G1> createComboBox(ActionListener aListener, Collection<G1> aItemC)
{
return createJRadioButton(aLabel, aListener, null);
var retBox = new JComboBox<G1>();
for (G1 aItem : aItemC)
retBox.addItem(aItem);
retBox.addActionListener(aListener);
return retBox;
}
public static JRadioButton createJRadioButton(String aLabel, ActionListener aListener, Font aFont)
/**
* Creates the JRadioButton with the following attributes.
*/
public static JRadioButton createJRadioButton(ItemListener aListener, String aLabel)
{
JRadioButton tmpRB;
var retRB = new JRadioButton(aLabel);
retRB.addItemListener(aListener);
tmpRB = new JRadioButton(aLabel);
tmpRB.addActionListener(aListener);
if (aFont != null)
tmpRB.setFont(aFont);
return retRB;
}
return tmpRB;
/**
* Creates the JRadioButton with the following attributes.
* <p>
* TODO: Do not remove this method until DistMaker has been updated...
*/
public static JRadioButton createJRadioButton(ItemListener aListener, String aLabel, Font aFont)
{
var retRB = new JRadioButton(aLabel);
retRB.addItemListener(aListener);
retRB.setFont(aFont);
return retRB;
}
/**
* Utility method for creating a visual thin divider
* <P>
* <p>
* Typically added to MigLayout (or like manager) with: add(aComp, "growx,h 4!,span,wrap");
*/
public static JPanel createDivider()
{
JPanel tmpPanel;
var retPanel = new JPanel();
retPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
tmpPanel = new JPanel();
tmpPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
return tmpPanel;
return retPanel;
}
/**
* Creates an uneditable JTextArea with no border, non-opaque, line wrap enabled and word wrap enabled.
* Creates an uneditable JTextArea with the settings: non-opaque, line wrap enabled and word wrap enabled.
*/
public static JTextArea createUneditableTextArea(int rows, int cols)
{
JTextArea tmpTA;
tmpTA = new JTextArea("", rows, cols);
var tmpTA = new JTextArea("", rows, cols);
tmpTA.setEditable(false);
tmpTA.setOpaque(false);
tmpTA.setLineWrap(true);
@@ -243,9 +231,7 @@ public class GuiUtil
*/
public static JTextPane createUneditableTextPane()
{
JTextPane tmpTP;
tmpTP = new JTextPane();
var tmpTP = new JTextPane();
tmpTP.setEditable(false);
tmpTP.setOpaque(false);
tmpTP.setContentType("text/html");
@@ -258,9 +244,7 @@ public class GuiUtil
*/
public static JTextField createUneditableTextField(String aTitle)
{
JTextField tmpTF;
tmpTF = new JTextField(aTitle);
var tmpTF = new JTextField(aTitle);
tmpTF.setBorder(null);
tmpTF.setEditable(false);
tmpTF.setOpaque(false);
@@ -268,134 +252,103 @@ public class GuiUtil
return tmpTF;
}
/**
* Utility helper method to create a JButton with the specified configuration.
*
* @param aListener
* A Listener registered with the JButton.
* @param aIcon
* The icon associated with the button
*/
public static JButton formButton(ActionListener aListener, Icon aIcon)
{
var retB = new JButton();
retB.addActionListener(aListener);
retB.setIcon(aIcon);
return retB;
}
/**
* Utility helper method to create a JButton with the specified configuration.
*
* @param aListener
* A Listener registered with the JButton.
* @param aImage
* The image to be used as an icon.
* @param aToolTip
* The tool tip associated with the JButton.
*/
public static JButton formButton(ActionListener aListener, BufferedImage aImage, String aToolTip)
{
var tmpIcon = new ImageIcon(aImage);
var retB = new JButton();
retB.setIcon(tmpIcon);
retB.addActionListener(aListener);
retB.setToolTipText(aToolTip);
return retB;
}
/**
* Utility helper method to create a JButton with the specified configuration.
*
* @param aListener
* A Listener registered with the JButton.
* @param aTitle
* The text title of the JButton.
*/
public static JButton formButton(ActionListener aListener, String aTitle)
{
var retB = new JButton();
retB.addActionListener(aListener);
retB.setText(aTitle);
return retB;
}
/**
* Utility helper method to create a JToggleButton with the specified configuration.
*
* @param aListener
* A Listener registered with the JButton.
* @param aPriIcon
* The icon to be used as the primary (unselected) icon.
* @param aSecIcon
* The icon to be used when the secondary (selected) icon.
* @param aToolTip
* The tool tip associated with the JToggleButton.
*/
public static JToggleButton formToggleButton(ActionListener aListener, Icon aPriIcon, Icon aSecIcon)
{
var retTB = new JToggleButton(aPriIcon, false);
retTB.setSelectedIcon(aSecIcon);
retTB.addActionListener(aListener);
return retTB;
}
/**
* Utility method to link a set of radio buttons together
*/
public static void linkRadioButtons(JRadioButton... buttonArr)
public static ButtonGroup linkRadioButtons(JRadioButton... aButtonArr)
{
ButtonGroup tmpGroup;
var retGroup = new ButtonGroup();
for (var aItem : aButtonArr)
retGroup.add(aItem);
tmpGroup = new ButtonGroup();
for (JRadioButton aItem : buttonArr)
tmpGroup.add(aItem);
return retGroup;
}
/**
* Reads a boolean from a string with out throwing a exception
* Utility method to link a set of radio buttons together
*/
public static boolean readBoolean(String aStr, boolean aVal)
public static ButtonGroup linkRadioButtons(Collection<JRadioButton> aButtonC)
{
if (aStr == null)
return aVal;
var retGroup = new ButtonGroup();
for (var aItem : aButtonC)
retGroup.add(aItem);
// Special case for 1 char strings
if (aStr.length() == 1)
{
char aChar;
aChar = aStr.charAt(0);
if (aChar == 'T' || aChar == 't' || aChar == '1')
return true;
return false;
}
try
{
return Boolean.valueOf(aStr).booleanValue();
}
catch(Exception e)
{
return aVal;
}
}
/**
* Reads a double from a string with out throwing a exception. Note aStr can have an number of separators: comma
* chars
*/
public static double readDouble(String aStr, double aVal)
{
try
{
aStr = aStr.replace(",", "");
return Double.parseDouble(aStr);
}
catch(Exception e)
{
return aVal;
}
}
/**
* Reads a float from a string with out throwing a exception. Note aStr can have an number of separators: comma chars
*/
public static float readFloat(String aStr, float aVal)
{
try
{
aStr = aStr.replace(",", "");
return Float.parseFloat(aStr);
}
catch(Exception e)
{
return aVal;
}
}
/**
* Reads an int from a string without throwing a exception Note aStr can have an number of separators: comma chars
*/
public static int readInt(String aStr, int aVal)
{
try
{
aStr = aStr.replace(",", "");
return Integer.parseInt(aStr);
}
catch(Exception e)
{
return aVal;
}
}
/**
* Reads a long from a string without throwing a exception Note aStr can have an number of separators: comma chars
*/
public static long readLong(String aStr, long aVal)
{
try
{
aStr = aStr.replace(",", "");
return Long.parseLong(aStr);
}
catch(Exception e)
{
return aVal;
}
}
/**
* Reads an int (forced to fit within a range) from a string with out throwing a exception
*/
public static int readRangeInt(String aStr, int minVal, int maxVal, int aVal)
{
int aInt;
try
{
aInt = Integer.parseInt(aStr);
if (aInt < minVal)
aInt = minVal;
else if (aInt > maxVal)
aInt = maxVal;
return aInt;
}
catch(Exception e)
{
return aVal;
}
return retGroup;
}
/**
@@ -403,28 +356,27 @@ public class GuiUtil
*/
public static RootPaneContainer getRootPaneContainer(Component aComponent)
{
Container aParent;
// Check to see if the Component is an actual RootPaneContainer
if (aComponent instanceof RootPaneContainer)
return (RootPaneContainer)aComponent;
return (RootPaneContainer) aComponent;
// Attempt to locate the RootPaneContainer (through our stack)
aParent = aComponent.getParent();
while (aParent != null && (aParent instanceof RootPaneContainer) == false)
aParent = aParent.getParent();
var retParent = aComponent.getParent();
while (retParent != null && (retParent instanceof RootPaneContainer) == false)
retParent = retParent.getParent();
// Bail if we failed to find the RootPaneContainer
if (aParent instanceof RootPaneContainer == false)
if (retParent instanceof RootPaneContainer == false)
throw new RuntimeException("No valid (grand)parent associated with GlassPane.");
return (RootPaneContainer)aParent;
return (RootPaneContainer) retParent;
}
/**
* Utility method to locate all of the subcomponents contained in aContainer which are an instance of searchClass
*/
public static void locateAllSubComponents(Container aContainer, Collection<Component> itemList, Class<?>... searchClassArr)
public static void locateAllSubComponents(Container aContainer, Collection<Component> itemList,
Class<?>... searchClassArr)
{
for (Component aComponent : aContainer.getComponents())
{
@@ -438,13 +390,14 @@ public class GuiUtil
}
if (aComponent instanceof Container)
locateAllSubComponents((Container)aComponent, itemList, searchClassArr);
locateAllSubComponents((Container) aComponent, itemList, searchClassArr);
}
}
/**
* Utility method to force a Component to act as modal while it is visible Source:
* http://stackoverflow.com/questions/804023/how-do-i-simulate-a-modal-dialog-from-within-an-applet
* Utility method to force a Component to act as modal while it is visible
* <p>
* Source: http://stackoverflow.com/questions/804023/how-do-i-simulate-a-modal-dialog-from-within-an-applet
*/
public static void modalWhileVisible(Component aComponent)
{
@@ -452,27 +405,27 @@ public class GuiUtil
if (SwingUtilities.isEventDispatchThread() == false)
throw new RuntimeException("Visibility for modal components must be changed via the Event thread.");
synchronized(aComponent)
synchronized (aComponent)
{
try
{
EventQueue theQueue = aComponent.getToolkit().getSystemEventQueue();
var theQueue = aComponent.getToolkit().getSystemEventQueue();
while (aComponent.isVisible())
{
//System.out.println("About to dispatch event... component.isVisible():" + aComponent.isVisible());
AWTEvent event = theQueue.getNextEvent();
Object source = event.getSource();
var event = theQueue.getNextEvent();
var source = event.getSource();
if (event instanceof ActiveEvent)
{
((ActiveEvent)event).dispatch();
((ActiveEvent) event).dispatch();
}
else if (source instanceof Component)
{
((Component)source).dispatchEvent(event);
((Component) source).dispatchEvent(event);
}
else if (source instanceof MenuComponent)
{
((MenuComponent)source).dispatchEvent(event);
((MenuComponent) source).dispatchEvent(event);
}
else
{
@@ -480,7 +433,7 @@ public class GuiUtil
}
}
}
catch(InterruptedException ignored)
catch (InterruptedException ignored)
{
}
}
@@ -489,18 +442,16 @@ public class GuiUtil
/**
* Utility to call a specific method (methodName) with specific parameters (aParamArr) on aComp and on all of the
* child subcomponents. The method will only be called if the components are an instance of refMatchClass.
* <P>
* This is useful so that a component and all of its children can be disabled, hidden, etc<BR>
* <p>
* This is useful so that a component and all of its children can be disabled, hidden, etc</br>
* Example: GuiUtil.callMethod(myPanel, setEnabled, false);
* <P>
* <p>
* Be aware, this is rather expensive, so do not call in time critical applications.
*/
public static void callMethod(Component aComp, Class<?> refMatchClass, String aMethodName, Object... aParamArr)
{
Class<?>[] typeArr;
// Construct the associated type array
typeArr = new Class[0];
var typeArr = new Class<?>[0];
if (aParamArr.length > 0)
{
// Determine the types of the specified arguments
@@ -520,24 +471,22 @@ public class GuiUtil
/**
* Helper method to callMethod
*/
private static void callMethodHelper(Component aComp, Class<?> refMatchClass, String aMethodName, Class<?>[] aTypeArr, Object[] aParamArr)
private static void callMethodHelper(Component aComp, Class<?> refMatchClass, String aMethodName,
Class<?>[] aTypeArr, Object[] aParamArr)
{
Component[] subCompArr;
Function aFunction;
// Locate and call the actual method
if (refMatchClass.isInstance(aComp) == true)
{
try
{
aFunction = new Function(aComp, aMethodName, aTypeArr);
aFunction.invoke(aParamArr);
var tmpFunction = new Function(aComp, aMethodName, aTypeArr);
tmpFunction.invoke(aParamArr);
}
catch(NoSuchMethodException aExp1)
catch (NoSuchMethodException aExp1)
{
throw new RuntimeException("Failed to locate valid function. Method:" + aMethodName, aExp1);
}
catch(Exception aExp2)
catch (Exception aExp2)
{
throw new RuntimeException("Failed to execute function. Method:" + aMethodName, aExp2);
}
@@ -548,34 +497,44 @@ public class GuiUtil
return;
// Recurse down our children
subCompArr = ((Container)aComp).getComponents();
var subCompArr = ((Container) aComp).getComponents();
for (Component aSubComp : subCompArr)
callMethodHelper(aSubComp, refMatchClass, aMethodName, aTypeArr, aParamArr);
}
/**
* Utility method to set all subcomponents to the specified enabled mode.
* Utility method to recursively change the enable state of all Components contained by the specified Container.
*
* @param aContainer
* The Container of interest.
* @param aBool
* Boolean used to define the enable state.
*/
// TODO: Phase this method out, replace with callMethod()
public static void setEnabled(Component aComp, boolean aBool)
public static void setEnabled(Container aContainer, boolean aBool)
{
Component[] subCompArr;
aComp.setEnabled(aBool);
if (aComp instanceof Container == false)
return;
subCompArr = ((Container)aComp).getComponents();
for (Component aSubComp : subCompArr)
GuiUtil.setEnabled(aSubComp, aBool);
for (Component aComp : aContainer.getComponents())
{
aComp.setEnabled(aBool);
if (aComp instanceof Container)
setEnabled((Container) aComp, aBool);
}
}
/**
* Utility method to set the enabled switch on all of the specified components.
* Utility method to set the enable state on all of the specified components.
*/
public static void setEnabled(boolean aBool, Component... componentArr)
public static void setEnabled(boolean aBool, Component... aComponentArr)
{
for (Component aComp : componentArr)
for (Component aComp : aComponentArr)
aComp.setEnabled(aBool);
}
/**
* Utility method to set the enable state on all of the specified components.
*/
public static void setEnabled(boolean aBool, Collection<? extends Component> aComponentC)
{
for (Component aComp : aComponentC)
aComp.setEnabled(aBool);
}
@@ -592,43 +551,48 @@ public class GuiUtil
}
/**
* Utility method that takes up to 8 buttons and converts all of their selection states to a single byte.
* Utility method that returns a bitmask composed of the selection state of the specified buttons.
* <p>
* The array is transformed such that the least significant bit is assumed to have index position 0 with the higher
* bits corresponding to a larger (array) index.
* <p>
* A maximum of 32 buttons is support. Passing in more than 32 buttons will result in an exception.
*/
public static byte getSelectionStateAsByte(AbstractButton... buttonArr)
public static int getSelectionStateAsBitMask(AbstractButton... aButtonArr)
{
byte retByte;
if (aButtonArr.length > 32)
throw new RuntimeException("Improper API call. Max of 32 buttons supported. Passed: " + aButtonArr.length);
if (buttonArr.length > 8)
throw new RuntimeException("Improper API call. Max of 8 buttons supported. Passed: " + buttonArr.length);
retByte = 0;
for (int c1 = 0; c1 < buttonArr.length; c1++)
int retBitMask = 0;
for (int c1 = 0; c1 < aButtonArr.length; c1++)
{
if (buttonArr[c1].isSelected() == true)
retByte |= 1 << c1;
if (aButtonArr[c1].isSelected() == true)
retBitMask |= 1 << c1;
}
return retByte;
return retBitMask;
}
/**
* Utility method that takes up to 8 buttons and configures the selection state of the buttons to match the bit
* pattern of aByte.
* Utility method that updates the selection state of the provided buttons to reflect the specified bitmask.
* <p>
* The array is transformed such that the least significant bit is assumed to have index position 0 with the higher
* bits corresponding to a larger (array) index.
* <p>
* A maximum of 32 buttons is support. Passing in more than 32 buttons will result in an exception.
*/
public static void setSelectionState(byte aByte, AbstractButton... buttonArr)
public static void setSelectionStateFromBitMask(int aBitMask, AbstractButton... aButtonArr)
{
boolean aBool;
if (aButtonArr.length > 32)
throw new RuntimeException("Improper API call. Max of 32 buttons supported. Passed: " + aButtonArr.length);
if (buttonArr.length > 8)
throw new RuntimeException("Improper API call. Max of 8 buttons supported. Passed: " + buttonArr.length);
for (int c1 = 0; c1 < buttonArr.length; c1++)
for (int c1 = 0; c1 < aButtonArr.length; c1++)
{
aBool = false;
if (((0x01 << c1) & aByte) != 0)
aBool = true;
var tmpBool = false;
if (((0x01 << c1) & aBitMask) != 0)
tmpBool = true;
buttonArr[c1].setSelected(aBool);
aButtonArr[c1].setSelected(tmpBool);
}
}
@@ -637,9 +601,7 @@ public class GuiUtil
*/
public static void updateSlider(JSlider aSlider, int aVal)
{
ChangeListener[] tmpArr;
tmpArr = aSlider.getChangeListeners();
var tmpArr = aSlider.getChangeListeners();
for (ChangeListener aListener : tmpArr)
aSlider.removeChangeListener(aListener);
@@ -654,13 +616,13 @@ public class GuiUtil
* Utility method that checks to ensure the current thread is running on the ATW thread. If it is NOT then the
* specified Runnable will be posted so that it is called on the AWT thread. If it is running on the AWT thread then
* nothing will happen and this method will return false.
* <P>
* <p>
* Typically this utility method is called at the start of a function to ensure it is on the AWT thread, and if not
* then schedule the function onto the AWT thread. Thus it is strongly advisable that if this method returns true the
* caller should immediately exit.
* <P>
* <p>
* <B>Typical usage within a method:</B>
*
*
* <PRE>
* public void actionPerformed(aEvent)
* {
@@ -668,7 +630,7 @@ public class GuiUtil
* Runnable tmpRunnable = ()-> actionPerformed(aEvent);
* if (redispatchOnAwtIfNeeded(this, "actionPerformed", aEvent) = true)
* return;
*
*
* // Do normal work ...
* }
* </PRE>

View File

@@ -0,0 +1,88 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui;
import java.awt.*;
/**
* Collection of additional AWT/Swing based utility methods.
*
* @author lopeznr1
*/
public class GuiUtilEx
{
/**
* Utility method that returns the default dimension for the main window.
* <p>
* The returned {@link Dimension} will have a minimum size of [aMinX,aMinY] or [80%,80%] of the screen resolution
* (which ever is smaller).
*/
public static Dimension getDimensionDefaultMain(int aMinX, int aMinY)
{
var screenDim = Toolkit.getDefaultToolkit().getScreenSize();
int winW = Math.min(aMinX, (int) (screenDim.getWidth() * 0.80));
int winH = Math.min(aMinY, (int) (screenDim.getHeight() * 0.80));
return new Dimension(winW, winH);
}
/**
* Utility method that returns the default dimension for the main window.
* <p>
* The returned {@link Dimension} will have a minimum size of [950, 750] or 80% of the screen resolution.
*/
public static Dimension getDimensionDefaultMain()
{
// Delegate
return getDimensionDefaultMain(950, 750);
}
/**
* Utility method that returns a new Dimension where the size has been scaled by the specified scalars.
*
* @param aDimension
* The original dimension
* @param aScalerX
* Percent to scale the dimensions width.
* @param aScalerY
* Percent to scale the dimensions height.
*/
public static Dimension getDimensionScaled(Dimension aDimension, double aScalerX, double aScalerY)
{
int winW = Math.min(950, (int) (aDimension.getWidth() * aScalerX));
int winH = Math.min(750, (int) (aDimension.getHeight() * aScalerY));
return new Dimension(winW, winH);
}
/**
* Utility method that returns the (first) parent that matches the specified Class. If there is no such component
* then null will be returned.
*/
public static Component getParent(Component aComp, Class<?> aClass)
{
// Search through all the (grand)parents
var parent = aComp.getParent();
while (parent != null)
{
// Bail once we have a matching class
if (parent.getClass() == aClass)
return parent;
// Next parent
parent = parent.getParent();
}
return null;
}
}

185
src/glum/gui/TableUtil.java Normal file
View File

@@ -0,0 +1,185 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui;
import java.util.*;
import javax.swing.JTable;
import javax.swing.event.*;
import com.google.common.primitives.Ints;
import glum.gui.table.TableSorter;
import glum.item.ItemManager;
/**
* Collection of utilities associated with JTables.
*
* @author lopeznr1
*/
public class TableUtil
{
/**
* Utility method to invert the selection on the specified table. The selection will be inverted with the specified
* ListSelectionListener being ignored.
*
* @param aTable
* The table for which the selection should be inverted.
* @param aIgnoreListener
* An ListSelectionListener that will not receive any intermediate events. It is important that this listener
* be registered with the table's selection model as it will be deregistered and then later registered. If
* null then this argument will be ignored.
*/
public static void invertSelection(JTable aTable, ListSelectionListener aIgnoreListener)
{
Set<Integer> oldSet = new HashSet<>();
for (int aId : aTable.getSelectedRows())
oldSet.add(aId);
int numRows = aTable.getRowCount();
int[] tmpArr = new int[numRows - oldSet.size()];
// Determine the rows that are to be selected
int idx = 0;
for (int aId = 0; aId < numRows; aId++)
{
// Skip to next if row was previously selected
if (oldSet.contains(aId) == true)
continue;
tmpArr[idx] = aId;
idx++;
}
// Delegate
setSortedSelection(aTable, aIgnoreListener, tmpArr);
// Send out a single event of the change
if (aIgnoreListener != null)
aIgnoreListener.valueChanged(new ListSelectionEvent(aTable, 0, aTable.getRowCount() - 1, false));
}
/**
* Utility method to select the rows at the specified indexes. The selection will be updated with the specified
* ListSelectionListener being ignored.
*
* @param aTable
* The table for which the selection should be updated.
* @param aIgnoreListener
* A ListSelectionListener that will not receive any intermediate events. It is important that this listener
* be registered with the table's selection model as it will be deregistered and then later registered. If
* null then this argument will be ignored.
* @param aRowL
* A list of indexes corresponding to the rows that are to be selected. All other rows will be unselected.
*/
public static void setSelection(JTable aTable, ListSelectionListener aIgnoreListener, List<Integer> aRowL)
{
// Transform to a sorted array
int[] rowArr = Ints.toArray(aRowL);
Arrays.parallelSort(rowArr);
// Delegate
setSortedSelection(aTable, aIgnoreListener, rowArr);
}
/**
* Utility method that will synchronize the table selection to match the selected items in the ItemManager. If new
* items were selected then the table will be scrolled (to the first newly selected row).
*/
public static <G1> void updateTableSelection(ListSelectionListener aIgnoreListener, ItemManager<G1> aManager,
JTable aTable, TableSorter aSortTableModel)
{
// Form a reverse lookup map of item to (view) index
List<G1> fullItemL = aManager.getAllItems();
Map<G1, Integer> revLookM = new HashMap<>();
for (int aIdx = 0; aIdx < fullItemL.size(); aIdx++)
{
int tmpIdx = aSortTableModel.viewIndex(aIdx);
revLookM.put(fullItemL.get(aIdx), tmpIdx);
}
int[] idxArr = aTable.getSelectedRows();
List<Integer> oldL = Ints.asList(idxArr);
Set<Integer> oldS = new LinkedHashSet<>(oldL);
List<Integer> newL = new ArrayList<>();
for (G1 aItem : aManager.getSelectedItems())
newL.add(revLookM.get(aItem));
Set<Integer> newS = new LinkedHashSet<>(newL);
// Bail if nothing has changed
if (newS.equals(oldS) == true)
return;
// Update the table's selection
setSelection(aTable, aIgnoreListener, newL);
aTable.repaint();
}
/**
* Utility helper method that selects the specified rows.
* <p>
* The rows must be in sorted order.
*
* @param aTable
* The table for which the selection should be updated.
* @param aIgnoreListener
* An ListSelectionListener that will not receive any intermediate events. It is important that this listener
* be registered with the table's selection model as it will be deregistered and then later registered. If
* null then this argument will be ignored.
* @param aSortedRowArr
* An array of indexes corresponding to the rows that are to be selected. All other rows will be unselected.
*/
private static void setSortedSelection(JTable aTable, ListSelectionListener aIgnoreListener, int[] aSortedRowArr)
{
// Initial range
int begIdx = -1;
int endIdx = -1;
if (aSortedRowArr.length >= 1)
{
begIdx = aSortedRowArr[0];
endIdx = begIdx;
}
if (aIgnoreListener != null)
aTable.getSelectionModel().removeListSelectionListener(aIgnoreListener);
aTable.clearSelection();
for (int aRow : aSortedRowArr)
{
// Expand the range by: +1
if (aRow == endIdx + 1)
{
endIdx++;
continue;
}
// Add the current interval
aTable.addRowSelectionInterval(begIdx, endIdx);
// Start a new range
begIdx = endIdx = aRow;
}
// Ensure the last interval gets added
if (begIdx != -1 && endIdx != -1)
aTable.addRowSelectionInterval(begIdx, endIdx);
if (aIgnoreListener != null)
aTable.getSelectionModel().addListSelectionListener(aIgnoreListener);
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.action;
import java.awt.Component;
import java.util.Collection;
/**
* Interface that provides a mechanism for a component to declare that it will provide action {@link Component}s
* (typically buttons).
*
* @author lopeznr1
*/
public interface ActionComponentProvider
{
/**
* Returns a list of {@link Component}s that should be placed in the action region.
*/
public Collection<? extends Component> getActionButtons();
}

View File

@@ -1,22 +1,44 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.action;
import java.awt.event.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
/**
* Action used to "click" on the target {@link AbstractButton}.
* <p>
* Clicking will be done via the {@link AbstractButton#doClick()} method.
*
* @author lopeznr1
*/
public class ClickAction extends AbstractAction
{
// State vars
protected AbstractButton target;
// Reference vars
private final AbstractButton refTarget;
public ClickAction(AbstractButton aTarget)
{
target = aTarget;
refTarget = aTarget;
}
@Override
public void actionPerformed(ActionEvent e)
{
target.doClick();
refTarget.doClick();
}
}

View File

@@ -0,0 +1,82 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.action;
import java.awt.Component;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;
import glum.gui.GuiUtil;
import net.miginfocom.swing.MigLayout;
/**
* JDialog that holds a single {@link Component} and a close button.
*
* @author lopeznr1
*/
public class CloseDialog extends JDialog implements ActionListener
{
// Gui vars
private final JButton closeB;
/**
* Standard Constructor
*/
public CloseDialog(Frame aParent, Component aMainComp)
{
super(aParent);
var tmpPanel = new JPanel();
tmpPanel.setLayout(new MigLayout("", "[]", "0[]0[]"));
tmpPanel.add(aMainComp, "growx,growy,pushx,pushy,span,wrap");
// Form a unified list of buttons
var tmpActionCompL = new ArrayList<Component>();
if (aMainComp instanceof ActionComponentProvider)
tmpActionCompL.addAll(((ActionComponentProvider) aMainComp).getActionButtons());
closeB = GuiUtil.formButton(this, "Close");
tmpActionCompL.add(closeB);
// Add the components in
var isFirst = true;
for (Component aComp : tmpActionCompL)
{
if (isFirst == true)
tmpPanel.add(aComp, "span,split,ax right");
else
tmpPanel.add(aComp, "");
isFirst = false;
}
setContentPane(tmpPanel);
setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
setModal(false);
pack();
}
@Override
public void actionPerformed(ActionEvent aEvent)
{
var source = aEvent.getSource();
if (source == closeB)
setVisible(false);
}
}

View File

@@ -1,23 +1,55 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.action;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
/**
* Action used to change the target {@link Component} to be visible.
*
* @author lopeznr1
*/
public class MakeVisibleAction extends AbstractAction
{
// State vars
protected Component target;
// Reference vars
private final Component refTarget;
/**
* Standard Constructor
*
* @param aTarget
*/
public MakeVisibleAction(Component aTarget)
{
target = aTarget;
refTarget = aTarget;
}
/**
* Returns the reference target.
*/
public Component getTarget()
{
return refTarget;
}
@Override
public void actionPerformed(ActionEvent e)
{
target.setVisible(true);
refTarget.setVisible(true);
}
}

View File

@@ -0,0 +1,66 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.action;
import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JMenuItem;
import com.google.common.collect.ImmutableList;
/**
* Base action specific to popup menus.
* <p>
* Whenever the list of selected objects changes this PopAction will be notified.
*
* @author lopeznr1
*/
public abstract class PopAction<G1> extends AbstractAction
{
// State vars
private ImmutableList<G1> itemL;
/**
* Standard Constructor
*/
public PopAction()
{
itemL = ImmutableList.of();
}
/**
* Notification that the {@link PopAction} should be executed on the specified items.
*
* @param aItemL
*/
public abstract void executeAction(List<G1> aItemL);
/**
* Sets in the items that are currently selected.
*/
public void setChosenItems(Collection<G1> aItemC, JMenuItem aAssocMI)
{
itemL = ImmutableList.copyOf(aItemC);
}
@Override
public void actionPerformed(ActionEvent aAction)
{
executeAction(itemL);
}
}

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.action;
import java.awt.Component;
import java.util.*;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import glum.item.ItemManager;
/**
* UI component that allows a custom popup menu to be built.
*
* @author lopeznr1
*/
public class PopupMenu<G1> extends JPopupMenu
{
// Reference vars
private ItemManager<G1> refManager;
// State vars
private Map<JMenuItem, PopAction<G1>> actionM;
/**
* Standard Constructor
*
* @param aManager
*/
public PopupMenu(ItemManager<G1> aManager)
{
refManager = aManager;
actionM = new HashMap<>();
}
/**
* Registers the specified {@link PopAction} into this {@link PopupMenu}.
* <p>
* A simple menu item will be created and associated with the specified action.
*/
public void installPopAction(PopAction<G1> aAction, String aTitle)
{
JMenuItem tmpMI = new JMenuItem(aAction);
tmpMI.setText(aTitle);
// Delegate
installPopAction(aAction, tmpMI);
}
/**
* Registers the specified {@link PopAction} into this {@link PopupMenu}.
* <p>
* The action will be associated with the specified menu item.
*/
public void installPopAction(PopAction<G1> aAction, JMenuItem aTargMI)
{
add(aTargMI);
actionM.put(aTargMI, aAction);
}
@Override
public void show(Component aParent, int aX, int aY)
{
// Bail if we do not have selected items
Set<G1> tmpS = refManager.getSelectedItems();
if (tmpS.size() == 0)
return;
// Update our PopActions
for (JMenuItem aMI : actionM.keySet())
{
PopAction<G1> tmpPA = actionM.get(aMI);
tmpPA.setChosenItems(tmpS, aMI);
}
// Delegate
super.show(aParent, aX, aY);
}
}

View File

@@ -0,0 +1,80 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.*;
import javax.swing.JTextField;
/**
* User interface input used to capture an input string.
* <p>
* This object provides the following additional features:
* <ul>
* <li>Display of passive hint text
* </ul>
*
* @author lopeznr1
*/
public class GBaseTextField extends JTextField
{
// State vars
private String mHint;
/** Standard Constructor */
public GBaseTextField(String aText, int aNumColumns)
{
super(aText, aNumColumns);
mHint = null;
}
/**
* Sets a hint that will be shown whenever the text field is empty.
*/
public void setHint(String aHint)
{
mHint = aHint;
repaint();
}
@Override
public void paint(Graphics g)
{
super.paint(g);
// Bail if there is already input
if (getText().length() != 0)
return;
// Bail if there is no hint
if (mHint == null || mHint.length() == 0)
return;
// Draw the textual hint
// Source:
// https://stackoverflow.com/questions/1738966/java-jtextfield-with-input-hint
int h = getHeight();
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Insets ins = getInsets();
FontMetrics fm = g.getFontMetrics();
int c0 = getBackground().getRGB();
int c1 = getForeground().getRGB();
int m = 0xfefefefe;
int c2 = ((c0 & m) >>> 1) + ((c1 & m) >>> 1);
g.setColor(new Color(c2, true));
g.drawString(mHint, ins.left, h / 2 + fm.getAscent() / 2 - 2);
}
}

View File

@@ -1,58 +1,81 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import glum.gui.component.model.GComboBoxModel;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Collection;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.ListCellRenderer;
import com.google.common.collect.ImmutableList;
import glum.gui.component.model.GComboBoxModel;
/**
* Enhanced implementation of {@link JComboBox}. This implementation provides for better generics support. Please
* utilize the {@link #getChosenItem()}, {@link #setChosenItem(Object)}, etc...
*
* @author lopeznr1
*/
public class GComboBox<G1> extends JComboBox<G1>
{
// State vars
protected GComboBoxModel<G1> itemModel;
private GComboBoxModel<G1> itemModel;
public GComboBox()
{
itemModel = new GComboBoxModel<G1>(new LinkedList<G1>());
itemModel = new GComboBoxModel<G1>(ImmutableList.of());
setModel(itemModel);
}
public GComboBox(ActionListener aListener, ListCellRenderer<? super G1> aRenderer)
{
this();
addActionListener(aListener);
setRenderer(aRenderer);
}
public GComboBox(ActionListener aListener)
{
this();
addActionListener(aListener);
}
public GComboBox(ActionListener aListener, List<G1> aItemList)
public GComboBox(ActionListener aListener, Collection<G1> aItemC)
{
itemModel = new GComboBoxModel<G1>(aItemList);
itemModel = new GComboBoxModel<>(aItemC);
setModel(itemModel);
addActionListener(aListener);
}
public GComboBox(ActionListener aListener, G1... aItemArr)
{
itemModel = new GComboBoxModel<G1>(aItemArr);
itemModel = new GComboBoxModel<>(aItemArr);
setModel(itemModel);
addActionListener(aListener);
}
/**
* Returns the list of all items stored in the GComboBox
*/
public ArrayList<G1> getAllItems()
public List<G1> getAllItems()
{
return itemModel.getAllItems();
}
@@ -64,43 +87,43 @@ public class GComboBox<G1> extends JComboBox<G1>
{
return itemModel.getSelectedItem();
}
/**
* Sets in the currently selected item. This method will not trigger an ActionEvent.
*
* @see JComboBox#setSelectedItem
*/
public void setChosenItem(G1 aItem)
{
ActionListener[] listenerArr;
listenerArr = getActionListeners();
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
itemModel.setSelectedItem(aItem);
super.setSelectedItem(aItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
// We must force a repaint since any ActionListener responsible will never get the update
// We must force a repaint since any ActionListener responsible will never get the update
repaint();
}
/**
* Note aItem must be of the generified type. This method will not trigger an ActionEvent.
*/
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public void addItem(Object aItem)
{
ActionListener[] listenerArr;
listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
itemModel.addItem((G1)aItem);
itemModel.addItem((G1) aItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
@@ -110,15 +133,29 @@ public class GComboBox<G1> extends JComboBox<G1>
*/
public void addItems(G1... aItemArr)
{
ActionListener[] listenerArr;
listenerArr = getActionListeners();
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
for (G1 aItem : aItemArr)
itemModel.addItem(aItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
/**
* Adds all of the specified items to the model. This method will not trigger an ActionEvent.
*/
public void addItems(Collection<G1> aItemC)
{
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
for (G1 aItem : aItemC)
itemModel.addItem(aItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
@@ -126,17 +163,68 @@ public class GComboBox<G1> extends JComboBox<G1>
/**
* Note aItem must be of the generified type. This method will not trigger an ActionEvent.
*/
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public void removeItem(Object aItem)
{
ActionListener[] listenerArr;
listenerArr = getActionListeners();
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
itemModel.removeItem((G1)aItem);
itemModel.removeItem((G1) aItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
/**
* Method to replace all of the items with the specified list of items.
* <p>
* If the current selection is in the replacement list then the selection will be maintained otherwise it will be
* replaced with the first item in the list.
* <p>
* This method will not trigger an ActionEvent.
*/
public void replaceAllItems(Collection<G1> aItemC)
{
G1 pickItem = getChosenItem();
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
// Replace the items
itemModel.removeAllItems();
for (G1 aItem : aItemC)
itemModel.addItem(aItem);
// Update the selection after the replacement
if (aItemC.contains(pickItem) == false)
pickItem = null;
if (pickItem == null && aItemC.size() > 0)
pickItem = aItemC.iterator().next();
setChosenItem(pickItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
/**
* Method to replace the original item with the provided replacement.
* <p>
* This method will not trigger an ActionEvent.
*/
public void replaceItem(G1 aOrigItem, G1 aReplItem)
{
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
// Delegate
itemModel.replaceItem(aOrigItem, aReplItem);
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
@@ -147,14 +235,12 @@ public class GComboBox<G1> extends JComboBox<G1>
@Override
public void removeAllItems()
{
ActionListener[] listenerArr;
listenerArr = getActionListeners();
var listenerArr = getActionListeners();
for (ActionListener aListener : listenerArr)
removeActionListener(aListener);
itemModel.removeAllItems();
for (ActionListener aListener : listenerArr)
addActionListener(aListener);
}
@@ -166,7 +252,7 @@ public class GComboBox<G1> extends JComboBox<G1>
// {
// throw new RuntimeException("Unsupported operation. Call getChosenItem()");
// }
//
//
// @Override
// public void setSelectedItem(Object aObj)
// {

View File

@@ -1,32 +1,49 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import glum.gui.panel.generic.GenericCodes;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import com.google.common.collect.Lists;
import glum.gui.panel.generic.GenericCodes;
/**
* Base component that provides support for {@link ActionListener} event mechanism.
*
* @author lopeznr1
*/
public class GComponent extends JComponent implements GenericCodes
{
// State vars
protected List<ActionListener> myListeners;
protected List<ActionListener> listenerL;
/** Standard Constructor */
public GComponent()
{
super();
myListeners = Lists.newLinkedList();
listenerL = new ArrayList<>();
}
/**
* Add an ActionListener to this GPanel
*/
public void addActionListener(ActionListener aListener)
{
myListeners.add(aListener);
listenerL.add(aListener);
}
/**
@@ -34,16 +51,16 @@ public class GComponent extends JComponent implements GenericCodes
*/
public void removeActionListener(ActionListener aListener)
{
myListeners.remove(aListener);
listenerL.remove(aListener);
}
/**
* Send out notification to all of the ActionListeners
*/
public void notifyListeners(Object aSource, int aId, String aCommand)
{
for (ActionListener aListener : myListeners)
for (var aListener : listenerL)
aListener.actionPerformed(new ActionEvent(aSource, aId, aCommand));
}
}

View File

@@ -1,25 +1,37 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JLabel;
import glum.unit.UnitListener;
import glum.unit.UnitProvider;
import javax.swing.JLabel;
public class GFancyLabel extends JLabel implements UnitListener
{
// State vars
protected UnitProvider[] unitProviderArr;
protected String[] formatStrArr;
protected Object[] refValueArr;
private UnitProvider[] unitProviderArr;
private String[] formatStrArr;
private Object[] refValueArr;
/**
* Fancy JLabel which provides auto formatting of objects. The constructor
* is provided with a formatStr which has unit place holders specified by "%u"
* There must be a corresponding UnitProvider for each occurrence of "%u". This
* is provided via the variable arguments of UnitProvider.
* Fancy JLabel which provides auto formatting of objects. The constructor is provided with a formatStr which has
* unit place holders specified by "%u" There must be a corresponding UnitProvider for each occurrence of "%u". This
* is provided via the variable arguments of UnitProvider.
*/
public GFancyLabel(String formatStr, UnitProvider... aUnitProviderArr)
{
@@ -27,27 +39,25 @@ public class GFancyLabel extends JLabel implements UnitListener
}
/**
* Fancy JLabel which provides auto formatting of objects. The constructor
* is provided with a formatStr which has unit place holders specified by "%u"
* There must be a corresponding UnitProvider for each occurrence of "%u". This
* is provided via the variable arguments of UnitProvider.
* Fancy JLabel which provides auto formatting of objects. The constructor is provided with a formatStr which has
* unit place holders specified by "%u" There must be a corresponding UnitProvider for each occurrence of "%u". This
* is provided via the variable arguments of UnitProvider.
*/
public GFancyLabel(Font aFont, String aFormatStr, UnitProvider... aUnitProviderArr)
{
super();
if (aFont != null)
setFont(aFont);
formatStrArr = aFormatStr.split("%u", -1);
unitProviderArr = aUnitProviderArr;
for (UnitProvider aUnitProvider : unitProviderArr)
aUnitProvider.addListener(this);
// Insanity check
if (unitProviderArr.length != formatStrArr.length - 1)
throw new RuntimeException("Num place holders: " + (formatStrArr.length - 1) + " Num units: " + unitProviderArr.length);
throw new RuntimeException(
"Num place holders: " + (formatStrArr.length - 1) + " Num units: " + unitProviderArr.length);
refValueArr = new Object[unitProviderArr.length];
for (int c1 = 0; c1 < unitProviderArr.length; c1++)
@@ -63,31 +73,30 @@ public class GFancyLabel extends JLabel implements UnitListener
}
/**
* Method to set in the set of values which will be formatted with the associated UnitProviders
* which were specified via the constructor.
* Method to set in the set of values which will be formatted with the associated UnitProviders which were specified
* via the constructor.
*/
public void setValues(Object... aValueArr)
{
String aStr;
// Ensure the number of objects matches the number of units
if (unitProviderArr.length != aValueArr.length)
throw new RuntimeException("Inproper number of arguments. Expected: " + unitProviderArr.length + " Recieved:" + aValueArr.length);
throw new RuntimeException("Inproper number of arguments. Expected: " + unitProviderArr.length //
+ " Recieved:" + aValueArr.length);
for (int c1 = 0; c1 < aValueArr.length; c1++)
refValueArr[c1] = aValueArr[c1];
aStr = "";
var tmpStr = "";
for (int c1 = 0; c1 < aValueArr.length; c1++)
{
aStr += formatStrArr[c1];
aStr += unitProviderArr[c1].getUnit().getString(aValueArr[c1], false);
tmpStr += formatStrArr[c1];
tmpStr += unitProviderArr[c1].getUnit().getString(aValueArr[c1], false);
}
if (formatStrArr.length > aValueArr.length)
aStr += formatStrArr[formatStrArr.length - 1];
setText(aStr);
if (formatStrArr.length > aValueArr.length)
tmpStr += formatStrArr[formatStrArr.length - 1];
setText(tmpStr);
}
}

View File

@@ -1,15 +1,25 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.Dimension;
import java.awt.Font;
import glum.unit.ConstUnitProvider;
import glum.unit.Unit;
import glum.unit.UnitListener;
import glum.unit.UnitProvider;
import javax.swing.JLabel;
import glum.unit.*;
public class GLabel extends JLabel implements UnitListener
{
// State vars
@@ -34,8 +44,6 @@ public class GLabel extends JLabel implements UnitListener
public GLabel(UnitProvider aUnitProvider, Font aFont, boolean aShowLabel)
{
super();
refUnitProvider = aUnitProvider;
if (refUnitProvider != null)
refUnitProvider.addListener(this);
@@ -62,9 +70,9 @@ public class GLabel extends JLabel implements UnitListener
{
String aStr;
Unit aUnit;
refValue = aValue;
aUnit = null;
if (refUnitProvider != null)
aUnit = refUnitProvider.getUnit();

View File

@@ -1,22 +1,30 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.SwingUtilities;
import java.util.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import glum.gui.component.model.GListModel;
import glum.gui.panel.generic.GenericCodes;
import com.google.common.collect.Lists;
public class GList<G1> extends JComponent implements GenericCodes, ListSelectionListener
{
// Gui vars
@@ -52,9 +60,7 @@ public class GList<G1> extends JComponent implements GenericCodes, ListSelection
*/
public G1 getSelectedItem()
{
int selectedIndex;
selectedIndex = refList.getSelectedIndex();
var selectedIndex = refList.getSelectedIndex();
if (selectedIndex == -1)
return null;
@@ -66,17 +72,14 @@ public class GList<G1> extends JComponent implements GenericCodes, ListSelection
*/
public List<G1> getSelectedItems()
{
ArrayList<G1> retList;
int[] indexArr;
var indexArr = refList.getSelectedIndices();
indexArr = refList.getSelectedIndices();
retList = Lists.newArrayList();
var retItemL = new ArrayList<G1>();
for (int aIndex : indexArr)
retList.add(refModel.getElementAt(aIndex));
retItemL.add(refModel.getElementAt(aIndex));
retList.trimToSize();
return retList;
retItemL.trimToSize();
return retItemL;
}
/**
@@ -104,17 +107,14 @@ public class GList<G1> extends JComponent implements GenericCodes, ListSelection
*/
public void setSelectedItems(List<G1> aItemList)
{
int[] idArr;
int c1;
// Ensure we are executed only on the proper thread
if (SwingUtilities.isEventDispatchThread() == false)
throw new RuntimeException("GList.selectItems() not executed on the AWT event dispatch thread.");
refList.removeListSelectionListener(this);
c1 = 0;
idArr = new int[aItemList.size()];
var c1 = 0;
var idArr = new int[aItemList.size()];
for (G1 aItem : aItemList)
{
idArr[c1] = refModel.indexOf(aItem);

View File

@@ -1,56 +1,86 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.Color;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import com.google.common.collect.Range;
import glum.gui.document.NumberDocument;
import glum.unit.ConstUnitProvider;
import glum.unit.NumberUnit;
import glum.unit.Unit;
import glum.unit.UnitListener;
import glum.unit.UnitProvider;
import glum.unit.*;
public class GNumberField extends JTextField implements DocumentListener, UnitListener
/**
* User interface input used to capture an individual numerical input (type: double).
* <p>
* Unlike JTextField, users of this class should not use getText() / setText() but rather getValue() / setValue()
* methods. Also it should not be necessary to register DocumentListeners - rather an ActionListener should be
* sufficient.
* <p>
* This class provides two modes of converting model values to textual input:
* <ul>
* <li>{@link NumberFormat} mechanism
* <li>{@link UnitProvider} mechanism
* </ul>
*
* @author lopeznr1
*/
public class GNumberField extends GBaseTextField implements DocumentListener, UnitListener
{
// Attributes
private final NumberFormat refFormat;
private final UnitProvider refUnitProvider;
// State vars
protected UnitProvider refUnitProvider;
protected double currValue, minValue, maxValue;
protected boolean isMutating;
private Range<Double> minMaxRange;
private double currValue;
private boolean isMutating;
// Gui vars
protected Color failColor, passColor;
protected NumberDocument myDocument;
private Color colorFail, colorPass;
private NumberDocument myDocument;
/**
* Constructor
*
* Standard Constructor
*
* @param aListener
* : Default ActionListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aUnit
* : Object used to format programatic entered values. Note aUnitProvider will also be used to determine if
* Floating or only Integral input is allowed.
* @param inputType
* : Type of input to accept (Integer, Double, etc...)
* @param aMinVal
* : Minimum value to accept
* @param aMaxVal
* : Maximum value to accept
* Object used to format programmatic entered values. Note aUnitProvider will also be used to determine if
* Floating or only Integral input is allowed.
* @param aMinMaxRange
* The range of values to accept.
*/
public GNumberField(ActionListener aListener, UnitProvider aUnitProvider, double aMinVal, double aMaxVal)
public GNumberField(ActionListener aListener, UnitProvider aUnitProvider, Range<Double> aMinMaxRange)
{
super("", 0);
refFormat = null;
refUnitProvider = aUnitProvider;
currValue = 0;
minValue = aMinVal;
maxValue = aMaxVal;
minMaxRange = aMinMaxRange;
currValue = Double.NaN;
isMutating = false;
failColor = Color.RED.darker();
passColor = getForeground();
colorFail = Color.RED.darker();
colorPass = getForeground();
// Register the ActionListener
if (aListener != null)
@@ -69,31 +99,82 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
installUnit();
}
public GNumberField(ActionListener aListener, Unit aUnit, double aMinVal, double aMaxVal)
/**
* Standard Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aFormat
* NumberFormat used to transform the numerical value to a string.
* @param aMinMaxRange
* The range of values to accept.
*/
public GNumberField(ActionListener aListener, NumberFormat aFormat, Range<Double> aMinMaxRange)
{
this(aListener, new ConstUnitProvider(aUnit), aMinVal, aMaxVal);
super("", 0);
refFormat = aFormat;
refUnitProvider = null;
minMaxRange = aMinMaxRange;
currValue = Double.NaN;
isMutating = false;
colorFail = Color.RED.darker();
colorPass = getForeground();
// Form the appropriate Document and initialize
myDocument = new NumberDocument(this, false);
super.setDocument(myDocument);
// Register the ActionListener
if (aListener != null)
addActionListener(aListener);
// Register for events of interest
myDocument.addDocumentListener(this);
// Force the UI component to reflect the currValue. Note this is done last since this method
// assumes the GNumberField is already registered with myDocument.
forceTF(currValue);
}
/**
* Returns whether the current input is valid
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aUnit
* @param aMinMaxRange
* The range of values to accept.
*/
public boolean isValidInput()
public GNumberField(ActionListener aListener, Unit aUnit, Range<Double> aMinMaxRange)
{
Unit aUnit;
double modelVal;
this(aListener, new ConstUnitProvider(aUnit), aMinMaxRange);
}
// Ensure we have valid input
aUnit = refUnitProvider.getUnit();
/**
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aFormat
* NumberFormat used to transform the numerical value to a string.
*/
public GNumberField(ActionListener aListener, NumberFormat aFormat)
{
this(aListener, aFormat, Range.closed(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
}
modelVal = aUnit.parseString(this.getText(), Double.NaN);
if (Double.isNaN(modelVal) == true)
return false;
// Ensure the value is within range
if (modelVal < minValue || modelVal > maxValue)
return false;
return true;
/**
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
*/
public GNumberField(ActionListener aListener)
{
this(aListener, new DecimalFormat("#.###"), Range.closed(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
}
/**
@@ -110,6 +191,30 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
myDocument.addDocumentListener(this);
}
/**
* Returns the {@link Color} used to change foreground text whenever invalid input is entered.
*/
public Color getColorFail()
{
return colorFail;
}
/**
* Returns the {@link Color} used to change foreground text whenever valid input is entered.
*/
public Color getColorPass()
{
return colorPass;
}
/**
* Returns the range of valid values.
*/
public Range<Double> getMinMaxRange()
{
return minMaxRange;
}
/**
* Returns the currently stored model value
*/
@@ -120,20 +225,65 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
/**
* Returns the currently stored model value as an integer. If the modelValue is NaN, then errorVal will be returned.
* The values MaxInt, MinInt are returned for Infinity.
* The values MAX_VALUE will be returned for +Infinity. The value MIN_VALUE will be returned for -Infinity.
*/
public int getValueAsInt(int errorVal)
public long getValueAsLong(long aErrorVal)
{
if (Double.isNaN(currValue) == true)
return errorVal;
return aErrorVal;
return (int)currValue;
return (long) currValue;
}
/**
* Returns the currently stored model value as an integer. If the modelValue is NaN, then errorVal will be returned.
* The values MAX_VALUE will be returned for +Infinity. The value MIN_VALUE will be returned for -Infinity.
*/
public int getValueAsInt(int aErrorVal)
{
if (Double.isNaN(currValue) == true)
return aErrorVal;
return (int) currValue;
}
/**
* Returns whether the current input is valid
*/
public boolean isValidInput()
{
// Ensure we have valid input
double modelVal = transformToModel(this.getText());
if (Double.isNaN(modelVal) == true)
return false;
// Ensure the value is within range
if (minMaxRange.contains(modelVal) == false)
return false;
return true;
}
/**
* Sets the {@link Color} used to indicate invalid input is entered.
*/
public void setColorFail(Color aColor)
{
colorFail = aColor;
}
/**
* Sets the {@link Color} used to indicate valid input is entered.
*/
public void setColorPass(Color aColor)
{
colorPass = aColor;
}
/**
* Takes in a model value and will display it with respect to the active unit. This method will not trigger an
* ActionEvent.
* <P>
* <p>
* Note this method will do nothing if the UI is being "mutated" when this method is called.
*/
public void setValue(final double aValue)
@@ -143,6 +293,16 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
if (isMutating == true)
return;
// Bail if the value has not changed. We do this so that user
// entered input will not change if the model value has not changed.
double ulp = Math.ulp(aValue);
boolean ignoreInput = true;
ignoreInput &= Double.isNaN(ulp) == false;
ignoreInput &= Double.isFinite(ulp) == true;
ignoreInput &= Math.abs(currValue - aValue) < ulp;
if (ignoreInput == true)
return;
// Simple edit if we are not currently being mutated
forceTF(aValue);
updateGui();
@@ -151,28 +311,26 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
/**
* Changes the range of acceptable values (in model units). Note the current value will be force to fit this range.
*/
public void setMinMaxValue(double aMinValue, double aMaxValue)
public void setMinMaxRange(Range<Double> aMinMaxRange)
{
Unit aUnit;
minValue = aMinValue;
maxValue = aMaxValue;
if (currValue < minValue || currValue > maxValue)
currValue = minValue;
minMaxRange = aMinMaxRange;
if (minMaxRange.hasLowerBound() == true && currValue < minMaxRange.lowerEndpoint())
currValue = minMaxRange.lowerEndpoint();
else if (minMaxRange.hasUpperBound() == true && currValue > minMaxRange.upperEndpoint())
currValue = minMaxRange.upperEndpoint();
// Update our document
aUnit = refUnitProvider.getUnit();
myDocument.setMinMaxValue(aUnit.toUnit(minValue), aUnit.toUnit(maxValue));
}
@Override
public void setDocument(Document aDoc)
{
// throw new UnsupportedOperationException();
if (aDoc != null)
aDoc.addDocumentListener(this);
super.setDocument(aDoc);
double minValue = minMaxRange.lowerEndpoint();
double maxValue = minMaxRange.upperEndpoint();
if (refUnitProvider != null)
{
Unit tmpUnit = refUnitProvider.getUnit();
myDocument.setMinMaxValue(tmpUnit.toUnit(minValue), tmpUnit.toUnit(maxValue));
}
else
{
myDocument.setMinMaxValue(minValue, maxValue);
}
}
@Override
@@ -193,6 +351,16 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
syncValue(aEvent);
}
@Override
public void setDocument(Document aDoc)
{
// throw new UnsupportedOperationException();
if (aDoc != null)
aDoc.addDocumentListener(this);
super.setDocument(aDoc);
}
@Override
public void unitChanged(UnitProvider aProvider, String aKey)
{
@@ -204,14 +372,11 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
*/
protected void forceTF(double aValue)
{
Unit aUnit;
String aStr;
// Save off the new model value, and check the validity
currValue = aValue;
if (currValue < minValue || currValue > maxValue)
if (minMaxRange.contains(currValue) == false)
currValue = Double.NaN;
// throw new RuntimeException("Programatic input is invalid. Is unit compatible? Input: " + aValue);
// throw new RuntimeException("Programmatic input is invalid. Is unit compatible? Input: " + aValue);
// Invalid values shall just clear the text field and bail
if (Double.isNaN(currValue) == true)
@@ -220,13 +385,12 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
return;
}
// Convert from model value to (unit) textual format
aUnit = refUnitProvider.getUnit();
aStr = aUnit.getString(currValue);
// Convert from model value to text
String tmpStr = transformToString(currValue);
// Update the GUI internals
myDocument.removeDocumentListener(this);
setText(aStr);
setText(tmpStr);
setCaretPosition(0);
myDocument.addDocumentListener(this);
}
@@ -236,20 +400,17 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
*/
protected void installUnit()
{
Unit aUnit;
boolean aBool;
// Ensure that we have a valid Unit
aUnit = refUnitProvider.getUnit();
if (aUnit instanceof NumberUnit == false)
throw new RuntimeException("refUnitProvider must return a Unit of type NumberUnit. Unit: " + aUnit);
Unit tmpUnit = refUnitProvider.getUnit();
if (tmpUnit instanceof NumberUnit == false)
throw new RuntimeException("refUnitProvider must return a Unit of type NumberUnit. Unit: " + tmpUnit);
// Update our Document to reflect whether this Unit supports floating point numbers
aBool = (aUnit instanceof NumberUnit) && (((NumberUnit)aUnit).isFloating() == true);
myDocument.setAllowFloats(aBool);
boolean tmpBool = (tmpUnit instanceof NumberUnit) && (((NumberUnit) tmpUnit).isFloating() == true);
myDocument.setAllowFloats(tmpBool);
// Update the Document's MinMax values reflect the new Unit
setMinMaxValue(minValue, maxValue);
setMinMaxRange(minMaxRange);
// Force myDocument's text to match the new unit
forceTF(currValue);
@@ -258,19 +419,16 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
/**
* Keeps the "model" value conceptually linked to the GUI component. It will also trigger the actionEventListeners.
*/
protected void syncValue(DocumentEvent e)
protected void syncValue(DocumentEvent aEvent)
{
Unit aUnit;
// Mark ourself as mutating
isMutating = true;
// Convert the textual (unit) value to the model value
aUnit = refUnitProvider.getUnit();
currValue = aUnit.parseString(this.getText(), Double.NaN);
// Convert the string to the model value
currValue = transformToModel(this.getText());
// If the value is not in range then, it is invalid
if (currValue < minValue || currValue > maxValue)
if (minMaxRange.contains(currValue) == false)
currValue = Double.NaN;
// Notify our listeners and update the GUI
@@ -286,13 +444,55 @@ public class GNumberField extends JTextField implements DocumentListener, UnitLi
*/
protected void updateGui()
{
Color aColor;
aColor = passColor;
Color tmpColor = colorPass;
if (isValidInput() == false)
aColor = failColor;
tmpColor = colorFail;
setForeground(aColor);
setForeground(tmpColor);
}
/**
* Helper method that will take a given value and convert it to a string.
*
* @param aValue
*/
private String transformToString(double aValue)
{
// Convert from model value to (unit) textual format
if (refUnitProvider != null)
{
Unit tmpUnit = refUnitProvider.getUnit();
String tmpStr = tmpUnit.getString(aValue);
return tmpStr;
}
return refFormat.format(aValue);
}
/**
* Helper method that will take a String and convert it to the equivalent numerical value. On failure Double.NaN will
* be returned.
*
* @param aValue
*/
private double transformToModel(String aStr)
{
// Convert the textual (unit) value to the model value
if (refUnitProvider != null)
{
Unit tmpUnit = refUnitProvider.getUnit();
double retValue = tmpUnit.parseString(aStr, Double.NaN);
return retValue;
}
try
{
return Double.parseDouble(aStr);
}
catch (NumberFormatException aExp)
{
return Double.NaN;
}
}
}

View File

@@ -0,0 +1,218 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JPanel;
import com.google.common.collect.Range;
import glum.gui.GuiUtil;
import net.miginfocom.swing.MigLayout;
/**
* User interface component that combines a {@link GNumberField} and a {@link GSlider} into a single unified component.
*
* @author lopeznr1
*/
public class GNumberFieldSlider extends JPanel implements ActionListener
{
// Ref vars
private final ActionListener refLister;
// Gui vars
private GNumberField valueNF;
private GSlider valueS;
/**
* Standard Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aFormat
* NumberFormat used to transform the numerical value to a string.
* @param aMinMaxRange
* The range of values to accept.
* @param aNumColumns
* The number of columns associated with the {@link GNumberField}.
*/
public GNumberFieldSlider(ActionListener aListener, NumberFormat aFormat, Range<Double> aMinMaxRange,
int aNumColumns)
{
refLister = aListener;
buildGui(aFormat, aMinMaxRange);
setNumColumns(aNumColumns);
setNumSteps(100);
}
/**
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aFormat
* NumberFormat used to transform the numerical value to a string.
* @param aMinMaxRange
* The range of values to accept.
*/
public GNumberFieldSlider(ActionListener aListener, NumberFormat aFormat, Range<Double> aMinMaxRange)
{
this(aListener, aFormat, aMinMaxRange, 4);
}
/**
* Returns whether the current input is valid
*/
public boolean isValidInput()
{
// Delegate
return valueNF.isValidInput();
}
/**
* Returns the selected value.
*/
public double getValue()
{
return valueNF.getValue();
}
/**
* Returns the currently stored model value as an integer.
* <p>
* See {@link GNumberField#getValueAsInt(int)}
*/
public int getValueAsInt(int aErrorVal)
{
return valueNF.getValueAsInt(aErrorVal);
}
/**
* Returns true if the value is being actively adjusted.
* <p>
* See also {@link GSlider#getValueIsAdjusting()}
*/
public boolean getValueIsAdjusting()
{
// Delegate
return valueS.getValueIsAdjusting();
}
/**
* Sets in the selected value. Note no events will be fired.
*/
public void setValue(double aVal)
{
valueNF.setValue(aVal);
valueS.setModelValue(aVal);
}
/**
* Set the editable state of the UI component.
*/
public void setEditable(boolean aBool)
{
valueNF.setEditable(aBool);
valueS.setEnabled(aBool);
}
/**
* Set the enable state of the UI component.
*/
@Override
public void setEnabled(boolean aBool)
{
GuiUtil.setEnabled(this, aBool);
}
/**
* Sets in the steps to be an integral value.
* <p>
* The minVal and maxVal must be integers otherwise this method will throw an exception. The number of steps will be:
* (maxVal - minVal).
*/
public void setIntegralSteps()
{
var tmpMinMaxRange = valueNF.getMinMaxRange();
double tmpMinVal = tmpMinMaxRange.lowerEndpoint();
double tmpMaxVal = tmpMinMaxRange.upperEndpoint();
int intMaxVal = (int) tmpMaxVal;
int intMinVal = (int) tmpMinVal;
var isIntegral = true;
isIntegral &= tmpMinVal - intMinVal == 0;
isIntegral &= tmpMaxVal - intMaxVal == 0;
if (isIntegral == false)
throw new RuntimeException("Min,Max values are not integral: [" + tmpMinVal + ", " + tmpMaxVal + "]");
// Delegate
int numSteps = intMaxVal - intMinVal;
setNumSteps(numSteps);
}
/**
* Sets in the number of columns for the associated GTextField.
*/
public void setNumColumns(int aNumColumns)
{
valueNF.setColumns(aNumColumns);
}
/**
* Sets in the number of steps associated with the slider.
*/
public void setNumSteps(int aNumSteps)
{
valueS.setNumSteps(aNumSteps);
}
@Override
public void actionPerformed(ActionEvent aEvent)
{
var source = aEvent.getSource();
if (source == valueNF)
{
double tmpVal = valueNF.getValue();
valueS.setModelValue(tmpVal);
}
else if (source == valueS)
{
double tmpVal = valueS.getModelValue();
valueNF.setValue(tmpVal);
}
var tmpEvent = new ActionEvent(this, 0, "");
refLister.actionPerformed(tmpEvent);
}
/**
* Helper method that builds the unified GUI
*/
private void buildGui(NumberFormat aNumberFormat, Range<Double> aMinMaxRange)
{
valueNF = new GNumberField(this, aNumberFormat, aMinMaxRange);
valueS = new GSlider(this, aMinMaxRange);
setLayout(new MigLayout("", "0[]0", "0[]0"));
add(valueNF, "w 40:");
add(valueS, "growx,pushx");
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.event.ActionListener;

View File

@@ -1,46 +1,91 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.google.common.collect.Range;
/**
* User interface input used to capture an individual numerical input (type: double).
* <p>
* Unlike JSlider, users of this class should not use getValue() / setValue() but rather getModelValue() /
* setModelValue() methods. Also it should not be necessary to register ChangeListeners - rather an ActionListener
* should be sufficient.
*
* @author lopeznr1
*/
public class GSlider extends JSlider implements ChangeListener
{
private ActionListener myListener;
private double minVal, maxVal, rngVal;
// Attributes
private final ActionListener refListener;
// State vars
private Range<Double> minMaxRange;
private int maxSteps;
public GSlider(ActionListener aListener, int aMaxSteps, double aMinVal, double aMaxVal)
/**
* Standard Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aMinMaxRange
* The range of values to accept.
* @param aMaxSteps
* The number of steps associated with the slider.
*/
public GSlider(ActionListener aListener, Range<Double> aMinMaxRange, int aMaxSteps)
{
super(0, aMaxSteps);
addChangeListener(this);
myListener = aListener;
refListener = aListener;
minMaxRange = aMinMaxRange;
maxSteps = aMaxSteps;
minVal = aMinVal;
maxVal = aMaxVal;
rngVal = maxVal - minVal;
}
public GSlider(ActionListener aListener, double aMinVal, double aMaxVal)
/**
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aMinMaxRange
* The range of values to accept.
*/
public GSlider(ActionListener aListener, Range<Double> aMinMaxRange)
{
this(aListener, 1000, aMinVal, aMaxVal);
this(aListener, aMinMaxRange, 1000);
}
/**
* Returns the model value for which this slider is currently set to.
* <P>
* <p>
* Use this method over {@link JSlider#getValue()}
*/
public double getModelValue()
{
double retVal;
double minVal = minMaxRange.lowerEndpoint();
double maxVal = minMaxRange.upperEndpoint();
double rngVal = maxVal - minVal;
retVal = minVal + ((super.getValue() / (double)maxSteps) * rngVal);
double retVal = minVal + ((super.getValue() / (double) maxSteps) * rngVal);
return retVal;
}
@@ -48,11 +93,13 @@ public class GSlider extends JSlider implements ChangeListener
* Takes in the model's minVal and maxVal range. The current chosen model value will be adjusted to be in the middle
* of the range.
*/
public void setModelRange(double aMinVal, double aMaxVal)
public void setModelRange(Range<Double> aMinMaxRange)
{
minVal = aMinVal;
maxVal = aMaxVal;
rngVal = maxVal - minVal;
minMaxRange = aMinMaxRange;
double minVal = minMaxRange.lowerEndpoint();
double maxVal = minMaxRange.upperEndpoint();
double rngVal = maxVal - minVal;
setModelValue(minVal + rngVal / 2);
}
@@ -60,17 +107,37 @@ public class GSlider extends JSlider implements ChangeListener
/**
* Takes in a model value and will adjust the slider to display the value. Note this method will not trigger an
* ActionEvent.
* <P>
* <p>
* Use this method over {@link JSlider#setValue}
*/
public void setModelValue(double aVal)
{
double guiVal;
guiVal = ((aVal - minVal) / rngVal) * maxSteps;
double minVal = minMaxRange.lowerEndpoint();
double maxVal = minMaxRange.upperEndpoint();
double rngVal = maxVal - minVal;
removeChangeListener(this);
setValue((int)guiVal);
double guiVal = ((aVal - minVal) / rngVal) * maxSteps;
setValue((int) guiVal);
addChangeListener(this);
}
/**
* Sets in the number of steps associated with the GSlider.
* <p>
* Values will be uniformly distributed over the range / numSteps
*
* @param aNumSteps
* The number of steps the slider should have.
*/
public void setNumSteps(int aNumSteps)
{
removeChangeListener(this);
setMinimum(0);
setMaximum(aNumSteps);
maxSteps = aNumSteps;
addChangeListener(this);
}
@@ -80,12 +147,26 @@ public class GSlider extends JSlider implements ChangeListener
notifyLisener();
}
@Override
@Deprecated
public int getValue()
{
return super.getValue();
}
@Override
@Deprecated
public void setValue(int n)
{
super.setValue(n);
}
/**
* Helper method to notify our listener
*/
private void notifyLisener()
{
myListener.actionPerformed(new ActionEvent(this, 0, "update"));
refListener.actionPerformed(new ActionEvent(this, 0, "update"));
}
}

View File

@@ -1,21 +1,49 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class GTextField extends JTextField implements DocumentListener
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
/**
* User interface input used to capture an input string.
* <p>
* Unlike JTextField, users of this class should not use getText() / setText() but rather getValue() / setValue()
* methods. Also it should not be necessary to register DocumentListeners - rather an ActionListener should be
* sufficient.
*
* @author lopeznr1
*/
public class GTextField extends GBaseTextField implements DocumentListener
{
/**
* Constructor
*
* Standard Constructor
*
* @param aListener
* : Default ActionListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aLabel
* The text value to use as the initial input.
* @param aHint
* The hint to show when no input has been entered.
*/
public GTextField(ActionListener aListener)
public GTextField(ActionListener aListener, String aLabel, String aHint)
{
super("", 0);
super(aLabel, 0);
if (aListener != null)
addActionListener(aListener);
@@ -27,6 +55,35 @@ public class GTextField extends JTextField implements DocumentListener
// Register for events of interest
doc.addDocumentListener(this);
if (aHint != null)
setHint(aHint);
forceTF(aLabel);
}
/**
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
* @param aLabel
* The text value to use as the initial input.
*/
public GTextField(ActionListener aListener, String aLabel)
{
this(aListener, aLabel, null);
}
/**
* Simplified Constructor
*
* @param aListener
* An ActionListener that will be notified when ever the user makes any input changes.
*/
public GTextField(ActionListener aListener)
{
this(aListener, "", null);
}
/**

View File

@@ -1,76 +0,0 @@
package glum.gui.component;
import javax.swing.Icon;
import javax.swing.JToggleButton;
public class GToggle extends JToggleButton
{
// State vars
protected boolean isActive;
// Gui vars
protected Icon falseIcon, trueIcon;
public GToggle(Icon aFalseIcon, Icon aTrueIcon, boolean aIsActive)
{
super();
falseIcon = aFalseIcon;
trueIcon = aTrueIcon;
setSelected(aIsActive);
setModel(new GToggleButtonModel());
}
@Override
public void setSelected(boolean b)
{
super.setSelected(b);
updateGui();
}
@Override
public void doClick(int pressTime)
{
super.doClick(pressTime);
updateGui();
}
/**
* Utility method
*/
private void updateGui()
{
if (isSelected() == true)
setIcon(trueIcon);
else
setIcon(falseIcon);
}
/**
* The ToggleButton model
* <p>
* <strong>Warning:</strong> Serialized objects of this class will not be compatible with future Swing releases. The
* current serialization support is appropriate for short term storage or RMI between applications running the same
* version of Swing. As of 1.4, support for long term storage of all JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package. Please see {@link java.beans.XMLEncoder}.
*/
public class GToggleButtonModel extends ToggleButtonModel
{
/**
* Creates a new ToggleButton Model
*/
public GToggleButtonModel()
{
}
@Override
public void setSelected(boolean b)
{
super.setSelected(b);
updateGui();
}
}
}

View File

@@ -1,11 +1,25 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component.banner;
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import glum.gui.*;
import javax.swing.JComponent;
import glum.io.ParseUtil;
import glum.io.token.MatchTokenizer;
import glum.io.token.Tokenizer;
@@ -37,7 +51,7 @@ public class Banner extends JComponent
double sX, sY, offSetY;
super.paintComponent(g);
g2d = (Graphics2D)g;
g2d = (Graphics2D) g;
// Determine the window boundaries
winW = getWidth();
@@ -72,7 +86,7 @@ public class Banner extends JComponent
sY = winH / 2.0 - msgH / 2.0;
g2d.setFont(myConfig.font);
g2d.setColor(myConfig.fgColor);
g2d.drawString(displayMsg, (int)sX, (int)(sY + offSetY));
g2d.drawString(displayMsg, (int) sX, (int) (sY + offSetY));
}
/**
@@ -102,8 +116,8 @@ public class Banner extends JComponent
}
/**
* Utility method that converts a string to a BannerConfig. Eventually this method class should be
* moved to a utility class of sorts.
* Utility method that converts a string to a BannerConfig. Eventually this method class should be moved to a utility
* class of sorts.
*/
public static BannerConfig readBannerConfig(String strLine)
{
@@ -128,7 +142,7 @@ public class Banner extends JComponent
for (String aInstr : instrSet)
{
parmSet = parmTokenizer.getTokens(aInstr);
parms = parmSet.toArray(new String[] {""});
parms = parmSet.toArray(new String[] { "" });
if (parms.length == 0)
{
@@ -152,15 +166,15 @@ public class Banner extends JComponent
size = 12;
if (parms.length > 2)
size = GuiUtil.readInt(parms[2], 12);
size = ParseUtil.readInt(parms[2], 12);
bold = false;
if (parms.length > 3)
bold = GuiUtil.readBoolean(parms[3], false);
bold = ParseUtil.readBoolean(parms[3], false);
italic = false;
if (parms.length > 4)
italic = GuiUtil.readBoolean(parms[4], false);
italic = ParseUtil.readBoolean(parms[4], false);
style = 0;
if (bold == false && italic == false)
@@ -176,22 +190,22 @@ public class Banner extends JComponent
{
int r, g, b;
r = GuiUtil.readRangeInt(parms[1], 0, 255, 255);
g = GuiUtil.readRangeInt(parms[2], 0, 255, 255);
b = GuiUtil.readRangeInt(parms[3], 0, 255, 255);
r = ParseUtil.readRangeInt(parms[1], 0, 255, 255);
g = ParseUtil.readRangeInt(parms[2], 0, 255, 255);
b = ParseUtil.readRangeInt(parms[3], 0, 255, 255);
aConfig.fgColor = new Color(r, g, b);
}
else if (parms[0].equalsIgnoreCase("bgColor") == true && parms.length >= 4)
{
int r, g, b, a;
r = GuiUtil.readRangeInt(parms[1], 0, 255, 255);
g = GuiUtil.readRangeInt(parms[2], 0, 255, 255);
b = GuiUtil.readRangeInt(parms[3], 0, 255, 255);
r = ParseUtil.readRangeInt(parms[1], 0, 255, 255);
g = ParseUtil.readRangeInt(parms[2], 0, 255, 255);
b = ParseUtil.readRangeInt(parms[3], 0, 255, 255);
a = 255;
if (parms.length > 4)
a = GuiUtil.readRangeInt(parms[4], 0, 255, 255);
a = ParseUtil.readRangeInt(parms[4], 0, 255, 255);
aConfig.bgColor = new Color(r, g, b, a);
}
@@ -199,20 +213,20 @@ public class Banner extends JComponent
{
int r, g, b;
r = GuiUtil.readRangeInt(parms[1], 0, 255, 255);
g = GuiUtil.readRangeInt(parms[2], 0, 255, 255);
b = GuiUtil.readRangeInt(parms[3], 0, 255, 255);
r = ParseUtil.readRangeInt(parms[1], 0, 255, 255);
g = ParseUtil.readRangeInt(parms[2], 0, 255, 255);
b = ParseUtil.readRangeInt(parms[3], 0, 255, 255);
aConfig.borderColor = new Color(r, g, b);
if (parms.length > 4)
aConfig.borderWidth = GuiUtil.readRangeInt(parms[4], 0, 10, 0);
aConfig.borderWidth = ParseUtil.readRangeInt(parms[4], 0, 10, 0);
if (parms.length > 5)
aConfig.borderPad = GuiUtil.readRangeInt(parms[5], -20, 20, 0);
aConfig.borderPad = ParseUtil.readRangeInt(parms[5], -20, 20, 0);
}
else if (parms[0].equalsIgnoreCase("repeatMsg") == true && parms.length == 2)
{
aConfig.numRepeats = GuiUtil.readRangeInt(parms[1], -1, 100, 0);
aConfig.numRepeats = ParseUtil.readRangeInt(parms[1], -1, 100, 0);
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component.banner;
import java.awt.*;

View File

@@ -1,26 +1,51 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component.model;
import java.util.Collection;
import javax.swing.ComboBoxModel;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableList;
import glum.gui.component.GComboBox;
/**
* Implementation of {@link ComboBoxModel} that is used with {@link GComboBox}.
*
* @author lopeznr1
*/
public class GComboBoxModel<G1> extends GListModel<G1> implements ComboBoxModel<G1>
{
protected G1 chosenItem;
private G1 chosenItem;
public GComboBoxModel(G1... aItemArr)
/**
* Standard Constructor
*/
public GComboBoxModel(Collection<G1> aItemC)
{
this(Lists.newArrayList(aItemArr));
}
public GComboBoxModel(Collection<G1> aItemList)
{
super(aItemList);
super(aItemC);
chosenItem = null;
if (itemList.size() > 0)
chosenItem = itemList.get(0);
if (itemL.size() > 0)
chosenItem = itemL.get(0);
}
@SafeVarargs
public GComboBoxModel(G1... aItemArr)
{
this(ImmutableList.copyOf(aItemArr));
}
@Override
@@ -38,17 +63,18 @@ public class GComboBoxModel<G1> extends GListModel<G1> implements ComboBoxModel<
super.removeItem(aItem);
chosenItem = null;
if (itemList.size() > 0)
chosenItem = itemList.get(0);
if (itemL.size() > 0)
chosenItem = itemL.get(0);
}
/**
* Note aItem must be of the Generified type
*/
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public void setSelectedItem(Object aItem)
{
chosenItem = (G1)aItem;
chosenItem = (G1) aItem;
}
@Override

View File

@@ -1,79 +1,98 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.component.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
import javax.swing.AbstractListModel;
import com.google.common.collect.Lists;
/**
* Generified mutable ListModel
*
* @author lopeznr1
*/
public class GListModel<G1> extends AbstractListModel<G1>
{
protected List<G1> itemList;
protected final List<G1> itemL;
public GListModel(Collection<G1> aItemList)
/**
* Standard Constructor
*/
public GListModel(Collection<G1> aItemC)
{
itemList = Lists.newArrayList(aItemList);
itemL = new ArrayList<>(aItemC);
}
// public GListModel(G1... aItemArr)
// {
// itemList = Lists.newArrayList(aItemArr);
// }
//
/**
* Adds aItem to this model
*/
public void addItem(G1 aItem)
{
int index;
itemList.add(aItem);
index = itemList.size() - 1;
itemL.add(aItem);
var index = itemL.size() - 1;
fireIntervalAdded(this, index, index);
}
/**
* Removes aItem from this model
*/
public void removeItem(G1 aItem)
{
int index;
index = itemList.indexOf(aItem);
itemList.remove(aItem);
var index = itemL.indexOf(aItem);
itemL.remove(aItem);
fireIntervalRemoved(this, index, index);
}
/**
* Removes all the items from this model
*/
public void removeAllItems()
{
int lastIndex;
// Bail if the list is empty
if (itemList.isEmpty() == true)
if (itemL.isEmpty() == true)
return;
lastIndex = itemList.size() - 1;
itemList.clear();
var lastIndex = itemL.size() - 1;
itemL.clear();
fireIntervalRemoved(this, 0, lastIndex);
}
/**
* Replaces the original item with the provided replacement.
* <p>
* Throws an exception if the original item is not installed.
*/
public void replaceItem(G1 aOrigItem, G1 aReplItem)
{
int tmpIdx = itemL.indexOf(aOrigItem);
if (tmpIdx == -1)
throw new RuntimeException("The original item is not in the list");
itemL.set(tmpIdx, aReplItem);
fireContentsChanged(this, tmpIdx, tmpIdx);
}
/**
* Returns a list of all the items
*/
public ArrayList<G1> getAllItems()
public List<G1> getAllItems()
{
return Lists.newArrayList(itemList);
return new ArrayList<>(itemL);
}
/**
@@ -81,18 +100,18 @@ public class GListModel<G1> extends AbstractListModel<G1>
*/
public int indexOf(G1 aItem)
{
return itemList.indexOf(aItem);
return itemL.indexOf(aItem);
}
@Override
public int getSize()
{
return itemList.size();
return itemL.size();
}
@Override
public G1 getElementAt(int index)
{
return itemList.get(index);
return itemL.get(index);
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dnd;
import java.awt.datatransfer.Transferable;
@@ -6,19 +19,20 @@ import javax.swing.JComponent;
import javax.swing.TransferHandler;
/**
* Generic TransferHandler that supports transferring an arbitrary Transferable. Note that before the DnD transfer
* mechanism is triggered via the method exportAsDrag(), the developer must set in the Transferable via the method
* setWorkTransferable().
* Generic {@link TransferHandler} that supports transferring an arbitrary {@link Transferable}. Note that before the
* DnD transfer mechanism is triggered via the method exportAsDrag(), the developer must set in the {@link Transferable}
* via the method {@link #setWorkTransferable(Transferable)}.
*
* @author lopeznr1
*/
public class PlainTransferHandler extends TransferHandler
{
// State vars
protected Transferable workTransferable;
/** Standard Constructor */
public PlainTransferHandler()
{
super();
workTransferable = null;
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import javax.swing.Icon;
@@ -11,18 +24,16 @@ public class BaseDockable extends DefaultDockable
// Tells whether this Dockable can be dragged and dropped to another station
private DockStation homeStation;
private boolean isTransferable;
public BaseDockable()
{
super();
isTransferable = true;
}
public BaseDockable(JComponent aComp, String aTitle, Icon aIcon)
{
super(aComp, aTitle, aIcon);
isTransferable = true;
}
@@ -30,21 +41,19 @@ public class BaseDockable extends DefaultDockable
{
if (isTransferable == true)
return true;
// We can only be transfered to our homeStation when we are not transferable
return aStation == homeStation;
}
public void setTransferable(boolean aBool)
{
homeStation = null;
isTransferable = aBool;
// Record our parent when we become non transferable
if (isTransferable == false)
homeStation = getDockParent();
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import glum.gui.dock.action.Closeable;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import bibliothek.gui.DockStation;

View File

@@ -1,14 +1,26 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.Icon;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import bibliothek.gui.DockController;
import bibliothek.gui.DockFrontend;
import bibliothek.gui.DockStation;
@@ -20,6 +32,11 @@ import bibliothek.gui.dock.action.actions.SimpleButtonAction;
import bibliothek.gui.dock.station.screen.ScreenFullscreenAction;
import bibliothek.gui.dock.station.split.SplitFullScreenAction;
/**
* Collection of utility methods useful for working dockables / dock stations.
*
* @author lopeznr1
*/
public class DockUtil
{
/**
@@ -27,14 +44,14 @@ public class DockUtil
*/
public static SimpleButtonAction createAction(String aText, Icon aIcon, ActionListener aListener)
{
SimpleButtonAction aAction;
SimpleButtonAction retAction;
aAction = new SimpleButtonAction();
aAction.setText(aText);
aAction.setIcon(aIcon);
aAction.addActionListener(aListener);
retAction = new SimpleButtonAction();
retAction.setText(aText);
retAction.setIcon(aIcon);
retAction.addActionListener(aListener);
return aAction;
return retAction;
}
/**
@@ -44,24 +61,24 @@ public class DockUtil
*/
public static DockAction createFullScreenAction(DockStation aStation, DockController aController)
{
DockAction fullScreenAction;
DockAction retAction;
if (aStation instanceof SplitDockStation)
{
fullScreenAction = new SplitFullScreenAction((SplitDockStation)aStation);
((SplitFullScreenAction)fullScreenAction).setController(aController);
retAction = new SplitFullScreenAction((SplitDockStation) aStation);
((SplitFullScreenAction) retAction).setController(aController);
}
else if (aStation instanceof ScreenDockStation)
{
fullScreenAction = new ScreenFullscreenAction((ScreenDockStation)aStation);
((ScreenFullscreenAction)fullScreenAction).setController(aController);
retAction = new ScreenFullscreenAction((ScreenDockStation) aStation);
((ScreenFullscreenAction) retAction).setController(aController);
}
else
{
throw new RuntimeException("Unsupported Dockable type: " + aStation);
}
return fullScreenAction;
return retAction;
}
/**
@@ -75,7 +92,7 @@ public class DockUtil
{
evalDockable = aStation.getDockable(c1);
if (evalDockable instanceof DockStation)
evalDockable = findDockable((DockStation)evalDockable, aClass);
evalDockable = findDockable((DockStation) evalDockable, aClass);
if (evalDockable.getClass() == aClass)
return aClass.cast(evalDockable);
@@ -90,19 +107,19 @@ public class DockUtil
*/
public static List<Dockable> findDockableList(DockFrontend aFrontend, Class<?>... aClassArr)
{
Set<Class<?>> classSet;
List<Dockable> itemList;
Set<Class<?>> tmpClassS;
List<Dockable> retItemL;
// Transform the match class array to a set
classSet = Sets.newHashSet();
tmpClassS = new HashSet<>();
for (Class<?> aClass : aClassArr)
classSet.add(aClass);
tmpClassS.add(aClass);
itemList = Lists.newLinkedList();
retItemL = new ArrayList<>();
for (DockStation aStation : aFrontend.getRoots())
findDockableList(aStation, classSet, itemList);
findDockableList(aStation, tmpClassS, retItemL);
return itemList;
return retItemL;
}
/**
@@ -111,18 +128,18 @@ public class DockUtil
*/
public static <G1 extends Dockable> List<G1> findDockableList(DockFrontend aFrontend, Class<G1> aClass)
{
Set<Class<?>> classSet;
List<G1> itemList;
Set<Class<?>> tmpClassS;
List<G1> retItemL;
// Transform the match class array to a set
classSet = Sets.newHashSet();
classSet.add(aClass);
tmpClassS = new HashSet<>();
tmpClassS.add(aClass);
itemList = Lists.newLinkedList();
retItemL = new ArrayList<>();
for (DockStation aStation : aFrontend.getRoots())
findDockableList(aStation, classSet, itemList);
findDockableList(aStation, tmpClassS, retItemL);
return itemList;
return retItemL;
}
/**
@@ -131,18 +148,18 @@ public class DockUtil
*/
public static List<Dockable> findDockableList(DockStation aStation, Class<?>... aClassArr)
{
Set<Class<?>> classSet;
List<Dockable> itemList;
Set<Class<?>> tmpClassS;
List<Dockable> retItemL;
// Transform the match class array to a set
classSet = Sets.newHashSet();
tmpClassS = new HashSet<>();
for (Class<?> aClass : aClassArr)
classSet.add(aClass);
tmpClassS.add(aClass);
itemList = Lists.newLinkedList();
findDockableList(aStation, classSet, itemList);
retItemL = new ArrayList<>();
findDockableList(aStation, tmpClassS, retItemL);
return itemList;
return retItemL;
}
/**
@@ -151,32 +168,32 @@ public class DockUtil
*/
public static <G1 extends Dockable> List<G1> findDockableList(DockStation aStation, Class<G1> aClass)
{
Set<Class<?>> classSet;
List<G1> itemList;
Set<Class<?>> tmpClassS;
List<G1> retItemL;
// Transform the match class array to a set
classSet = Sets.newHashSet();
classSet.add(aClass);
tmpClassS = new HashSet<>();
tmpClassS.add(aClass);
itemList = Lists.newLinkedList();
findDockableList(aStation, classSet, itemList);
retItemL = new ArrayList<>();
findDockableList(aStation, tmpClassS, retItemL);
return itemList;
return retItemL;
}
/**
* Helper method to remove all PlotGroupStations and ChartDockables
*/
public static <G1 extends Dockable> void removeAllDockablesOfType(DockFrontend aFrontend, Class<?>... dockTypeArr)
public static <G1 extends Dockable> void removeAllDockablesOfType(DockFrontend aFrontend, Class<?>... aDockTypeArr)
{
List<Dockable> dockList;
List<Dockable> dockL;
DockStation dockStation;
// Gather all of the Dockables of interest
dockList = DockUtil.findDockableList(aFrontend, dockTypeArr);
dockL = DockUtil.findDockableList(aFrontend, aDockTypeArr);
// Remove all of the Dockables
for (Dockable aDock : dockList)
for (Dockable aDock : dockL)
{
dockStation = aDock.getDockParent();
if (dockStation != null)
@@ -189,24 +206,25 @@ public class DockUtil
* results will be stored in aItemList
*/
@SuppressWarnings("unchecked")
private static <G1 extends Dockable> void findDockableList(DockStation aStation, Set<Class<?>> aClassSet, List<G1> aItemList)
private static <G1 extends Dockable> void findDockableList(DockStation aStation, Set<Class<?>> aClassS,
List<G1> aItemL)
{
Dockable evalDockable;
for (int c1 = 0; c1 < aStation.getDockableCount(); c1++)
{
evalDockable = aStation.getDockable(c1);
for (Class<?> aClass : aClassSet)
for (Class<?> aClass : aClassS)
{
if (aClass.isAssignableFrom(evalDockable.getClass()) == true)
{
aItemList.add((G1)evalDockable);
aItemL.add((G1) evalDockable);
break;
}
}
if (evalDockable instanceof DockStation)
findDockableList((DockStation)evalDockable, aClassSet, aItemList);
findDockableList((DockStation) evalDockable, aClassS, aItemL);
}
}

View File

@@ -1,23 +1,38 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import java.awt.*;
import java.awt.Component;
import java.awt.event.ActionEvent;
import bibliothek.gui.DockFrontend;
import glum.gui.panel.generic.BaseTextInputPanel;
import glum.gui.panel.generic.TextInputPanel;
public class FrontendAddConfigPanel extends TextInputPanel
/**
* UI component that allows the creation of a docking configuration.
*
* @author lopeznr1
*/
public class FrontendAddConfigPanel extends BaseTextInputPanel
{
// Constants
public static final String DEFAULT_NAME = "Default";
// State vars
protected DockFrontend refFrontend;
// Ref vars
private final DockFrontend refFrontend;
/**
* Constructor
*/
/** Standard Constructor */
public FrontendAddConfigPanel(Component aParent, DockFrontend aFrontend)
{
super(aParent);
@@ -32,14 +47,11 @@ public class FrontendAddConfigPanel extends TextInputPanel
@Override
public void actionPerformed(ActionEvent e)
{
Object source;
String configName;
// Save of the configuration
source = e.getSource();
var source = e.getSource();
if (source == acceptB)
{
configName = getInput();
var configName = getInput();
refFrontend.save(configName);
}
@@ -50,16 +62,14 @@ public class FrontendAddConfigPanel extends TextInputPanel
@Override
protected void updateGui()
{
String inputStr, infoMsg;
boolean isEnabled;
// Assume the GUI is invalid
isEnabled = false;
var isEnabled = false;
// Retrieve the name
inputStr = inputTF.getText();
var inputStr = inputTF.getText();
// Determine the validity of specified name
String infoMsg;
if (inputStr.equals("") == true)
{
infoMsg = "Please enter a valid configuration name.";

View File

@@ -1,21 +1,29 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
//import echo.gui.LookUp;
import com.google.common.collect.Lists;
import bibliothek.gui.DockFrontend;
import glum.database.QueryItem;
import glum.gui.FocusUtil;
import glum.gui.GuiUtil;
@@ -25,24 +33,27 @@ import glum.gui.panel.itemList.ItemListPanel;
import glum.gui.panel.itemList.StaticItemProcessor;
import glum.gui.panel.itemList.query.QueryComposer;
import glum.gui.panel.itemList.query.QueryItemHandler;
import bibliothek.gui.DockFrontend;
import net.miginfocom.swing.MigLayout;
/**
* UI component that provides a listing of all docking configurations.
*
* @author lopeznr1
*/
public class FrontendManageConfigPanel extends GlassPanel implements ActionListener, ListSelectionListener
{
// GUI vars
protected ItemListPanel<ConfigItem> listPanel;
protected JButton deleteB, closeB;
private ItemListPanel<ConfigItem, LookUp> listPanel;
private JButton deleteB, closeB;
// State vars
protected DockFrontend refFrontend;
protected StaticItemProcessor<ConfigItem> myItemProcessor;
private DockFrontend refFrontend;
private StaticItemProcessor<ConfigItem> myItemProcessor;
/**
* Constructor
* @param aFrontend
* Standard Constructor
*
* @param aFrontend
*/
public FrontendManageConfigPanel(Component aParent, DockFrontend aFrontend)
{
@@ -53,8 +64,8 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
// Build the actual GUI
buildGuiArea();
setPreferredSize(new Dimension(250, 300));//TODO:getPreferredSize().height));
setPreferredSize(new Dimension(250, 300));// TODO:getPreferredSize().height));
// Set up keyboard short cuts
FocusUtil.addAncestorKeyBinding(this, "ESCAPE", new ClickAction(closeB));
FocusUtil.addAncestorKeyBinding(this, "ENTER", new ClickAction(closeB));
@@ -65,19 +76,16 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
public void setVisible(boolean aBool)
{
resetGui();
super.setVisible(aBool);
}
@Override
public void actionPerformed(ActionEvent e)
public void actionPerformed(ActionEvent aEvent)
{
Object source;
ConfigItem chosenItem;
var chosenItem = listPanel.getSelectedItem();
chosenItem = listPanel.getSelectedItem();
source = e.getSource();
var source = aEvent.getSource();
if (source == deleteB)
{
refFrontend.delete(chosenItem.getName());
@@ -94,7 +102,7 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
{
if (aEvent.getValueIsAdjusting() == true)
return;
updateGui();
}
@@ -103,34 +111,27 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
*/
private void buildGuiArea()
{
JLabel tmpL;
QueryItemHandler<ConfigItem> aItemHandler;
QueryComposer<LookUp> aComposer;
setLayout(new MigLayout("", "[grow][][]", "[][grow][]"));
tmpL = new JLabel("Select configuration:", JLabel.CENTER);
add(tmpL, "growx,span 4,wrap");
// Construct the actual table panel
aComposer = new QueryComposer<LookUp>();
aComposer.addAttribute(LookUp.Name, String.class, "Configuration", null);
myItemProcessor = new StaticItemProcessor<ConfigItem>();
aItemHandler = new QueryItemHandler<ConfigItem>(aComposer);
listPanel = new ItemListPanel<ConfigItem>(aItemHandler, myItemProcessor, false, true);
var tmpL = new JLabel("Select configuration:", JLabel.CENTER);
add(tmpL, "growx,span 4,wrap");
// Construct the actual table panel
var tmpComposer = new QueryComposer<LookUp>();
tmpComposer.addAttribute(LookUp.Name, String.class, "Configuration", null);
myItemProcessor = new StaticItemProcessor<>();
var tmpIH = new QueryItemHandler<ConfigItem, LookUp>();
listPanel = new ItemListPanel<>(tmpIH, myItemProcessor, tmpComposer, true);
listPanel.addListSelectionListener(this);
add(listPanel, "growx,growy,span 4,wrap");
// Control area
deleteB = GuiUtil.createJButton("Delete", this);
closeB = GuiUtil.createJButton("Close", this);
add(deleteB, "skip 1,span 1");
add(closeB, "span 1");
setBorder(new BevelBorder(BevelBorder.RAISED));
add(deleteB, "skip 1");
add(closeB, "");
}
/**
@@ -138,31 +139,19 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
*/
private void resetGui()
{
Collection<String> strList;
Collection<ConfigItem> itemList;
itemList = Lists.newLinkedList();
strList = refFrontend.getSettings();
for (String aStr : strList)
var itemL = new ArrayList<ConfigItem>();
var strL = refFrontend.getSettings();
for (String aStr : strL)
{
// Add only non reserved items
if (aStr.charAt(0) != '.')
itemList.add(new ConfigItem(aStr));
itemL.add(new ConfigItem(aStr));
}
myItemProcessor.setItems(itemList);
// TODO: Ugly code: Should be able to just call updateGui but can not
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
updateGui();
}
});
myItemProcessor.setItems(itemL);
// TODO: Should be able to just call updateGui but can not
SwingUtilities.invokeLater(() -> updateGui());
}
/**
@@ -170,58 +159,46 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
*/
private void updateGui()
{
ConfigItem chosenItem;
boolean isEnabled;
chosenItem = listPanel.getSelectedItem();
var chosenItem = listPanel.getSelectedItem();
if (chosenItem != null)
refFrontend.load(chosenItem.getName());
isEnabled = chosenItem != null;
var isEnabled = chosenItem != null;
deleteB.setEnabled(isEnabled);
// Ensure we have the focus.
//listPanel.requestFocusInWindow();
//listPanel.requestFocusInWindow();
repaint();
// TODO: Ugly code: Not sure why need to request focus multiple times to ensure we regrab
// TODO: Ugly code: Not sure why need to request focus multiple times to ensure we regrab
// the focus. This is particularly true when there are multiple DockStations located on different
// windows
SwingUtilities.invokeLater(new Runnable()
{
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run()
{
listPanel.getTable().requestFocus();
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
listPanel.getTable().requestFocus();
}
});
// listPanel.getTable().getFocusCycleRootAncestor().setFocusCycleRoot(true);
SwingUtilities.invokeLater(() -> listPanel.getTable().requestFocus());
// listPanel.getTable().getFocusCycleRootAncestor().setFocusCycleRoot(true);
listPanel.getTable().requestFocusInWindow();
repaint();
}
});
}
/**
* Internal class only used to wrap named (string) settings into
* a QueryItem
* Internal class only used to wrap named (string) settings into a QueryItem.
*
* @author lopeznr1
*/
class ConfigItem implements QueryItem<LookUp>
{
private String refName;
// Attributes
private final String refName;
public ConfigItem(String aName)
{
refName = aName;
@@ -246,7 +223,7 @@ public class FrontendManageConfigPanel extends GlassPanel implements ActionListe
{
throw new UnsupportedOperationException();
}
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
public enum LookUp

View File

@@ -1,9 +1,21 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import java.util.LinkedHashSet;
import java.util.Set;
import com.google.common.collect.Sets;
import bibliothek.gui.DockStation;
import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.layout.DockSituationIgnore;
@@ -12,50 +24,52 @@ import bibliothek.gui.dock.perspective.PerspectiveStation;
public class PlainDockSituationIgnore implements DockSituationIgnore
{
private Set<Class<?>> ignoreClassSet;
// State vars
private Set<Class<?>> ignoreClassS;
/** Standard Constructor */
public PlainDockSituationIgnore()
{
ignoreClassSet = Sets.newLinkedHashSet();
ignoreClassS = new LinkedHashSet<>();
}
/**
* Method to register a new type of Dockable/Station to ignore
*/
public void addIgnoreClass(Class<?> aClass)
{
ignoreClassSet.add(aClass);
ignoreClassS.add(aClass);
}
@Override
public boolean ignoreElement(PerspectiveElement aElement)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean ignoreElement(DockElement aElement)
{
// Check to see if aElement is of one of the types in ignoreClassSet
for (Class<?> aClass : ignoreClassSet)
for (var aClass : ignoreClassS)
{
if (aClass.isAssignableFrom(aElement.getClass()) == true)
return true;
}
return false;
}
@Override
public boolean ignoreChildren(PerspectiveStation station)
public boolean ignoreChildren(PerspectiveStation aStation)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean ignoreChildren(DockStation station)
public boolean ignoreChildren(DockStation aStation)
{
// TODO Auto-generated method stub
return false;

View File

@@ -1,211 +1,196 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Maps;
import glum.io.IoUtil;
/**
* Container which holds a mapping of keys (String) to a bunch of primitive objects.
* <p>
* Serialization of content is supported via {@link #readBin(DataInputStream)} and {@link #writeBin(DataOutputStream)}
*
* @author lopeznr1
*/
public class PrimConfig
{
// Constants
public static final byte CODE_BOOL = 1;
public static final byte CODE_INT = 10;
public static final byte CODE_LONG = 11;
public static final byte CODE_SHORT = 12;
public static final byte CODE_FLOAT = 13;
public static final byte CODE_BOOL = 1;
public static final byte CODE_INT = 10;
public static final byte CODE_LONG = 11;
public static final byte CODE_SHORT = 12;
public static final byte CODE_FLOAT = 13;
public static final byte CODE_DOUBLE = 14;
public static final byte CODE_STRING = 20;
// State vars
protected Map<String, Object> mySingletonMap;
/**
* Container which holds a mapping of keys (String) to a bunch
* of primitive objects.
*/
protected Map<String, Object> mySingletonM;
/** Standard Constructor */
public PrimConfig()
{
mySingletonMap = Maps.newLinkedHashMap();
mySingletonM = new LinkedHashMap<>();
}
/**
* Returns the boolean associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the boolean associated with aKey If no such value is found then defaultVal is returned.
*/
public boolean getBoolean(String aKey, boolean defaultVal)
public boolean getBoolean(String aKey, boolean aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != Boolean.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != Boolean.class)
return aDefaultVal;
return (Boolean)aValue;
return (Boolean) tmpVal;
}
/**
* Returns the int associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the int associated with aKey If no such value is found then defaultVal is returned.
*/
public int getInt(String aKey, int defaultVal)
public int getInt(String aKey, int aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != Integer.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != Integer.class)
return aDefaultVal;
return (Integer)aValue;
return (Integer) tmpVal;
}
/**
* Returns the long associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the long associated with aKey If no such value is found then defaultVal is returned.
*/
public long getLong(String aKey, long defaultVal)
public long getLong(String aKey, long aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != Long.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != Long.class)
return aDefaultVal;
return (Long)aValue;
return (Long) tmpVal;
}
/**
* Returns the short associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the short associated with aKey If no such value is found then defaultVal is returned.
*/
public short getShort(String aKey, short defaultVal)
public short getShort(String aKey, short aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != Short.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != Short.class)
return aDefaultVal;
return (Short)aValue;
return (Short) tmpVal;
}
/**
* Returns the float associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the float associated with aKey If no such value is found then defaultVal is returned.
*/
public float getFloat(String aKey, float defaultVal)
public float getFloat(String aKey, float aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != Float.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != Float.class)
return aDefaultVal;
return (Float)aValue;
return (Float) tmpVal;
}
/**
* Returns the double associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the double associated with aKey If no such value is found then defaultVal is returned.
*/
public double getDouble(String aKey, double defaultVal)
public double getDouble(String aKey, double aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != Double.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != Double.class)
return aDefaultVal;
return (Double)aValue;
return (Double) tmpVal;
}
/**
* Returns the String associated with aKey
* If no such value is found then defaultVal is returned.
* Returns the String associated with aKey If no such value is found then defaultVal is returned.
*/
public String getString(String aKey, String defaultVal)
public String getString(String aKey, String aDefaultVal)
{
Object aValue;
// If no value associated with the key then return defaultVal
aValue = mySingletonMap.get(aKey);
if (aValue == null || aValue.getClass() != String.class)
return defaultVal;
var tmpVal = mySingletonM.get(aKey);
if (tmpVal == null || tmpVal.getClass() != String.class)
return aDefaultVal;
return (String)aValue;
return (String) tmpVal;
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setBoolean(String aKey, boolean aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setInt(String aKey, int aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setLong(String aKey, long aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setShort(String aKey, short aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setFloat(String aKey, float aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setDouble(String aKey, double aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
* Associates aVal with aKey. Note this will overwrite any
* previous association.
* Associates aVal with aKey. Note this will overwrite any previous association.
*/
public void setString(String aKey, String aValue)
{
mySingletonMap.put(aKey, aValue);
mySingletonM.put(aKey, aValue);
}
/**
@@ -213,50 +198,46 @@ public class PrimConfig
*/
public void readBin(DataInputStream aStream) throws IOException
{
int numItems;
String aKey;
byte aType;
mySingletonM.clear();
mySingletonMap.clear();
numItems = aStream.readInt();
var numItems = aStream.readInt();
for (int c1 = 0; c1 < numItems; c1++)
{
aKey = IoUtil.readString(aStream);
aType = aStream.readByte();
switch(aType)
var tmpKey = IoUtil.readString(aStream);
var tmpType = aStream.readByte();
switch (tmpType)
{
case CODE_BOOL:
mySingletonMap.put(aKey, aStream.readBoolean());
mySingletonM.put(tmpKey, aStream.readBoolean());
break;
case CODE_INT:
mySingletonMap.put(aKey, aStream.readInt());
mySingletonM.put(tmpKey, aStream.readInt());
break;
case CODE_LONG:
mySingletonMap.put(aKey, aStream.readLong());
mySingletonM.put(tmpKey, aStream.readLong());
break;
case CODE_SHORT:
mySingletonMap.put(aKey, aStream.readShort());
mySingletonM.put(tmpKey, aStream.readShort());
break;
case CODE_FLOAT:
mySingletonMap.put(aKey, aStream.readFloat());
mySingletonM.put(tmpKey, aStream.readFloat());
break;
case CODE_DOUBLE:
mySingletonMap.put(aKey, aStream.readDouble());
mySingletonM.put(tmpKey, aStream.readDouble());
break;
case CODE_STRING:
mySingletonMap.put(aKey, IoUtil.readString(aStream));
mySingletonM.put(tmpKey, IoUtil.readString(aStream));
break;
default:
throw new RuntimeException("Unreconnized type: " + aType);
throw new RuntimeException("Unreconnized type: " + tmpType);
}
}
}
@@ -266,55 +247,52 @@ public class PrimConfig
*/
public void writeBin(DataOutputStream aStream) throws IOException
{
Set<String> keySet;
Object aVal;
keySet = mySingletonMap.keySet();
aStream.writeInt(keySet.size());
for (String aKey : keySet)
var keyS = mySingletonM.keySet();
aStream.writeInt(keyS.size());
for (String aKey : keyS)
{
IoUtil.writeString(aStream, aKey);
aVal = mySingletonMap.get(aKey);
if (aVal instanceof Boolean)
var tmpVal = mySingletonM.get(aKey);
if (tmpVal instanceof Boolean)
{
aStream.writeByte(CODE_BOOL);
aStream.writeBoolean((Boolean)aVal);
aStream.writeBoolean((Boolean) tmpVal);
}
else if (aVal instanceof Integer)
else if (tmpVal instanceof Integer)
{
aStream.writeByte(CODE_INT);
aStream.writeInt((Integer)aVal);
aStream.writeInt((Integer) tmpVal);
}
else if (aVal instanceof Long)
else if (tmpVal instanceof Long)
{
aStream.writeByte(CODE_LONG);
aStream.writeLong((Long)aVal);
aStream.writeLong((Long) tmpVal);
}
else if (aVal instanceof Short)
else if (tmpVal instanceof Short)
{
aStream.writeByte(CODE_SHORT);
aStream.writeLong((Short)aVal);
aStream.writeLong((Short) tmpVal);
}
else if (aVal instanceof Float)
else if (tmpVal instanceof Float)
{
aStream.writeByte(CODE_FLOAT);
aStream.writeFloat((Float)aVal);
aStream.writeFloat((Float) tmpVal);
}
else if (aVal instanceof Double)
else if (tmpVal instanceof Double)
{
aStream.writeByte(CODE_DOUBLE);
aStream.writeDouble((Double)aVal);
aStream.writeDouble((Double) tmpVal);
}
else if (aVal instanceof String)
else if (tmpVal instanceof String)
{
aStream.writeByte(CODE_STRING);
IoUtil.writeString(aStream, (String)aVal);
IoUtil.writeString(aStream, (String) tmpVal);
}
else
{
throw new RuntimeException("Unsupported Object: " + aVal);
throw new RuntimeException("Unsupported Object: " + tmpVal);
}
}
}

View File

@@ -1,28 +1,41 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import bibliothek.gui.dock.DockElement;
/**
* Base class for Dockables which would like to store their configuration via
* the PrimConfig mechanism. Note if the child class will be loaded with the
* PrimDockableFactory, then you should have a constructor with one of the
* following properties:.
* <LI> 1 arguments: Registry
* <LI> 0 arguments: Empty Constructor
* <BR>
* <BR>It is also important the method getFactoryID() is overridden so that it returns PrimDockableFactory.ID
* Base class for Dockables which would like to store their configuration via the PrimConfig mechanism. Note if the
* child class will be loaded with the PrimDockableFactory, then you should have a constructor with one of the following
* properties:.
* <ul>
* <li>1 arguments: Registry
* <li>0 arguments: Empty Constructor
* </ul>
* It is also important the method getFactoryID() is overridden so that it returns PrimDockableFactory.ID
*
* @author lopeznr1
*/
public interface PrimDock extends DockElement
{
/**
* Returns the PrimConfig associated with the Dockable
* @return
* Returns the PrimConfig associated with the Dockable.
*/
public abstract PrimConfig getConfiguration();
/**
* Configures the Dockable with the aConfig
* @return
* Configures the Dockable with the aConfig.
*/
public abstract void setConfiguration(PrimConfig aConfig);

View File

@@ -1,16 +1,25 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import glum.reflect.ReflectUtil;
import glum.registry.Registry;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.*;
import java.lang.reflect.Constructor;
import java.util.Map;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockFactory;
import bibliothek.gui.dock.dockable.DefaultDockablePerspective;
@@ -18,47 +27,52 @@ import bibliothek.gui.dock.layout.LocationEstimationMap;
import bibliothek.gui.dock.perspective.PerspectiveDockable;
import bibliothek.gui.dock.station.support.PlaceholderStrategy;
import bibliothek.util.xml.XElement;
import glum.reflect.ReflectUtil;
import glum.registry.Registry;
/**
* Generic DockableFactory for creating PrimDocks.
* <P>
* <p>
* Note that before this factory is used all PrimDockable class types must first be associated with a spawnName. This is
* used during serialization configuration associated with PrimDock. See method {@link PrimDockFactory#addSpawnMapping}
*
* @author lopeznr1
*/
public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePerspective, PrimConfig>
{
// Constants
public static final String ID = "PrimDockFactory";
public static final String SpawnNameKey = "factory.spawnName";
public static final String SpawnNameKey = "factory.spawnName";
// State var
protected Registry refRegistry;
protected BiMap<String, Class<? extends PrimDock>> spawnMap;
private Registry refRegistry;
private BiMap<String, Class<? extends PrimDock>> spawnM;
/** Standard Constructor */
public PrimDockFactory(Registry aRegistry)
{
refRegistry = aRegistry;
spawnMap = HashBiMap.create();
spawnM = HashBiMap.create();
}
/**
* Add a mapping for a PrimDockable to a the associated spawnName. It is mandatory
* that this mapping is always the same regardless of application executions, as
* this value will be serialized to the disk.
* this value will be serialized to the disk.
*/
public void addSpawnMapping(String spawnName, Class<? extends PrimDock> spawnClass)
public void addSpawnMapping(String aSpawnName, Class<? extends PrimDock> aSpawnClass)
{
// Ensure the spawnName is not already reserved
if (spawnMap.containsKey(spawnName) == true)
throw new RuntimeException("Previous mapping stored for spawnName:" + spawnName);
if (spawnM.containsKey(aSpawnName) == true)
throw new RuntimeException("Previous mapping stored for spawnName:" + aSpawnName);
// Ensure the spawnClass is not already stored
if (spawnMap.inverse().containsKey(spawnClass) == true)
throw new RuntimeException("Previous mapping stored for spawnClass:" + spawnClass);
spawnMap.put(spawnName, spawnClass);
if (spawnM.inverse().containsKey(aSpawnClass) == true)
throw new RuntimeException("Previous mapping stored for spawnClass:" + aSpawnClass);
spawnM.put(aSpawnName, aSpawnClass);
}
@Override
public String getID()
@@ -71,18 +85,18 @@ public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePer
{
PrimConfig rConfig;
String spawnName;
rConfig = aDockable.getConfiguration();
// Store the associated spawnName used to instantiate the Dockable
spawnName = spawnMap.inverse().get(aDockable.getClass());
spawnName = spawnM.inverse().get(aDockable.getClass());
if (spawnName == null)
throw new RuntimeException("Factory is not configured properly. Failed to locate associated spawnName for class:" + aDockable.getClass());
// Ensure that the SpawnNameKey is not already reserved.
; // TODO
rConfig.setString(SpawnNameKey, spawnName);
rConfig.setString(SpawnNameKey, spawnName);
return rConfig;
}
@@ -120,8 +134,8 @@ public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePer
@Override
public PrimConfig read(DataInputStream aStream, PlaceholderStrategy placeholders) throws IOException
{
PrimConfig rLayout;
PrimConfig rLayout;
rLayout = new PrimConfig();
rLayout.readBin(aStream);
return rLayout;
@@ -143,7 +157,7 @@ public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePer
public PrimDock layout(PrimConfig layout, Map<Integer, Dockable> children, PlaceholderStrategy placeholders)
{
PrimDock aDockable;
aDockable = layout(layout, placeholders);
return aDockable;
}
@@ -157,13 +171,13 @@ public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePer
Class<?> parmTypes[] = {Registry.class};
Object parmValues[] = {refRegistry};
String spawnName;
spawnName = aLayout.getString(SpawnNameKey, null);
spawnClass = spawnMap.get(spawnName);
spawnClass = spawnM.get(spawnName);
if (spawnClass == null)
throw new RuntimeException("Factory is not configured properly. Failed to locate associated class for spawn name:" + spawnName);
try
{
spawnConstructor = ReflectUtil.getConstructorSafe(spawnClass, parmTypes);
@@ -176,7 +190,7 @@ public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePer
{
throw new RuntimeException("Failed to instantite class.", aExp);
}
rDockable.setConfiguration(aLayout);
return rDockable;
}
@@ -189,7 +203,8 @@ public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePer
}
@Override
public void layoutPerspective(DefaultDockablePerspective perspective, PrimConfig layout, Map<Integer, PerspectiveDockable> children)
public void layoutPerspective(DefaultDockablePerspective perspective, PrimConfig layout,
Map<Integer, PerspectiveDockable> children)
{
; // Nothing to do
}

View File

@@ -1,14 +1,30 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock;
import bibliothek.gui.dock.DefaultDockable;
/**
* Base class for Dockables which would like to store their configuration via
* the PrimConfig mechanism. Note if the child class will be loaded with the
* PrimDockableFactory, then you should have a constructor with one of the
* following properties:.
* <LI> 1 arguments: Registry
* <LI> 0 arguments: Empty Constructor
* Base class for Dockables which would like to store their configuration via the PrimConfig mechanism. Note if the
* child class will be loaded with the PrimDockableFactory, then you should have a constructor with one of the following
* properties:.
* <ul>
* <li>1 arguments: Registry
* <li>0 arguments: Empty Constructor
* </ul>
*
* @author lopeznr1
*/
public abstract class PrimDockable extends DefaultDockable implements PrimDock
{

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.action;
public interface Closeable

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.action;
public interface Destroyable

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.action;
import javax.swing.Icon;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.action;
import javax.swing.Icon;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.action;
import java.awt.event.ActionEvent;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.action;
import javax.swing.Icon;
@@ -7,21 +20,22 @@ import bibliothek.gui.dock.action.actions.SimpleButtonAction;
/**
* An DockAction that will fire trigger an embedded java.awt Action
*
* @author lopeznr1
*/
public class ToggleAction extends SimpleButtonAction
{
// State vars
protected boolean isActive;
private boolean isActive;
// Gui vars
protected Icon falseIcon, trueIcon;
private final Icon falseIcon, trueIcon;
/** Standard Constructor */
public ToggleAction(String aText, Icon aFalseIcon, Icon aTrueIcon, boolean aIsActive)
{
super();
isActive = aIsActive;
falseIcon = aFalseIcon;
trueIcon = aTrueIcon;
@@ -36,24 +50,24 @@ public class ToggleAction extends SimpleButtonAction
{
return isActive;
}
public void setIsActive(boolean aBool)
{
isActive = aBool;
updateGui();
}
@Override
public void action(Dockable aDockable)
{
isActive = !isActive;
updateGui();
super.action(aDockable);
}
/**
* Utility method
* Utility method
*/
private void updateGui()
{

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.alt;
import glum.gui.dock.action.Destroyable;

View File

@@ -1,42 +1,58 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.alt;
import glum.gui.dock.BaseDockable;
import java.awt.Window;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.ScreenDockStation;
import bibliothek.gui.dock.action.DefaultDockActionSource;
import bibliothek.gui.dock.action.DockAction;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.action.LocationHint;
import glum.gui.dock.BaseDockable;
/**
* Alternative ScreenDockStation which provides no default direct/indirect action offers.
*
* @author lopeznr1
*/
public class AltScreenDockStation extends ScreenDockStation
{
// Action vars
private List<DockAction> directDockActionList;
private List<DockAction> indirectDockActionList;
private List<DockAction> directDockActionL;
private List<DockAction> indirectDockActionL;
// Lock vars
private Set<Dockable> lockSet;
private Set<Dockable> lockS;
private boolean isLocked;
public AltScreenDockStation(Window owner)
/**
* Standard Constructor
*/
public AltScreenDockStation(Window aOwner)
{
super(owner);
super(aOwner);
directDockActionList = Lists.newArrayList();
indirectDockActionList = Lists.newArrayList();
directDockActionL = new ArrayList<>();
indirectDockActionL = new ArrayList<>();
lockSet = Sets.newHashSet();
lockS = new HashSet<>();
isLocked = false;
}
@@ -45,7 +61,7 @@ public class AltScreenDockStation extends ScreenDockStation
*/
public void addDirectActionOffer(DockAction aDockAction)
{
directDockActionList.add(aDockAction);
directDockActionL.add(aDockAction);
}
/**
@@ -53,7 +69,7 @@ public class AltScreenDockStation extends ScreenDockStation
*/
public void addIndirectActionOffer(DockAction aDockAction)
{
indirectDockActionList.add(aDockAction);
indirectDockActionL.add(aDockAction);
}
/**
@@ -66,14 +82,14 @@ public class AltScreenDockStation extends ScreenDockStation
if (isLocked == false)
{
lockSet.clear();
lockS.clear();
return;
}
// Record all of the valid children when the lock is triggered
for (int c1 = 0; c1 < getDockableCount(); c1++)
{
lockSet.add(getDockable(c1));
lockS.add(getDockable(c1));
}
}
@@ -82,34 +98,34 @@ public class AltScreenDockStation extends ScreenDockStation
public boolean accept(Dockable aChild)
{
// If we are locked then never accept any Dockable, which was not recorded as valid when the lock happened
if (isLocked == true && lockSet.contains(aChild) == false)
if (isLocked == true && lockS.contains(aChild) == false)
return false;
// Never accept any Dockable that has been marked as nontransferable
if (aChild instanceof BaseDockable)
return ((BaseDockable)aChild).isTransferable(this);
return ((BaseDockable) aChild).isTransferable(this);
return super.accept(aChild);
}
@Override
public DefaultDockActionSource getDirectActionOffers(Dockable dockable)
public DefaultDockActionSource getDirectActionOffers(Dockable aDockable)
{
DefaultDockActionSource source;
source = new DefaultDockActionSource(new LocationHint(LocationHint.DIRECT_ACTION, LocationHint.VERY_RIGHT));
source.add(directDockActionList.toArray(new DockAction[0]));
source.add(directDockActionL.toArray(new DockAction[0]));
return source;
}
@Override
public DockActionSource getIndirectActionOffers(Dockable dockable)
public DockActionSource getIndirectActionOffers(Dockable aDockable)
{
DefaultDockActionSource source;
source = new DefaultDockActionSource(new LocationHint(LocationHint.INDIRECT_ACTION, LocationHint.VERY_RIGHT));
source.add(indirectDockActionList.toArray(new DockAction[0]));
source.add(indirectDockActionL.toArray(new DockAction[0]));
return source;
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.alt;
import java.awt.Dialog;

View File

@@ -1,39 +1,49 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.dock.alt;
import glum.gui.dock.BaseDockable;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.*;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.action.DefaultDockActionSource;
import bibliothek.gui.dock.action.DockAction;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.action.LocationHint;
import bibliothek.gui.dock.action.*;
import glum.gui.dock.BaseDockable;
/**
* Alternative implementation of SplitDockStation.
*
* @author lopeznr1
*/
public class AltSplitDockStation extends SplitDockStation
{
// Action vars
private List<DockAction> directDockActionList;
private List<DockAction> localDockActionList;
private List<DockAction> indirectDockActionList;
private List<DockAction> directDockActionL;
private List<DockAction> localDockActionL;
private List<DockAction> indirectDockActionL;
// Lock vars
private Set<Dockable> lockSet;
private Set<Dockable> lockS;
private boolean isLocked;
/** Standard Constructor */
public AltSplitDockStation()
{
super();
directDockActionL = new ArrayList<>();
localDockActionL = new ArrayList<>();
indirectDockActionL = new ArrayList<>();
directDockActionList = Lists.newArrayList();
localDockActionList = Lists.newArrayList();
indirectDockActionList = Lists.newArrayList();
lockSet = Sets.newHashSet();
lockS = new HashSet<>();
isLocked = false;
}
@@ -42,7 +52,7 @@ public class AltSplitDockStation extends SplitDockStation
*/
public void addDirectActionOffer(DockAction aDockAction)
{
directDockActionList.add(aDockAction);
directDockActionL.add(aDockAction);
}
/**
@@ -50,7 +60,7 @@ public class AltSplitDockStation extends SplitDockStation
*/
public void addLocalActionOffer(DockAction aDockAction)
{
localDockActionList.add(aDockAction);
localDockActionL.add(aDockAction);
}
/**
@@ -58,7 +68,7 @@ public class AltSplitDockStation extends SplitDockStation
*/
public void addIndirectActionOffer(DockAction aDockAction)
{
indirectDockActionList.add(aDockAction);
indirectDockActionL.add(aDockAction);
}
/**
@@ -71,14 +81,14 @@ public class AltSplitDockStation extends SplitDockStation
if (isLocked == false)
{
lockSet.clear();
lockS.clear();
return;
}
// Record all of the valid children when the lock is triggered
for (int c1 = 0; c1 < getDockableCount(); c1++)
{
lockSet.add(getDockable(c1));
lockS.add(getDockable(c1));
}
}
@@ -87,18 +97,18 @@ public class AltSplitDockStation extends SplitDockStation
public boolean accept(Dockable aChild)
{
// If we are locked then never accept any Dockable, which was not recorded as valid when the lock happened
if (isLocked == true && lockSet.contains(aChild) == false)
if (isLocked == true && lockS.contains(aChild) == false)
return false;
// Never accept any Dockable that has been marked as nontransferable
if (aChild instanceof BaseDockable)
return ((BaseDockable)aChild).isTransferable(this);
return ((BaseDockable) aChild).isTransferable(this);
// Default behavior for non BaseDockables
return super.accept(aChild);
}
//
//
// @Override
// protected boolean acceptable(Dockable old, Dockable next)
// {
@@ -112,8 +122,8 @@ public class AltSplitDockStation extends SplitDockStation
//// if (((BaseDockable)next).isTransferable() == false)
//// return false;
//// }
////
////
////
////
//// // TODO Auto-generated method stub
//// return super.acceptable(old, next);
// }
@@ -127,7 +137,7 @@ public class AltSplitDockStation extends SplitDockStation
// return super.canDrag(aDockable);
// }
//
//
//
// @Override
// public boolean canReplace(Dockable oldDockable, Dockable nextDockable)
// {
@@ -141,12 +151,10 @@ public class AltSplitDockStation extends SplitDockStation
// }
@Override
public DefaultDockActionSource getDirectActionOffers(Dockable dockable)
public DefaultDockActionSource getDirectActionOffers(Dockable aDockable)
{
DefaultDockActionSource source;
source = new DefaultDockActionSource(new LocationHint(LocationHint.DIRECT_ACTION, LocationHint.VERY_RIGHT));
source.add(directDockActionList.toArray(new DockAction[0]));
var source = new DefaultDockActionSource(new LocationHint(LocationHint.DIRECT_ACTION, LocationHint.VERY_RIGHT));
source.add(directDockActionL.toArray(new DockAction[0]));
return source;
}
@@ -154,21 +162,17 @@ public class AltSplitDockStation extends SplitDockStation
@Override
public DockActionSource getLocalActionOffers()
{
DefaultDockActionSource source;
source = new DefaultDockActionSource(new LocationHint(LocationHint.DOCKABLE, LocationHint.RIGHT));
source.add(localDockActionList.toArray(new DockAction[0]));
var source = new DefaultDockActionSource(new LocationHint(LocationHint.DOCKABLE, LocationHint.RIGHT));
source.add(localDockActionL.toArray(new DockAction[0]));
return source;
}
@Override
public DockActionSource getIndirectActionOffers(Dockable dockable)
public DockActionSource getIndirectActionOffers(Dockable aDockable)
{
DefaultDockActionSource source;
source = new DefaultDockActionSource(new LocationHint(LocationHint.INDIRECT_ACTION, LocationHint.VERY_RIGHT));
source.add(indirectDockActionList.toArray(new DockAction[0]));
var source = new DefaultDockActionSource(new LocationHint(LocationHint.INDIRECT_ACTION, LocationHint.VERY_RIGHT));
source.add(indirectDockActionL.toArray(new DockAction[0]));
return source;
}

View File

@@ -1,24 +1,38 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.document;
import java.awt.event.*;
import javax.swing.text.*;
import javax.swing.JTextField;
import javax.swing.text.PlainDocument;
public abstract class BaseDocument extends PlainDocument implements ActionListener, FocusListener
{
// State vars
protected JTextField ownerTF;
/** Standard Constructor */
public BaseDocument(JTextField aOwnerTF)
{
super();
ownerTF = aOwnerTF;
}
/**
* Get the owner of this Document model
* Todo: This method should no longer be needed.
* <p>
* TODO: This method should no longer be needed.
*/
public JTextField getOwner()
{

View File

@@ -1,23 +1,40 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.document;
import javax.swing.JTextField;
/**
* Implementation of {@link BaseDocument} specific for numerical input.
*
* @author lopeznr1
*/
public abstract class BaseNumberDocument extends BaseDocument
{
// State vars
protected double minVal, maxVal;
protected boolean formalizeDoc;
protected int numAvailCols;
/** Standard Constructor */
public BaseNumberDocument(JTextField aOwner, double aMinVal, double aMaxVal)
{
super(aOwner);
setMinMaxValue(aMinVal, aMaxVal);
formalizeDoc = false;
numAvailCols = -1;
}
/**
* Updates the new range of valid numbers.
*/
@@ -25,12 +42,12 @@ public abstract class BaseNumberDocument extends BaseDocument
{
minVal = aMinVal;
maxVal = aMaxVal;
// Insanity check
if (minVal >= maxVal)
throw new RuntimeException("Illogical range. Range: [" + minVal + "," + maxVal + "]");
}
@Override
public void formalizeInput()
{
@@ -56,6 +73,4 @@ public abstract class BaseNumberDocument extends BaseDocument
ownerTF.addFocusListener(this);
}
}

View File

@@ -1,37 +1,49 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.document;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import com.google.common.collect.Sets;
/**
* Specialized Document designed to accept only the specified input chars
*
* @author lopeznr1
*/
public class CharDocument extends BaseDocument
{
private Set<Character> validSet;
private Set<Character> validS;
public CharDocument(JTextField aOwner, String validCharStr)
{
this(aOwner, validCharStr, true);
}
public CharDocument(JTextField aOwner, String validCharStr, boolean isCaseSensitive)
/**
* Standard Constructor
*/
public CharDocument(JTextField aOwner, String aValidCharStr, boolean aIsCaseSensitive)
{
super(aOwner);
validSet = Sets.newHashSet();
for (int c1 = 0; c1 < validCharStr.length(); c1++)
validS = new HashSet<>();
for (int c1 = 0; c1 < aValidCharStr.length(); c1++)
{
validSet.add(validCharStr.charAt(c1));
if (isCaseSensitive == false)
validS.add(aValidCharStr.charAt(c1));
if (aIsCaseSensitive == false)
{
validSet.add(Character.toLowerCase(validCharStr.charAt(c1)));
validSet.add(Character.toUpperCase(validCharStr.charAt(c1)));
validS.add(Character.toLowerCase(aValidCharStr.charAt(c1)));
validS.add(Character.toUpperCase(aValidCharStr.charAt(c1)));
}
}
}
@@ -41,25 +53,23 @@ public class CharDocument extends BaseDocument
{
; // Nothing to do
}
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
{
char aChar;
@Override
public void insertString(int aOffs, String aStr, AttributeSet aAS) throws BadLocationException
{
// Insanity check
if (str == null)
if (aStr == null)
return;
// Ensure all of the characters in str are in the valid set
for (int c1 = 0; c1 < str.length(); c1++)
for (int c1 = 0; c1 < aStr.length(); c1++)
{
aChar = str.charAt(c1);
if (validSet.contains(aChar) == false)
throw new BadLocationException("Invalid character: " + aChar, offs);
char tmpChar = aStr.charAt(c1);
if (validS.contains(tmpChar) == false)
throw new BadLocationException("Invalid character: " + tmpChar, aOffs);
}
super.insertString(offs, str, a);
super.insertString(aOffs, aStr, aAS);
}
}

View File

@@ -1,15 +1,40 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.document;
import javax.swing.text.*;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import glum.gui.GuiUtil;
import glum.io.ParseUtil;
/**
* Implementation of {@link BaseNumberDocument}.
*
* @author lopeznr1
*/
public class NumberDocument extends BaseNumberDocument
{
protected boolean allowFloats;
// protected NumberUnit myUnit;
// Constants
private final String ValidPosDigitStr = "0123456789";
private final String ValidNegDigitStr = "+-0123456789";
private final String ValidFractStr = "+-0123456789e.";
protected boolean allowFloats;
// protected NumberUnit myUnit;
/** Standard Constructor */
public NumberDocument(JTextField aOwnerTF, boolean aFormalizeDoc)
{
super(aOwnerTF, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
@@ -38,6 +63,28 @@ public class NumberDocument extends BaseNumberDocument
if (str == null)
return;
// Change to allow user to enter any valid single character to be input. Note that the
// NumberDocument is used primary by GNumberField and as such invalid input will be
// colored with the "fail" color.
if (str.length() == 1)
{
if (allowFloats == false && minVal >= 0 && ValidPosDigitStr.contains(str) == true)
{
super.insertString(offs, str, a);
return;
}
else if (allowFloats == false && minVal < 0 && ValidNegDigitStr.contains(str) == true)
{
super.insertString(offs, str, a);
return;
}
else if (allowFloats == true && ValidFractStr.contains(str) == true)
{
super.insertString(offs, str, a);
return;
}
}
// Special cases
aChar = str.charAt(0);
if (offs == 0)
@@ -76,13 +123,6 @@ public class NumberDocument extends BaseNumberDocument
if (str.contains(".") == true && allowFloats == false)
throw new BadLocationException("Only integers are allowed.", offs);
// Ensure we do not exceed number of columns
if (numAvailCols > 0)
{
if (offs + str.length() >= numAvailCols)
throw new BadLocationException("Too many characters to insert.", offs);
}
// Form the resultant string
bStr = "";
eStr = "";
@@ -92,7 +132,7 @@ public class NumberDocument extends BaseNumberDocument
resultStr = bStr + str + eStr;
// Ensure the resultant is sensical
aVal = GuiUtil.readDouble(resultStr, Double.NaN);
aVal = ParseUtil.readDouble(resultStr, Double.NaN);
if (Double.isNaN(aVal) == true)
throw new BadLocationException("Nonsensical number.", offs);

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.icon;
import java.awt.Color;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.icon;
import java.awt.Color;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.icon;
import javax.swing.Icon;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.icon;
import java.awt.BasicStroke;

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.icon;
import java.awt.Component;
@@ -5,11 +18,28 @@ import java.awt.Graphics;
import javax.swing.Icon;
/**
* Immutable icon that renders nothing.
* <p>
* This icon will typically be used as a place holder.
*
* @author lopeznr1
*/
public class EmptyIcon implements Icon
{
protected int width, height;
EmptyIcon(int aWidth, int aHeight)
// Attributes
private final int width;
private final int height;
/**
* Standard Constructor
*
* @param aWidth
* The width of the icon.
* @param aHeight
* The height of the icon.
*/
public EmptyIcon(int aWidth, int aHeight)
{
width = aWidth;
height = aHeight;

View File

@@ -1,24 +1,45 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.icon;
import java.awt.Component;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
/**
* Collection of utility methods for dealing with icons.
*
* @author lopeznr1
*/
public class IconUtil
{
/**
* Utility method to load the Icon specified by the resource path.
* Utility method to load an icon from the specified resource.
*/
public static ImageIcon loadIcon(String iconPath)
public static ImageIcon loadIcon(String aIconPath)
{
// URL aURL;
//
// aURL = IconUtil.class.getClassLoader().getResource(iconPath);
// if (aURL == null)
// throw new RuntimeException("Failed to load icon for path: " + iconPath);
//
// return new ImageIcon(aURL);
return new ImageIcon(ClassLoader.getSystemResource(iconPath));
return new ImageIcon(ClassLoader.getSystemResource(aIconPath));
}
/**
* Utility method to load an icon from the specified resource.
*/
public static ImageIcon loadIcon(URL aURL)
{
return new ImageIcon(aURL);
}
/**
@@ -28,8 +49,8 @@ public class IconUtil
{
if (aComp instanceof JButton == false)
return false;
return ((JButton)aComp).getModel().isPressed();
return ((JButton) aComp).getModel().isPressed();
}
}

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.info;
import glum.zio.*;

View File

@@ -0,0 +1,162 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.info;
import java.awt.Component;
import java.awt.Dimension;
import java.io.IOException;
import glum.zio.*;
/**
* Immutable object used to store the position/dimension/visibility state of a {@link Component}.
* <p>
* This is typically used capture the state of a dialog or window.
*
* @author lopeznr1
*/
public class WindowCfg implements ZioRaw
{
// Attributes
private final boolean isShown;
private final int posX;
private final int posY;
private final int dimX;
private final int dimY;
/** Standard Constructor */
public WindowCfg(boolean aIsShown, int aPosX, int aPosY, int aDimX, int aDimY)
{
isShown = aIsShown;
posX = aPosX;
posY = aPosY;
dimX = aDimX;
dimY = aDimY;
}
/** Serialization Constructor */
public WindowCfg(ZinStream aStream) throws IOException
{
aStream.readVersion(0);
isShown = aStream.readBool();
posX = aStream.readInt();
posY = aStream.readInt();
dimX = aStream.readInt();
dimY = aStream.readInt();
}
/**
* UI based constructor
*
* The WindowInfo will be setup to the current state of the provided {@link Component}.
*/
public WindowCfg(Component aComponent)
{
isShown = aComponent.isVisible();
posX = aComponent.getLocation().x;
posY = aComponent.getLocation().y;
dimX = aComponent.getSize().width;
dimY = aComponent.getSize().height;
}
/**
* Syncs the specified {@link Component} to match the state of this {@link WindowCfg}.
*/
public void configure(Component aComponent)
{
aComponent.setLocation(posX, posY);
aComponent.setPreferredSize(new Dimension(dimX, dimY));
aComponent.setSize(dimX, dimY);
}
/**
* Returns a {@link WindowCfg} which matches this WindowInfo but with the isShown flag set to the requested setting.
*/
public WindowCfg withIsShown(boolean aIsShown)
{
// Bail if nothing changes
if (isShown == aIsShown)
return this;
return new WindowCfg(aIsShown, posX, posY, dimX, dimY);
}
// @formatter:off
// Accessor methods
public boolean isShown() { return isShown; }
public int dimX() { return dimX; }
public int dimY() { return dimY; }
public int posX() { return posX; }
public int posY() { return posY; }
// @formatter:on
@Override
public void zioWrite(ZoutStream aStream) throws IOException
{
aStream.writeVersion(0);
aStream.writeBool(isShown);
aStream.writeInt(posX);
aStream.writeInt(posY);
aStream.writeInt(dimX);
aStream.writeInt(dimY);
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + dimX;
result = prime * result + dimY;
result = prime * result + (isShown ? 1231 : 1237);
result = prime * result + posX;
result = prime * result + posY;
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
WindowCfg other = (WindowCfg) obj;
if (dimX != other.dimX)
return false;
if (dimY != other.dimY)
return false;
if (isShown != other.isShown)
return false;
if (posX != other.posX)
return false;
if (posY != other.posY)
return false;
return true;
}
}

View File

@@ -1,77 +0,0 @@
package glum.gui.info;
import glum.zio.*;
import glum.zio.util.ZioUtil;
import java.awt.*;
import java.io.*;
public class WindowInfo implements ZioObj
{
// Raw vars
protected Point position;
protected Dimension size;
protected boolean isVisible;
/**
* Constructor
*/
public WindowInfo()
{
position = null;
size = null;
isVisible = false;
}
public WindowInfo(Component aComponent)
{
this();
if (aComponent == null)
return;
position = aComponent.getLocation();
size = aComponent.getSize();
isVisible = aComponent.isVisible();
}
/**
* configure - Syncs aComponent with parmaters of this WindowInfo
*/
public void configure(Component aComponent)
{
if (position != null)
aComponent.setLocation(position);
if (size != null)
{
aComponent.setPreferredSize(size);
aComponent.setSize(size);
}
}
@Override
public void zioRead(ZinStream aStream) throws IOException
{
aStream.readVersion(0);
isVisible = aStream.readBool();
position = ZioUtil.readPoint(aStream);
size = ZioUtil.readDimension(aStream);
}
@Override
public void zioWrite(ZoutStream aStream) throws IOException
{
aStream.writeVersion(0);
aStream.writeBool(isVisible);
ZioUtil.writePoint(aStream, position);
ZioUtil.writeDimension(aStream, size);
}
}

View File

@@ -1,20 +1,36 @@
package glum.gui.dialog;
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.memory;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.*;
import net.miginfocom.swing.MigLayout;
import glum.gui.FocusUtil;
import glum.gui.GuiUtil;
import glum.gui.action.ClickAction;
import glum.gui.component.GLabel;
import glum.unit.ConstUnitProvider;
import glum.unit.NumberUnit;
import glum.unit.UnitProvider;
import glum.unit.*;
import net.miginfocom.swing.MigLayout;
/**
* UI componet that provides a view of the applications memory state.
*
* @author lopeznr1
*/
public class MemoryUtilDialog extends JDialog implements ActionListener
{
// Gui components
@@ -23,7 +39,7 @@ public class MemoryUtilDialog extends JDialog implements ActionListener
private JButton closeB, gcRunB, updateB;
/**
* Constructor
* Standard Constructor
*/
public MemoryUtilDialog(JFrame parentFrame)
{
@@ -33,8 +49,7 @@ public class MemoryUtilDialog extends JDialog implements ActionListener
setDefaultCloseOperation(HIDE_ON_CLOSE);
setModal(false);
DecimalFormat numFormat;
numFormat = new DecimalFormat();
var numFormat = new DecimalFormat();
numFormat.setGroupingUsed(true);
numFormat.setGroupingSize(3);
numFormat.setMaximumFractionDigits(0);
@@ -52,9 +67,7 @@ public class MemoryUtilDialog extends JDialog implements ActionListener
@Override
public void actionPerformed(ActionEvent e)
{
Object source;
source = e.getSource();
var source = e.getSource();
if (source == gcRunB)
{
System.gc();
@@ -82,40 +95,36 @@ public class MemoryUtilDialog extends JDialog implements ActionListener
*/
private void buildGuiArea()
{
JPanel aPanel;
JLabel tmpL;
Font tmpFont;
// Form the panel
aPanel = new JPanel(new MigLayout("", "[right][left,grow]", "[][][]10[]10"));
tmpFont = new JTextField().getFont();
var tmpPanel = new JPanel(new MigLayout("", "[right][left,grow]", "[][][]10[]10"));
var tmpFont = new JTextField().getFont();
// Info area
tmpL = new JLabel("Total Memory:");
var tmpL = new JLabel("Total Memory:");
totalMemL = new GLabel(byteUP, tmpFont, true);
aPanel.add(tmpL, "");
aPanel.add(totalMemL, "growx,wrap");
tmpPanel.add(tmpL, "");
tmpPanel.add(totalMemL, "growx,wrap");
tmpL = new JLabel("Free Memory:");
freeMemL = new GLabel(byteUP, tmpFont, true);
aPanel.add(tmpL, "");
aPanel.add(freeMemL, "growx,wrap");
tmpPanel.add(tmpL, "");
tmpPanel.add(freeMemL, "growx,wrap");
tmpL = new JLabel("Used Memory:");
usedMemL = new GLabel(byteUP, tmpFont, true);
aPanel.add(tmpL, "");
aPanel.add(usedMemL, "growx,wrap");
tmpPanel.add(tmpL, "");
tmpPanel.add(usedMemL, "growx,wrap");
// Control area
updateB = GuiUtil.createJButton("Update", this);
gcRunB = GuiUtil.createJButton("Run GC", this);
closeB = GuiUtil.createJButton("Close", this);
aPanel.add(updateB, "span 2,split 3");
aPanel.add(gcRunB, "");
aPanel.add(closeB, "");
tmpPanel.add(updateB, "span 2,split 3");
tmpPanel.add(gcRunB, "");
tmpPanel.add(closeB, "");
// Add the main panel into the dialog
getContentPane().add(aPanel);
getContentPane().add(tmpPanel);
pack();
}
@@ -124,15 +133,12 @@ public class MemoryUtilDialog extends JDialog implements ActionListener
*/
private void updateGui()
{
Runtime aRuntime;
long freeMem, usedMem, totalMem;
aRuntime = Runtime.getRuntime();
var tmpRuntime = Runtime.getRuntime();
// Update the memory usage
freeMem = aRuntime.freeMemory();
totalMem = aRuntime.totalMemory();
usedMem = totalMem - freeMem;
var freeMem = tmpRuntime.freeMemory();
var totalMem = tmpRuntime.totalMemory();
var usedMem = totalMem - freeMem;
freeMemL.setValue(freeMem);
totalMemL.setValue(totalMem);

View File

@@ -1,3 +1,16 @@
// Copyright (C) 2024 The Johns Hopkins University Applied Physics Laboratory LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glum.gui.misc;
import java.awt.Component;
@@ -5,43 +18,47 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.LinkedList;
import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
/**
* Cell editor suitable for editing boolean values.
*
* @author lopeznr1
*/
public class BooleanCellEditor extends AbstractCellEditor implements ActionListener, TableCellEditor
{
// State vars
protected Collection<ActionListener> myListeners;
protected JCheckBox refCheckBox;
private Collection<ActionListener> listenerL;
private JCheckBox refCheckBox;
/**
* Constructor
*/
/** Standard Constructor */
public BooleanCellEditor(ActionListener aListener)
{
listenerL = new LinkedList<>();
if (aListener != null)
listenerL.add(aListener);
refCheckBox = new JCheckBox("", false);
refCheckBox.addActionListener(this);
refCheckBox.setHorizontalAlignment(JCheckBox.CENTER);
}
/** Simplified Constructor */
public BooleanCellEditor()
{
this(null);
}
public BooleanCellEditor(ActionListener aListener)
{
myListeners = new LinkedList<ActionListener>();
if (aListener != null)
myListeners.add(aListener);
refCheckBox = new JCheckBox("", false);
refCheckBox.addActionListener(this);
}
public void addActionListener(ActionListener aListener)
{
myListeners.add(aListener);
listenerL.add(aListener);
}
public void removeActionListener(ActionListener aListener)
{
myListeners.remove(aListener);
listenerL.remove(aListener);
}
@Override
@@ -50,7 +67,7 @@ public class BooleanCellEditor extends AbstractCellEditor implements ActionListe
fireEditingStopped();
aEvent = new ActionEvent(this, aEvent.getID(), "BooleanCell edited.");
for (ActionListener aListener : myListeners)
for (ActionListener aListener : listenerL)
aListener.actionPerformed(aEvent);
}
@@ -60,7 +77,7 @@ public class BooleanCellEditor extends AbstractCellEditor implements ActionListe
// Update our checkbox with the appropriate state
refCheckBox.removeActionListener(this);
if (value instanceof Boolean)
refCheckBox.setSelected((Boolean)value);
refCheckBox.setSelected((Boolean) value);
refCheckBox.addActionListener(this);
return refCheckBox;

Some files were not shown because too many files have changed in this diff Show More