[DEV] basic port

This commit is contained in:
Edouard DUPIN 2021-02-22 22:02:48 +01:00
parent b328969dc8
commit 8cbbe2f94e
164 changed files with 26277 additions and 0 deletions

7
.checkstyle Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<fileset name="all" enabled="true" check-config-name="ewol" local="false">
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
</fileset-config>

30
.classpath Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**/*.java" kind="src" output="out/eclipse/classes-test" path="test/src">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-14">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/scenarium-logger">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="out/eclipse/classes"/>
</classpath>

17
.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
/bin/
/Operator/
/DrawerProperties/
*.pdfd
*.dbc
SchedulerConfig.txt
scenicView.properties
ScenariumConfig.txt
*.class
*~
*.bck
build.number
/extern/
/out/
/.settings/
/junit/
/target/

24
.project Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>atriasoft-ewol</name>
<comment></comment>
<projects>
<project>atriasoft-ewol</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
</natures>
</projectDescription>

66
CheckStyle.xml Executable file
View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Check Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
This configuration file was written by the eclipse-cs plugin configuration editor
-->
<!--
Checkstyle-Configuration: Marc Checks
Description:
Checkstyle configuration that checks the sun coding conventions.
-->
<module name="Checker">
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<module name="TreeWalker">
<module name="ConstantName"/>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<module name="AvoidStarImport"/>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="false"/>
</module>
<module name="ModifierOrder"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="IllegalInstantiation"/>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="HideUtilityClassConstructor"/>
<module name="InterfaceIsType"/>
<module name="ArrayTypeStyle"/>
<module name="TodoComment"/>
<module name="UpperEll"/>
<module name="AnnotationUseStyle"/>
<module name="MissingDeprecated"/>
<module name="MissingOverride"/>
<module name="PackageAnnotation"/>
<module name="SuppressWarnings"/>
<module name="AnnotationLocation"/>
<module name="ClassTypeParameterName"/>
<module name="MethodTypeParameterName"/>
<module name="InterfaceTypeParameterName"/>
<module name="CatchParameterName"/>
<module name="LambdaParameterName"/>
<module name="Regexp"/>
<module name="RegexpSinglelineJava"/>
</module>
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<module name="Translation"/>
<module name="Header"/>
<module name="RegexpHeader"/>
<module name="RegexpMultiline"/>
<module name="RegexpOnFilename"/>
<module name="RegexpSingleline"/>
</module>

106
CleanUp.xml Normal file
View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="2">
<profile kind="CleanUpProfile" name="EWOL" version="2">
<setting id="cleanup.use_autoboxing" value="false"/>
<setting id="cleanup.always_use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
<setting id="cleanup.format_source_code_changes_only" value="false"/>
<setting id="cleanup.remove_redundant_semicolons" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
<setting id="cleanup.useless_continue" value="false"/>
<setting id="cleanup.remove_redundant_type_arguments" value="true"/>
<setting id="cleanup.remove_unused_imports" value="true"/>
<setting id="cleanup.break_loop" value="false"/>
<setting id="cleanup.pull_up_assignment" value="false"/>
<setting id="cleanup.stringbuilder" value="false"/>
<setting id="cleanup.no_super" value="false"/>
<setting id="cleanup.arrays_fill" value="false"/>
<setting id="cleanup.use_lambda" value="true"/>
<setting id="cleanup.simplify_lambda_expression_and_method_ref" value="false"/>
<setting id="cleanup.always_use_blocks" value="true"/>
<setting id="cleanup.sort_members_all" value="false"/>
<setting id="cleanup.instanceof" value="false"/>
<setting id="cleanup.add_missing_annotations" value="true"/>
<setting id="cleanup.precompile_regex" value="false"/>
<setting id="cleanup.always_use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.boolean_literal" value="false"/>
<setting id="cleanup.always_use_parentheses_in_expressions" value="false"/>
<setting id="cleanup.sort_members" value="false"/>
<setting id="cleanup.remove_unused_local_variables" value="false"/>
<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
<setting id="cleanup.no_string_creation" value="false"/>
<setting id="cleanup.use_unboxing" value="false"/>
<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
<setting id="cleanup.if_condition" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces" value="true"/>
<setting id="cleanup.map_cloning" value="false"/>
<setting id="cleanup.add_serial_version_id" value="true"/>
<setting id="cleanup.try_with_resource" value="false"/>
<setting id="cleanup.use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.use_this_for_non_static_method_access_only_if_necessary" value="true"/>
<setting id="cleanup.make_local_variable_final" value="false"/>
<setting id="cleanup.add_missing_methods" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_with_declaring_class" value="true"/>
<setting id="cleanup.add_missing_override_annotations" value="true"/>
<setting id="cleanup.use_blocks" value="true"/>
<setting id="cleanup.collection_cloning" value="false"/>
<setting id="cleanup.convert_to_enhanced_for_loop_if_loop_var_used" value="false"/>
<setting id="cleanup.make_variable_declarations_final" value="true"/>
<setting id="cleanup.remove_unused_private_types" value="true"/>
<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.organize_imports" value="true"/>
<setting id="cleanup.lazy_logical_operator" value="false"/>
<setting id="cleanup.bitwise_conditional_expression" value="false"/>
<setting id="cleanup.add_all" value="false"/>
<setting id="cleanup.use_directly_map_method" value="false"/>
<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.add_generated_serial_version_id" value="false"/>
<setting id="cleanup.primitive_serialization" value="false"/>
<setting id="cleanup.comparison_statement" value="false"/>
<setting id="cleanup.insert_inferred_type_arguments" value="false"/>
<setting id="cleanup.make_private_fields_final" value="true"/>
<setting id="cleanup.useless_return" value="false"/>
<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
<setting id="cleanup.remove_unnecessary_array_creation" value="false"/>
<setting id="cleanup.remove_private_constructors" value="true"/>
<setting id="cleanup.make_parameters_final" value="false"/>
<setting id="cleanup.ternary_operator" value="false"/>
<setting id="cleanup.merge_conditional_blocks" value="false"/>
<setting id="cleanup.convert_to_enhanced_for_loop" value="false"/>
<setting id="cleanup.remove_unused_private_fields" value="true"/>
<setting id="cleanup.never_use_blocks" value="false"/>
<setting id="cleanup.remove_redundant_modifiers" value="false"/>
<setting id="cleanup.redundant_falling_through_block_end" value="false"/>
<setting id="cleanup.switch" value="false"/>
<setting id="cleanup.number_suffix" value="false"/>
<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
<setting id="cleanup.convert_to_switch_expressions" value="false"/>
<setting id="cleanup.use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.add_missing_nls_tags" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
<setting id="cleanup.remove_unnecessary_casts" value="true"/>
<setting id="cleanup.objects_equals" value="false"/>
<setting id="cleanup.convert_functional_interfaces" value="true"/>
<setting id="cleanup.format_source_code" value="true"/>
<setting id="cleanup.else_if" value="true"/>
<setting id="cleanup.add_default_serial_version_id" value="true"/>
<setting id="cleanup.remove_unused_private_methods" value="true"/>
<setting id="cleanup.make_type_abstract_if_missing_method" value="false"/>
<setting id="cleanup.join" value="false"/>
<setting id="cleanup.embedded_if" value="false"/>
<setting id="cleanup.use_anonymous_class_creation" value="false"/>
<setting id="cleanup.add_missing_override_annotations_interface_methods" value="true"/>
<setting id="cleanup.remove_unused_private_members" value="false"/>
<setting id="cleanup.strictly_equal_or_different" value="false"/>
<setting id="cleanup.never_use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.push_down_negation" value="false"/>
<setting id="cleanup.evaluate_nullable" value="false"/>
<setting id="cleanup.use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.hash" value="false"/>
<setting id="cleanup.double_negation" value="false"/>
<setting id="cleanup.overridden_assignment" value="false"/>
<setting id="cleanup.correct_indentation" value="true"/>
<setting id="cleanup.use_var" value="false"/>
</profile>
</profiles>

390
Formatter.xml Normal file
View File

@ -0,0 +1,390 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="20">
<profile kind="CodeFormatterProfile" name="EWOL" version="20">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="200"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="33"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="33"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_if_empty"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="200"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

373
LICENSE Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

9
src/module-info.java Normal file
View File

@ -0,0 +1,9 @@
/** Basic module interface.
*
* @author Edouard DUPIN */
open module org.atriasoft.etk {
exports org.atriasoft.etk;
exports org.atriasoft.etk.math;
requires transitive io.scenarium.logger;
}

View File

@ -0,0 +1,24 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/DrawProperty.hpp>
#include <ewol/debug.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::DrawProperty);
etk::Stream& ewol::operator <<(etk::Stream& _os, const ewol::DrawProperty& _obj) {
_os << "{ windowsSize=" << _obj.m_windowsSize << " start=" << _obj.m_origin << " stop=" << (_obj.m_origin+_obj.m_size) << "}";
return _os;
}
void ewol::DrawProperty::limit(const vec2& _origin, const vec2& _size) {
m_size += m_origin;
m_origin.setMax(_origin);
m_size.setMin(_origin+_size);
m_size -= m_origin;
}

View File

@ -0,0 +1,48 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/math/Vector2D.hpp>
namespace ewol {
/**
* @not_in_doc
*/
class DrawProperty{
/*
/--> m_windowsSize
*--------------------------------------------------*
| g |
| |
| m_size |
| / |
| o-------------------o |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| o-------------------o |
| / |
| m_origin |
| |
*--------------------------------------------------*
/
(0,0)
*/
public :
ivec2 m_windowsSize; //!< Windows compleate size
ivec2 m_origin; //!< Windows clipping upper widget (can not be <0)
ivec2 m_size; //!< Windows clipping upper widget (can not be <0 and >m_windowsSize)
void limit(const vec2& _origin, const vec2& _size);
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::DrawProperty& _obj);
}

View File

@ -0,0 +1,93 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/Padding.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::Padding);
ewol::Padding::Padding() {
// nothing to do...
}
ewol::Padding::Padding(float _xl, float _yt, float _xr, float _yb) {
setValue(_xl, _yt, _xr, _yb);
}
void ewol::Padding::setValue(float _xl, float _yt, float _xr, float _yb) {
m_value[0] = _xl;
m_value[1] = _yt;
m_value[2] = _xr;
m_value[3] = _yb;
}
float ewol::Padding::x() const {
return m_value[0] + m_value[2];
}
float ewol::Padding::y() const {
return m_value[1] + m_value[3];
}
float ewol::Padding::xLeft() const {
return m_value[0];
}
void ewol::Padding::setXLeft(float _val) {
m_value[0] = _val;
}
float ewol::Padding::xRight() const {
return m_value[2];
}
void ewol::Padding::setXRight(float _val) {
m_value[2] = _val;
}
float ewol::Padding::yTop() const {
return m_value[1];
}
void ewol::Padding::setYTop(float _val) {
m_value[1] = _val;
}
float ewol::Padding::yButtom() const {
return m_value[3];
}
void ewol::Padding::setYButtom(float _val) {
m_value[3] = _val;
}
ewol::Padding& ewol::Padding::operator+=(const Padding& _v) {
m_value[0] += _v.m_value[0];
m_value[1] += _v.m_value[1];
m_value[2] += _v.m_value[2];
m_value[3] += _v.m_value[3];
return *this;
}
ewol::Padding ewol::Padding::operator+(const Padding& _v) {
return Padding(m_value[0] + _v.m_value[0],
m_value[1] + _v.m_value[1],
m_value[2] + _v.m_value[2],
m_value[3] + _v.m_value[3]);
}
etk::Stream& ewol::operator <<(etk::Stream& _os, const ewol::Padding& _obj) {
_os << "{";
_os << _obj.xLeft();
_os << ",";
_os << _obj.yTop();
_os << ",";
_os << _obj.xRight();
_os << ",";
_os << _obj.yButtom();
_os << "}";
return _os;
}

View File

@ -0,0 +1,43 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/Stream.hpp>
namespace ewol {
/**
* @breif Simple class to abstarct the padding porperty.
*/
class Padding {
private:
float m_value[4]; //!< this represent the 4 padding value Left top right buttom (like css)
public:
Padding();
Padding(float _xl, float _yt=0.0f, float _xr=0.0f, float _yb=0.0f);
void setValue(float _xl, float _yt=0.0f, float _xr=0.0f, float _yb=0.0f);
float x() const;
float y() const;
float xLeft() const;
void setXLeft(float _val);
float xRight() const;
void setXRight(float _val);
float yTop() const;
void setYTop(float _val);
float yButtom() const;
void setYButtom(float _val);
/**
* @brief Add a vector to this one
* @param _v The vector to add to this one
*/
Padding& operator+=(const Padding& _v);
//! @previous
Padding operator+(const Padding& _v);
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::Padding& _obj);
};

View File

@ -0,0 +1,142 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/compositing/Area.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::Area);
// VBO table property:
const int32_t ewol::compositing::Area::m_vboIdCoord(0);
const int32_t ewol::compositing::Area::m_vboIdCoordText(1);
const int32_t ewol::compositing::Area::m_vboIdColor(2);
#define NB_VBO (3)
ewol::compositing::Area::Area(const ivec2& _size) :
m_position(0.0, 0.0, 0.0),
m_color(etk::color::white),
m_GLprogram(null),
m_GLPosition(-1),
m_GLMatrix(-1),
m_GLColor(-1),
m_GLtexture(-1),
m_GLtexID(-1),
m_resource(null) {
m_resource = ewol::resource::Texture::create();
m_resource->setImageSize(_size);
m_resource->flush();
// Create the VBO:
m_VBO = gale::resource::VirtualBufferObject::create(NB_VBO);
if (m_VBO == null) {
EWOL_ERROR("can not instanciate VBO ...");
return;
}
// TO facilitate some debugs we add a name of the VBO:
m_VBO->setName("[VBO] of ewol::compositing::Area");
loadProgram();
}
ewol::compositing::Area::~Area() {
}
void ewol::compositing::Area::loadProgram() {
// get the shader resource :
m_GLPosition = 0;
m_GLprogram = gale::resource::Program::create(etk::String("DATA:///textured3D.prog?lib=ewol"));
if (m_GLprogram != null) {
m_GLPosition = m_GLprogram->getAttribute("EW_coord3d");
m_GLColor = m_GLprogram->getAttribute("EW_color");
m_GLtexture = m_GLprogram->getAttribute("EW_texture2d");
m_GLMatrix = m_GLprogram->getUniform("EW_MatrixTransformation");
m_GLtexID = m_GLprogram->getUniform("EW_texID");
}
}
void ewol::compositing::Area::draw(bool _disableDepthTest) {
if (m_VBO->bufferSize(m_vboIdCoord) <= 0) {
//EWOL_WARNING("Nothink to draw...");
return;
}
if (m_resource == null) {
// this is a normale case ... the user can choice to have no image ...
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
// set Matrix : translation/positionMatrix
mat4 tmpMatrix = gale::openGL::getMatrix()*m_matrixApply;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// TextureID
m_GLprogram->setTexture0(m_GLtexID, m_resource->getRendererId());
// position:
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
// Texture:
m_GLprogram->sendAttributePointer(m_GLtexture, m_VBO, m_vboIdColor);
// color:
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdCoordText);
// Request the draw od the elements :
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
}
void ewol::compositing::Area::clear() {
// call upper class
ewol::Compositing::clear();
// reset all VBOs:
m_VBO->clear();
// reset temporal variables :
m_position = vec3(0.0, 0.0, 0.0);
}
void ewol::compositing::Area::print(const ivec2& _size) {
vec3 point(0,0,0);
vec2 tex(0,1);
point.setX(m_position.x());
point.setY(m_position.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoordText, tex);
tex.setValue(1,1);
point.setX(m_position.x() + _size.x());
point.setY(m_position.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoordText, tex);
tex.setValue(1,0);
point.setX(m_position.x() + _size.x());
point.setY(m_position.y() + _size.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoordText, tex);
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoordText, tex);
tex.setValue(0,0);
point.setX(m_position.x());
point.setY(m_position.y() + _size.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoordText, tex);
tex.setValue(0,1);
point.setX(m_position.x());
point.setY(m_position.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoordText, tex);
m_VBO->flush();
}

View File

@ -0,0 +1,101 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/Color.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <gale/resource/Program.hpp>
#include <ewol/resource/Texture.hpp>
#include <egami/Image.hpp>
#include <ememory/memory.hpp>
namespace ewol {
namespace compositing {
class Area : public ewol::Compositing {
private:
vec3 m_position; //!< The current position to draw
etk::Color<float,4> m_color; //!< The text foreground color
private:
ememory::SharedPtr<gale::resource::Program> m_GLprogram; //!< pointer on the opengl display program
int32_t m_GLPosition; //!< openGL id on the element (vertex buffer)
int32_t m_GLMatrix; //!< openGL id on the element (transformation matrix)
int32_t m_GLColor; //!< openGL id on the element (color buffer)
int32_t m_GLtexture; //!< openGL id on the element (Texture position)
int32_t m_GLtexID; //!< openGL id on the element (texture ID)
private:
ememory::SharedPtr<ewol::resource::Texture> m_resource; //!< texture resources
protected:
static const int32_t m_vboIdCoord;
static const int32_t m_vboIdCoordText;
static const int32_t m_vboIdColor;
ememory::SharedPtr<gale::resource::VirtualBufferObject> m_VBO;
private:
/**
* @brief load the openGL program and get all the ID needed
*/
void loadProgram();
public:
/**
* @brief generic constructor
* @param[in] _size Basic size of the area.
*/
Area(const ivec2& _size);
/**
* @brief generic destructor
*/
virtual ~Area();
public:
/**
* @brief draw All the refistered text in the current element on openGL
*/
void draw(bool _disableDepthTest=true);
/**
* @brief clear alll the registered element in the current element
*/
void clear();
/**
* @brief get the current display position (sometime needed in the gui control)
* @return the current position.
*/
const vec3& getPos() {
return m_position;
};
/**
* @brief set position for the next text writen
* @param[in] _pos Position of the text (in 3D)
*/
void setPos(const vec3& _pos) {
m_position = _pos;
};
inline void setPos(const vec2& _pos) {
setPos(vec3(_pos.x(),_pos.y(),0));
};
/**
* @brief set relative position for the next text writen
* @param[in] _pos ofset apply of the text (in 3D)
*/
void setRelPos(const vec3& _pos) {
m_position += _pos;
};
inline void setRelPos(const vec2& _pos) {
setRelPos(vec3(_pos.x(),_pos.y(),0));
};
/**
* @brief add a compleate of the image to display with the requested size
* @param[in] _size size of the output image
*/
void print(const ivec2& _size);
egami::Image& get() {
return m_resource->get();
};
void flush() {
m_resource->flush();
};
};
};
};

View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <etk/math/Matrix4x4.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::Compositing);
ewol::Compositing::Compositing() {
// nothing to do
}
void ewol::Compositing::resetMatrix() {
m_matrixApply.identity();
}
void ewol::Compositing::translate(const vec3& _vect) {
m_matrixApply *= etk::matTranslate(_vect);
}
void ewol::Compositing::rotate(const vec3& _vect, float _angle) {
m_matrixApply *= etk::matRotate(_vect, _angle);
}
void ewol::Compositing::scale(const vec3& _vect) {
m_matrixApply *= etk::matScale(_vect);
}
void ewol::Compositing::clear() {
m_matrixApply.identity();
}
void ewol::Compositing::setMatrix(const mat4& _mat) {
m_matrixApply = _mat;
}

View File

@ -0,0 +1,58 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/debug.hpp>
#include <etk/types.hpp>
#include <etk/math/Matrix4x4.hpp>
namespace ewol {
class Compositing {
protected:
mat4 m_matrixApply;
public:
/**
* @brief generic constructor
*/
Compositing();
/**
* @brief Generic destructor
*/
virtual ~Compositing() = default;
/**
* @brief Virtal pure function that request the draw of all openGl elements
*/
virtual void draw(bool _disableDepthTest = true) = 0;
/**
* @brief clear alll tre registered element in the current element
*/
virtual void clear();
/**
* @brief reset to the eye matrix the openGL mouving system
*/
virtual void resetMatrix();
/**
* @brief translate the current display of this element
* @param[in] _vect The translation vector to apply at the transformation matrix
*/
virtual void translate(const vec3& _vect);
/**
* @brief rotate the curent display of this element
* @param[in] _vect The rotation vector to apply at the transformation matrix
*/
virtual void rotate(const vec3& _vect, float _angle);
/**
* @brief scale the current diaplsy of this element
* @param[in] _vect The scaling vector to apply at the transformation matrix
*/
virtual void scale(const vec3& _vect);
/**
* @brief set the transformation matrix
* @param[in] _mat The new matrix.
*/
virtual void setMatrix(const mat4& _mat);
};
};

View File

@ -0,0 +1,558 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::Drawing);
// VBO table property:
const int32_t ewol::compositing::Drawing::m_vboIdCoord(0);
const int32_t ewol::compositing::Drawing::m_vboIdColor(1);
#define NB_VBO (2)
#if 0
static void generatePolyGone(etk::Vector<vec2 > & input, etk::Vector<vec2 > & output )
{
if (input.size()<3) {
return;
}
// TODO : Regenerate a linear poligone generation
for (int32_t iii=1; iii<input.size()-1; iii++) {
output.pushBack(input[0]);
output.pushBack(input[iii]);
output.pushBack(input[iii+1]);
}
//EWOL_DEBUG("generate Plygone : " << input.size() << " == > " << output.size() );
}
static void SutherlandHodgman(etk::Vector<vec2 > & input, etk::Vector<vec2 > & output, float sx, float sy, float ex, float ey)
{
// with Sutherland-Hodgman-Algorithm
if (input.size() <0) {
return;
}
//int32_t sizeInit=input.size();
// last element :
vec2 destPoint;
vec2 lastElement = input[input.size()-1];
bool inside = true;
if (lastElement.x < sx) {
inside = false;
}
//EWOL_DEBUG("generate an crop : ");
for(int32_t iii=0; iii<input.size(); iii++) {
if(input[iii].x < sx) {
if(true == inside) {
//EWOL_DEBUG("element IN == > OUT ");
//new point intersection ...
//y=aaax+bbb
float aaa = (lastElement.y-input[iii].y) / (lastElement.x-input[iii].x);
float bbb = lastElement.y - (aaa*lastElement.x);
destPoint.y = aaa*sx + bbb;
destPoint.x = sx;
output.pushBack(destPoint);
} else {
//EWOL_DEBUG("element OUT == > OUT ");
}
inside = false;
} else {
if(true == inside) {
//EWOL_DEBUG("element IN == > IN ");
output.pushBack(input[iii]);
} else {
//EWOL_DEBUG("element OUT == > IN ");
//new point intersection ...
//y=aaax+bbb
float aaa = (lastElement.y-input[iii].y) / (lastElement.x-input[iii].x);
float bbb = lastElement.y - (aaa*lastElement.x);
destPoint.y = aaa*sx + bbb;
destPoint.x = sx;
output.pushBack(destPoint);
output.pushBack(input[iii]);
}
inside = true;
}
// update the last point position :
lastElement.x = input[iii].x;
lastElement.y = input[iii].y;
}
//EWOL_DEBUG("generate an crop on element : " << sizeInit << " == > " << output.size() << "intermediate (1)");
input = output;
output.clear();
lastElement = input[input.size()-1];
inside = true;
if (lastElement.y < sy) {
inside = false;
}
for(int32_t iii=0; iii<input.size(); iii++) {
if(input[iii].y < sy) {
if(true == inside) {
//EWOL_DEBUG("element IN == > OUT ");
//new point intersection ...
//x=aaay+bbb
float aaa = (lastElement.x-input[iii].x) / (lastElement.y-input[iii].y);
float bbb = lastElement.x - (aaa*lastElement.y);
destPoint.y = sy;
destPoint.x = sy*aaa + bbb;
output.pushBack(destPoint);
} else {
//EWOL_DEBUG("element OUT == > OUT ");
}
inside = false;
} else {
if(true == inside) {
//EWOL_DEBUG("element IN == > IN ");
output.pushBack(input[iii]);
} else {
//EWOL_DEBUG("element OUT == > IN ");
//new point intersection ...
//y=aaax+bbb
float aaa = (lastElement.x-input[iii].x) / (lastElement.y-input[iii].y);
float bbb = lastElement.x - (aaa*lastElement.y);
destPoint.y = sy;
destPoint.x = sy*aaa + bbb;
output.pushBack(destPoint);
output.pushBack(input[iii]);
}
inside = true;
}
// update the last point position :
lastElement.x = input[iii].x;
lastElement.y = input[iii].y;
}
input = output;
output.clear();
lastElement = input[input.size()-1];
inside = true;
if (lastElement.x > ex) {
inside = false;
}
//EWOL_DEBUG("generate an crop : ");
for(int32_t iii=0; iii<input.size(); iii++) {
if(input[iii].x > ex) {
if(true == inside) {
//EWOL_DEBUG("element IN == > OUT ");
//new point intersection ...
//y=aaax+bbb
float aaa = (lastElement.y-input[iii].y) / (lastElement.x-input[iii].x);
float bbb = lastElement.y - (aaa*lastElement.x);
destPoint.y = aaa*ex + bbb;
destPoint.x = ex;
output.pushBack(destPoint);
} else {
//EWOL_DEBUG("element OUT == > OUT ");
}
inside = false;
} else {
if(true == inside) {
//EWOL_DEBUG("element IN == > IN ");
output.pushBack(input[iii]);
} else {
//EWOL_DEBUG("element OUT == > IN ");
//new point intersection ...
//y=aaax+bbb
float aaa = (lastElement.y-input[iii].y) / (lastElement.x-input[iii].x);
float bbb = lastElement.y - (aaa*lastElement.x);
destPoint.y = aaa*ex + bbb;
destPoint.x = ex;
output.pushBack(destPoint);
output.pushBack(input[iii]);
}
inside = true;
}
// update the last point position :
lastElement.x = input[iii].x;
lastElement.y = input[iii].y;
}
input = output;
output.clear();
lastElement = input[input.size()-1];
inside = true;
if (lastElement.y > ey) {
inside = false;
}
for(int32_t iii=0; iii<input.size(); iii++) {
if(input[iii].y > ey) {
if(true == inside) {
//EWOL_DEBUG("element IN == > OUT ");
//new point intersection ...
//x=aaay+bbb
float aaa = (lastElement.x-input[iii].x) / (lastElement.y-input[iii].y);
float bbb = lastElement.x - (aaa*lastElement.y);
destPoint.y = ey;
destPoint.x = ey*aaa + bbb;
output.pushBack(destPoint);
} else {
//EWOL_DEBUG("element OUT == > OUT ");
}
inside = false;
} else {
if(true == inside) {
//EWOL_DEBUG("element IN == > IN ");
output.pushBack(input[iii]);
} else {
//EWOL_DEBUG("element OUT == > IN ");
//new point intersection ...
//y=aaax+bbb
float aaa = (lastElement.x-input[iii].x) / (lastElement.y-input[iii].y);
float bbb = lastElement.x - (aaa*lastElement.y);
destPoint.y = ey;
destPoint.x = ey*aaa + bbb;
output.pushBack(destPoint);
output.pushBack(input[iii]);
}
inside = true;
}
// update the last point position :
lastElement.x = input[iii].x;
lastElement.y = input[iii].y;
}
//EWOL_DEBUG("generate an crop on element : " << sizeInit << " == > " << output.size() );
}
#endif
ewol::compositing::Drawing::Drawing() :
m_position(0.0, 0.0, 0.0),
m_clippingPosStart(0.0, 0.0, 0.0),
m_clippingPosStop(0.0, 0.0, 0.0),
m_clippingEnable(false),
m_color(etk::color::black),
m_colorBg(etk::color::none),
m_GLprogram(null),
m_GLPosition(-1),
m_GLMatrix(-1),
m_GLMatrixPosition(-1),
m_GLColor(-1),
m_thickness(0.0),
m_triElement(0) {
loadProgram();
for (int32_t iii=0; iii<3; iii++) {
m_triangle[iii] = m_position;
m_tricolor[iii] = m_color;
}
// Create the VBO:
m_VBO = gale::resource::VirtualBufferObject::create(NB_VBO);
if (m_VBO == null) {
EWOL_ERROR("can not instanciate VBO ...");
return;
}
// TO facilitate some debugs we add a name of the VBO:
m_VBO->setName("[VBO] of ewol::compositing::Area");
}
ewol::compositing::Drawing::~Drawing() {
unLoadProgram();
}
void ewol::compositing::Drawing::generateTriangle() {
m_triElement = 0;
m_VBO->pushOnBuffer(m_vboIdCoord, m_triangle[0]);
m_VBO->pushOnBuffer(m_vboIdColor, m_tricolor[0]);
m_VBO->pushOnBuffer(m_vboIdCoord, m_triangle[1]);
m_VBO->pushOnBuffer(m_vboIdColor, m_tricolor[1]);
m_VBO->pushOnBuffer(m_vboIdCoord, m_triangle[2]);
m_VBO->pushOnBuffer(m_vboIdColor, m_tricolor[2]);
}
void ewol::compositing::Drawing::internalSetColor(const etk::Color<>& _color) {
if (m_triElement < 1) {
m_tricolor[0] = _color;
}
if (m_triElement < 2) {
m_tricolor[1] = _color;
}
if (m_triElement < 3) {
m_tricolor[2] = _color;
}
}
void ewol::compositing::Drawing::setPoint(const vec3& _point) {
m_triangle[m_triElement] = _point;
m_triElement++;
if (m_triElement >= 3) {
generateTriangle();
}
m_VBO->flush();
}
void ewol::compositing::Drawing::resetCount() {
m_triElement = 0;
}
void ewol::compositing::Drawing::unLoadProgram() {
m_GLprogram.reset();
}
void ewol::compositing::Drawing::loadProgram() {
// remove previous loading ... in case
unLoadProgram();
// oad the new ...
m_GLprogram = gale::resource::Program::create("DATA:///color3.prog?lib=ewol");
// get the shader resource :
if (m_GLprogram != null) {
m_GLPosition = m_GLprogram->getAttribute("EW_coord3d");
m_GLColor = m_GLprogram->getAttribute("EW_color");
m_GLMatrix = m_GLprogram->getUniform("EW_MatrixTransformation");
m_GLMatrixPosition = m_GLprogram->getUniform("EW_MatrixPosition");
}
}
void ewol::compositing::Drawing::draw(bool _disableDepthTest) {
if (m_VBO->bufferSize(m_vboIdCoord) <= 0) {
// TODO : set it back ...
//EWOL_WARNING("Nothink to draw...");
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
// set Matrix : translation/positionMatrix
mat4 tmpMatrix = gale::openGL::getMatrix()*m_matrixApply;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
mat4 tmpMatrix2;
m_GLprogram->uniformMatrix(m_GLMatrixPosition, tmpMatrix2);
// position:
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
// color:
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdColor);
// Request the draw od the elements :
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
}
void ewol::compositing::Drawing::clear() {
// call upper class
ewol::Compositing::clear();
// reset Buffer :
m_VBO->clear();
// reset temporal variables :
m_position = vec3(0.0, 0.0, 0.0);
m_clippingPosStart = vec3(0.0, 0.0, 0.0);
m_clippingPosStop = vec3(0.0, 0.0, 0.0);
m_clippingEnable = false;
m_color = etk::color::black;
m_colorBg = etk::color::none;
for (int32_t iii=0; iii<3; iii++) {
m_triangle[iii] = m_position;
m_tricolor[iii] = m_color;
}
}
void ewol::compositing::Drawing::setClipping(const vec3& _pos, const vec3& _posEnd) {
// note the internal system all time request to have a bounding all time in the same order
if (_pos.x() <= _posEnd.x()) {
m_clippingPosStart.setX(_pos.x());
m_clippingPosStop.setX(_posEnd.x());
} else {
m_clippingPosStart.setX(_posEnd.x());
m_clippingPosStop.setX(_pos.x());
}
if (_pos.y() <= _posEnd.y()) {
m_clippingPosStart.setY(_pos.y());
m_clippingPosStop.setY(_posEnd.y());
} else {
m_clippingPosStart.setY(_posEnd.y());
m_clippingPosStop.setY(_pos.y());
}
if (_pos.z() <= _posEnd.z()) {
m_clippingPosStart.setZ(_pos.z());
m_clippingPosStop.setZ(_posEnd.z());
} else {
m_clippingPosStart.setZ(_posEnd.z());
m_clippingPosStop.setZ(_pos.z());
}
m_clippingEnable = true;
}
void ewol::compositing::Drawing::setThickness(float _thickness) {
m_thickness = _thickness;
// thickness must be positive
if (m_thickness < 0) {
m_thickness *= -1;
}
}
void ewol::compositing::Drawing::addVertex() {
internalSetColor(m_color);
setPoint(m_position);
}
void ewol::compositing::Drawing::lineTo(const vec3& _dest) {
resetCount();
internalSetColor(m_color);
//EWOL_VERBOSE("DrawLine : " << m_position << " to " << _dest);
if (m_position.x() == _dest.x() && m_position.y() == _dest.y() && m_position.z() == _dest.z()) {
//EWOL_WARNING("Try to draw a line width 0");
return;
}
//teta = tan-1(oposer/adjacent)
float teta = 0;
if (m_position.x() <= _dest.x()) {
teta = atan((_dest.y()-m_position.y())/(_dest.x()-m_position.x()));
} else {
teta = M_PI + atan((_dest.y()-m_position.y())/(_dest.x()-m_position.x()));
}
if (teta < 0) {
teta += 2*M_PI;
} else if (teta > 2*M_PI) {
teta -= 2*M_PI;
}
//EWOL_DEBUG("teta = " << (teta*180/(M_PI)) << " deg." );
float offsety = sin(teta-M_PI/2) * (m_thickness/2);
float offsetx = cos(teta-M_PI/2) * (m_thickness/2);
setPoint(vec3(m_position.x() - offsetx, m_position.y() - offsety, m_position.z()) );
setPoint(vec3(m_position.x() + offsetx, m_position.y() + offsety, m_position.z()) );
setPoint(vec3(_dest.x() + offsetx, _dest.y() + offsety, m_position.z()) );
setPoint(vec3(_dest.x() + offsetx, _dest.y() + offsety, _dest.z()) );
setPoint(vec3(_dest.x() - offsetx, _dest.y() - offsety, _dest.z()) );
setPoint(vec3(m_position.x() - offsetx, m_position.y() - offsety, _dest.z()) );
// update the system position :
m_position = _dest;
}
void ewol::compositing::Drawing::rectangle(const vec3& _dest) {
resetCount();
internalSetColor(m_color);
/* Bitmap position
* xA xB
* yC *------*
* | |
* | |
* yD *------*
*/
float dxA = m_position.x();
float dxB = _dest.x();
if (dxA > dxB) {
// inverse order :
float tmp = dxA;
dxA = dxB;
dxB = tmp;
}
float dyC = m_position.y();
float dyD = _dest.y();
if (dyC > dyD) {
// inverse order :
float tmp = dyC;
dyC = dyD;
dyD = tmp;
}
if (true == m_clippingEnable) {
if (dxA < m_clippingPosStart.x()) {
dxA = m_clippingPosStart.x();
}
if (dxB > m_clippingPosStop.x()) {
dxB = m_clippingPosStop.x();
}
if (dyC < m_clippingPosStart.y()) {
dyC = m_clippingPosStart.y();
}
if (dyD > m_clippingPosStop.y()) {
dyD = m_clippingPosStop.y();
}
}
if( dyC >= dyD
|| dxA >= dxB) {
return;
}
setPoint(vec3(dxA, dyD, 0) );
setPoint(vec3(dxA, dyC, 0) );
setPoint(vec3(dxB, dyC, 0) );
setPoint(vec3(dxB, dyC, 0) );
setPoint(vec3(dxB, dyD, 0) );
setPoint(vec3(dxA, dyD, 0) );
}
void ewol::compositing::Drawing::cube(const vec3& _dest) {
}
void ewol::compositing::Drawing::circle(float _radius, float _angleStart, float _angleStop) {
resetCount();
if (_radius<0) {
_radius *= -1;
}
_angleStop = _angleStop-_angleStart;
int32_t nbOcurence = _radius;
if (nbOcurence < 10)
{
nbOcurence = 10;
}
// display background :
if (m_colorBg.a()!=0) {
internalSetColor(m_colorBg);
for (int32_t iii=0; iii<nbOcurence; iii++) {
setPoint(vec3(m_position.x(),
m_position.y(),
0) );
float angleOne = _angleStart + (_angleStop* iii / nbOcurence) ;
float offsety = sin(angleOne) * _radius;
float offsetx = cos(angleOne) * _radius;
setPoint(vec3(m_position.x() + offsetx,
m_position.y() + offsety,
0) );
float angleTwo = _angleStart + (_angleStop* (iii+1) / nbOcurence) ;
offsety = sin(angleTwo) * _radius;
offsetx = cos(angleTwo) * _radius;
setPoint(vec3(m_position.x() + offsetx,
m_position.y() + offsety,
0) );
}
}
// show if we have a border :
if( m_thickness == 0
|| m_color.a() == 0) {
return;
}
internalSetColor(m_color);
for (int32_t iii=0; iii<nbOcurence; iii++) {
float angleOne = _angleStart + (_angleStop* iii / nbOcurence) ;
float offsetExty = sin(angleOne) * (_radius+m_thickness/2);
float offsetExtx = cos(angleOne) * (_radius+m_thickness/2);
float offsetInty = sin(angleOne) * (_radius-m_thickness/2);
float offsetIntx = cos(angleOne) * (_radius-m_thickness/2);
float angleTwo = _angleStart + (_angleStop* (iii+1) / nbOcurence );
float offsetExt2y = sin(angleTwo) * (_radius+m_thickness/2);
float offsetExt2x = cos(angleTwo) * (_radius+m_thickness/2);
float offsetInt2y = sin(angleTwo) * (_radius-m_thickness/2);
float offsetInt2x = cos(angleTwo) * (_radius-m_thickness/2);
setPoint(vec3(m_position.x() + offsetIntx, m_position.y() + offsetInty, 0));
setPoint(vec3(m_position.x() + offsetExtx, m_position.y() + offsetExty, 0));
setPoint(vec3(m_position.x() + offsetExt2x, m_position.y() + offsetExt2y, 0));
setPoint(vec3(m_position.x() + offsetExt2x, m_position.y() + offsetExt2y, 0));
setPoint(vec3(m_position.x() + offsetInt2x, m_position.y() + offsetInt2y, 0));
setPoint(vec3(m_position.x() + offsetIntx, m_position.y() + offsetInty, 0));
}
}

View File

@ -0,0 +1,229 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/Color.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <gale/resource/Program.hpp>
namespace ewol {
namespace compositing {
class Drawing : public ewol::Compositing {
private:
vec3 m_position; //!< The current position to draw
vec3 m_clippingPosStart; //!< Clipping start position
vec3 m_clippingPosStop; //!< Clipping stop position
bool m_clippingEnable; //!< true if the clipping must be activated
private:
etk::Color<> m_color; //!< The text foreground color
etk::Color<> m_colorBg; //!< The text background color
private:
ememory::SharedPtr<gale::resource::Program> m_GLprogram; //!< pointer on the opengl display program
int32_t m_GLPosition; //!< openGL id on the element (vertex buffer)
int32_t m_GLMatrix; //!< openGL id on the element (transformation matrix)
int32_t m_GLMatrixPosition; //!< position matrix
int32_t m_GLColor; //!< openGL id on the element (color buffer)
protected:
static const int32_t m_vboIdCoord;
static const int32_t m_vboIdColor;
ememory::SharedPtr<gale::resource::VirtualBufferObject> m_VBO;
public:
/**
* @brief Basic constructor
*/
Drawing();
/**
* @brief Basic destructor
*/
virtual ~Drawing();
private:
/**
* @brief load the openGL program and get all the ID needed
*/
void loadProgram();
/**
* @brief Un-Load the openGL program and get all the ID needed
*/
void unLoadProgram();
float m_thickness; //!< when drawing line and other things
int32_t m_triElement; //!< special counter of the single dot generated
vec3 m_triangle[3]; //!< Register every system with a combinaison of tiangle
etk::Color<float,4> m_tricolor[3]; //!< Register every the associated color foreground
// internal API for the generation abstraction of triangles
/**
* @brief Lunch the generation of triangle
*/
void generateTriangle();
/**
* @brief in case of some error the count can be reset
*/
void resetCount();
/**
* @brief set the Color of the current triangle drawing
* @param[in] _color Color to current dots generated
*/
void internalSetColor(const etk::Color<>& _color);
/**
* @brief internal add of the specific point
* @param[in] _point The requeste dpoint to add
*/
void setPoint(const vec3& point);
public:
/**
* @brief draw All the refistered text in the current element on openGL
*/
void draw(bool _disableDepthTest=true);
/**
* @brief clear alll tre registered element in the current element
*/
void clear();
/**
* @brief get the current display position (sometime needed in the gui control)
* @return the current position.
*/
const vec3& getPos() {
return m_position;
};
/**
* @brief set position for the next text writen
* @param[in] _pos Position of the text (in 3D)
*/
void setPos(const vec3& _pos) {
m_position = _pos;
};
inline void setPos(const vec2& _pos) {
setPos(vec3(_pos.x(), _pos.y(), 0));
};
/**
* @brief set relative position for the next text writen
* @param[in] _pos ofset apply of the text (in 3D)
*/
void setRelPos(const vec3& _pos) {
m_position += _pos;
};
inline void setRelPos(const vec2& _pos) {
setRelPos(vec3(_pos.x(), _pos.y(), 0));
};
/**
* @brief set the Color of the current foreground font
* @param[in] _color Color to set on foreground (for next print)
*/
void setColor(const etk::Color<>& _color) {
m_color = _color;
};
/**
* @brief Get the foreground color of the font.
* @return Foreground color.
*/
const etk::Color<>& getColor() {
return m_color;
};
/**
* @brief set the background color of the font (for selected Text (not the global BG))
* @param[in] _color Color to set on background (for next print)
*/
void setColorBg(const etk::Color<>& _color) {
m_colorBg = _color;
};
/**
* @brief Get the background color of the font.
* @return Background color.
*/
const etk::Color<>& getColorBg() {
return m_colorBg;
};
/**
* @brief Request a clipping area for the text (next draw only)
* @param[in]_ pos Start position of the clipping
* @param[in] _width Width size of the clipping
*/
void setClippingWidth(const vec3& _pos, const vec3& _width) {
setClipping(_pos, _pos+_width);
};
inline void setClippingWidth(const vec2& _pos, const vec2& _width) {
setClippingWidth(vec3(_pos.x(),_pos.y(),-1), vec3(_width.x(),_width.y(), 2));
};
/**
* @brief Request a clipping area for the text (next draw only)
* @param[in] _pos Start position of the clipping
* @param[in] _posEnd End position of the clipping
*/
void setClipping(const vec3& _pos, const vec3& _posEnd);
inline void setClipping(const vec2& _pos, const vec2& _posEnd) {
setClipping(vec3(_pos.x(),_pos.y(),-1), vec3(_posEnd.x(),_posEnd.y(), 1));
};
/**
* @brief enable/Disable the clipping (without lose the current clipping position)
* @brief _newMode The new status of the clipping
*/
void setClippingMode(bool _newMode) {
m_clippingEnable = _newMode;
};
/**
* @brief Specify the line thickness for the next elements
* @param[in] _thickness The thickness disired for the next print
*/
void setThickness(float _thickness);
/**
* @brief add a point reference at the current position (this is a vertex reference at the current position
*/
void addVertex();
/**
* @brief draw a line to a specific position
* @param[in] _dest Position of the end of the line.
*/
void lineTo(const vec3& _dest);
inline void lineTo(const vec2& _dest) {
lineTo(vec3(_dest.x(), _dest.y(), 0));
};
/**
* @brief Relative drawing a line (spacial vector)
* @param[in] _vect Vector of the curent line.
*/
void lineRel(const vec3& _vect) {
lineTo(m_position+_vect);
};
inline void lineRel(const vec2& _vect) {
lineRel(vec3(_vect.x(), _vect.y(), 0));
};
/**
* @brief draw a 2D rectangle to the position requested.
* @param[in] _dest Position the the end of the rectangle
*/
void rectangle(const vec3& _dest);
inline void rectangle(const vec2& _dest) {
rectangle(vec3(_dest.x(), _dest.y(), 0));
};
/**
* @brief draw a 2D rectangle to the requested size.
* @param[in] _size size of the rectangle
*/
void rectangleWidth(const vec3& _size) {
rectangle(m_position+_size);
};
inline void rectangleWidth(const vec2& _size) {
rectangleWidth(vec3(_size.x(), _size.y(), 0));
};
/**
* @brief draw a 3D rectangle to the position requested.
* @param[in] _dest Position the the end of the rectangle
*/
void cube(const vec3& _dest);
/**
* @brief draw a 2D circle with the specify rafdius parameter.
* @param[in] _radius Distence to the dorder
* @param[in] _angleStart start angle of this circle ([0..2PI] otherwithe == > disable)
* @param[in] _angleStop stop angle of this circle ([0..2PI] otherwithe == > disable)
*/
void circle(float _radius, float _angleStart = 0, float _angleStop = 2*M_PI);
};
};
};

View File

@ -0,0 +1,364 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/compositing/Image.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::Image);
const int32_t ewol::compositing::Image::sizeAuto(0);
// VBO table property:
const int32_t ewol::compositing::Image::m_vboIdCoord(0);
const int32_t ewol::compositing::Image::m_vboIdCoordTex(1);
const int32_t ewol::compositing::Image::m_vboIdColor(2);
#define NB_VBO (3)
ewol::compositing::Image::Image(const etk::Uri& _imageName,
bool _df,
int32_t _size) :
m_filename(_imageName),
m_requestSize(2,2),
m_position(0.0, 0.0, 0.0),
m_clippingPosStart(0.0, 0.0, 0.0),
m_clippingPosStop(0.0, 0.0, 0.0),
m_clippingEnable(false),
m_color(etk::color::white),
m_angle(0.0),
m_GLprogram(null),
m_GLPosition(-1),
m_GLMatrix(-1),
m_GLColor(-1),
m_GLtexture(-1),
m_GLtexID(-1),
m_distanceFieldMode(_df),
m_resource(null),
m_resourceDF(null) {
// Create the VBO:
m_VBO = gale::resource::VirtualBufferObject::create(NB_VBO);
if (m_VBO == null) {
EWOL_ERROR("can not instanciate VBO ...");
return;
}
// TO facilitate some debugs we add a name of the VBO:
m_VBO->setName("[VBO] of ewol::compositing::Image");
setSource(_imageName, _size);
loadProgram();
}
ewol::compositing::Image::~Image() {
}
void ewol::compositing::Image::loadProgram() {
// get the shader resource:
m_GLPosition = 0;
m_GLprogram.reset();
if (m_distanceFieldMode == true) {
m_GLprogram = gale::resource::Program::create("DATA:///texturedDF.prog?lib=ewol");
} else {
m_GLprogram = gale::resource::Program::create("DATA:///textured3D.prog?lib=ewol");
}
if (m_GLprogram != null) {
m_GLPosition = m_GLprogram->getAttribute("EW_coord3d");
m_GLColor = m_GLprogram->getAttribute("EW_color");
m_GLtexture = m_GLprogram->getAttribute("EW_texture2d");
m_GLMatrix = m_GLprogram->getUniform("EW_MatrixTransformation");
m_GLtexID = m_GLprogram->getUniform("EW_texID");
}
}
void ewol::compositing::Image::draw(bool _disableDepthTest) {
if (m_VBO->bufferSize(m_vboIdCoord) <= 0) {
//EWOL_WARNING("Nothink to draw...");
return;
}
if ( m_resource == null
&& m_resourceDF == null
&& m_resourceImage == null) {
// this is a normale case ... the user can choice to have no image ...
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
//EWOL_WARNING("Display image : " << m_VBO->bufferSize(m_vboIdCoord));
if (_disableDepthTest == true) {
gale::openGL::disable(gale::openGL::flag_depthTest);
} else {
gale::openGL::enable(gale::openGL::flag_depthTest);
}
// set Matrix : translation/positionMatrix
mat4 tmpMatrix = gale::openGL::getMatrix()*m_matrixApply;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// TextureID
if (m_resourceImage != null) {
m_GLprogram->setTexture0(m_GLtexID, m_resourceImage->getRendererId());
} else if (m_resource != null) {
if (m_distanceFieldMode == true) {
EWOL_ERROR("FONT type error Request distance field and display normal ...");
}
m_GLprogram->setTexture0(m_GLtexID, m_resource->getRendererId());
} else {
if (m_distanceFieldMode == false) {
EWOL_ERROR("FONT type error Request normal and display distance field ...");
}
m_GLprogram->setTexture0(m_GLtexID, m_resourceDF->getRendererId());
}
// position:
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
// Texture:
m_GLprogram->sendAttributePointer(m_GLtexture, m_VBO, m_vboIdCoordTex);
// color:
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdColor);
// Request the draw of the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
}
void ewol::compositing::Image::clear() {
// call upper class
ewol::Compositing::clear();
// reset Buffer :
m_VBO->clear();
// reset temporal variables :
m_position = vec3(0.0, 0.0, 0.0);
m_clippingPosStart = vec3(0.0, 0.0, 0.0);
m_clippingPosStop = vec3(0.0, 0.0, 0.0);
m_clippingEnable = false;
m_color = etk::color::white;
m_angle = 0.0;
}
void ewol::compositing::Image::setClipping(const vec3& _pos, vec3 _posEnd) {
// note the internal system all time request to have a bounding all time in the same order
if (_pos.x() <= _posEnd.x()) {
m_clippingPosStart.setX(_pos.x());
m_clippingPosStop.setX(_posEnd.x());
} else {
m_clippingPosStart.setX(_posEnd.x());
m_clippingPosStop.setX(_pos.x());
}
if (_pos.y() <= _posEnd.y()) {
m_clippingPosStart.setY(_pos.y());
m_clippingPosStop.setY(_posEnd.y());
} else {
m_clippingPosStart.setY(_posEnd.y());
m_clippingPosStop.setY(_pos.y());
}
if (_pos.z() <= _posEnd.z()) {
m_clippingPosStart.setZ(_pos.z());
m_clippingPosStop.setZ(_posEnd.z());
} else {
m_clippingPosStart.setZ(_posEnd.z());
m_clippingPosStop.setZ(_pos.z());
}
m_clippingEnable = true;
}
void ewol::compositing::Image::setAngle(float _angle) {
m_angle = _angle;
}
void ewol::compositing::Image::print(const vec2& _size) {
printPart(_size, vec2(0,0), vec2(1.0,1.0));
}
void ewol::compositing::Image::printPart(const vec2& _size,
vec2 _sourcePosStart,
vec2 _sourcePosStop) {
if (m_resource == null) {
return;
}
vec2 openGLSize = vec2(m_resource->getOpenGlSize().x(), m_resource->getOpenGlSize().y());
vec2 usefullSize = m_resource->getUsableSize();
vec2 ratio = usefullSize/openGLSize;
_sourcePosStart *= ratio;
_sourcePosStop *= ratio;
EWOL_VERBOSE(" openGLSize=" << openGLSize << " usableSize=" << usefullSize << " start=" << _sourcePosStart << " stop=" << _sourcePosStop);
//EWOL_ERROR("Debug image " << m_filename << " ==> " << m_position << " " << _size << " " << _sourcePosStart << " " << _sourcePosStop);
if (m_angle == 0.0f) {
vec3 point = m_position;
vec2 tex(_sourcePosStart.x(),_sourcePosStop.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStop.x(),_sourcePosStop.y());
point.setX(m_position.x() + _size.x());
point.setY(m_position.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStop.x(),_sourcePosStart.y());
point.setX(m_position.x() + _size.x());
point.setY(m_position.y() + _size.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStart.x(),_sourcePosStart.y());
point.setX(m_position.x());
point.setY(m_position.y() + _size.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStart.x(),_sourcePosStop.y());
point.setX(m_position.x());
point.setY(m_position.y());
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->flush();
return;
}
vec3 center = m_position + vec3(_size.x(),_size.y(),0)/2.0f;
vec3 limitedSize(_size.x()*0.5f, _size.y()*0.5f, 0.0f);
vec3 point(0,0,0);
vec2 tex(_sourcePosStart.x(),_sourcePosStop.y());
point.setValue(-limitedSize.x(), -limitedSize.y(), 0);
point = point.rotate(vec3(0,0,1), m_angle) + center;
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStop.x(),_sourcePosStop.y());
point.setValue(limitedSize.x(), -limitedSize.y(), 0);
point = point.rotate(vec3(0,0,1), m_angle) + center;
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStop.x(),_sourcePosStart.y());
point.setValue(limitedSize.x(), limitedSize.y(), 0);
point = point.rotate(vec3(0,0,1), m_angle) + center;
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStart.x(),_sourcePosStart.y());
point.setValue(-limitedSize.x(), limitedSize.y(), 0);
point = point.rotate(vec3(0,0,1), m_angle) + center;
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
tex.setValue(_sourcePosStart.x(),_sourcePosStop.y());
point.setValue(-limitedSize.x(), -limitedSize.y(), 0);
point = point.rotate(vec3(0,0,1), m_angle) + center;
m_VBO->pushOnBuffer(m_vboIdCoord, point);
m_VBO->pushOnBuffer(m_vboIdCoordTex, tex);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->flush();
}
void ewol::compositing::Image::setSource(const etk::Uri& _uri, const vec2& _size) {
clear();
if ( m_filename == _uri
&& m_requestSize == _size) {
// Nothing to do ...
return;
}
ememory::SharedPtr<ewol::resource::TextureFile> resource = m_resource;
ememory::SharedPtr<ewol::resource::ImageDF> resourceDF = m_resourceDF;
ememory::SharedPtr<ewol::resource::Texture> resourceTex = m_resourceImage;
m_filename = _uri;
m_requestSize = _size;
m_resource.reset();
m_resourceDF.reset();
m_resourceImage.reset();
ivec2 tmpSize(_size.x(),_size.y());
// note that no image can be loaded...
if (_uri.isEmpty() == false) {
// link to new one
if (m_distanceFieldMode == false) {
m_resource = ewol::resource::TextureFile::create(m_filename, tmpSize);
if (m_resource == null) {
EWOL_ERROR("Can not get Image resource");
}
} else {
m_resourceDF = ewol::resource::ImageDF::create(m_filename, tmpSize);
if (m_resourceDF == null) {
EWOL_ERROR("Can not get Image resource DF");
}
}
}
if ( m_resource == null
&& m_resourceDF == null
&& m_resourceImage == null) {
if (resource != null) {
EWOL_WARNING("Retrive previous resource");
m_resource = resource;
}
if (resourceDF != null) {
EWOL_WARNING("Retrive previous resource (DF)");
m_resourceDF = resourceDF;
}
if (resourceTex != null) {
EWOL_WARNING("Retrive previous resource (image)");
m_resourceImage = resourceTex;
}
}
}
void ewol::compositing::Image::setSource(egami::Image _image) {
clear();
m_filename = "direct image BUFFER";
m_requestSize = _image.getSize();
m_resourceImage = ewol::resource::Texture::create();
m_resourceImage->set(etk::move(_image));
}
bool ewol::compositing::Image::hasSources() {
return m_resource != null
|| m_resourceDF != null;
}
vec2 ewol::compositing::Image::getRealSize() {
if ( m_resource == null
&& m_resourceDF == null
&& m_resourceImage == null) {
return vec2(0,0);
}
if (m_resource != null) {
return m_resource->getRealSize();
}
if (m_resourceDF != null) {
return m_resourceDF->getRealSize();
}
if (m_resourceImage != null) {
return m_resourceImage->getUsableSize();
}
return vec2(0,0);
}
void ewol::compositing::Image::setDistanceFieldMode(bool _mode) {
if (m_distanceFieldMode == _mode) {
return;
}
m_distanceFieldMode = _mode;
// Force reload input
setSource(m_filename, m_requestSize);
loadProgram();
}

View File

@ -0,0 +1,193 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <gale/resource/Program.hpp>
#include <ewol/resource/TextureFile.hpp>
#include <ewol/resource/ImageDF.hpp>
namespace ewol {
namespace compositing {
class Image : public ewol::Compositing {
public:
static const int32_t sizeAuto;
private:
etk::Uri m_filename;
ivec2 m_requestSize;
vec3 m_position; //!< The current position to draw
vec3 m_clippingPosStart; //!< Clipping start position
vec3 m_clippingPosStop; //!< Clipping stop position
bool m_clippingEnable; //!< true if the clipping must be activated
private:
etk::Color<float,4> m_color; //!< The text foreground color
float m_angle; //!< Angle to set at the axes
private:
ememory::SharedPtr<gale::resource::Program> m_GLprogram; //!< pointer on the opengl display program
int32_t m_GLPosition; //!< openGL id on the element (vertex buffer)
int32_t m_GLMatrix; //!< openGL id on the element (transformation matrix)
int32_t m_GLColor; //!< openGL id on the element (color buffer)
int32_t m_GLtexture; //!< openGL id on the element (Texture position)
int32_t m_GLtexID; //!< openGL id on the element (texture ID)
private:
bool m_distanceFieldMode; //!< select distance field mode
ememory::SharedPtr<ewol::resource::TextureFile> m_resource; //!< texture resources
ememory::SharedPtr<ewol::resource::Texture> m_resourceImage; //!< texture resources
ememory::SharedPtr<ewol::resource::ImageDF> m_resourceDF; //!< texture resources
static const int32_t m_vboIdCoord;
static const int32_t m_vboIdCoordTex;
static const int32_t m_vboIdColor;
ememory::SharedPtr<gale::resource::VirtualBufferObject> m_VBO;
private:
/**
* @brief load the openGL program and get all the ID needed
*/
void loadProgram();
public:
/**
* @brief generic constructor
* @param[in] _uri URI of the file that might be loaded
* @param[in] _df enable distance field mode
* @param[in] _size for the image when Verctorial image loading is requested
*/
Image(const etk::Uri& _uri="",
bool _df=false,
int32_t _size=ewol::compositing::Image::sizeAuto);
/**
* @brief generic destructor
*/
virtual ~Image();
public:
/**
* @brief draw All the refistered text in the current element on openGL
* @param[in] _disableDepthTest disable the Depth test for display
*/
void draw(bool _disableDepthTest=true);
/**
* @brief clear alll tre registered element in the current element
*/
void clear();
/**
* @brief get the current display position (sometime needed in the gui control)
* @return the current position.
*/
const vec3& getPos() {
return m_position;
};
/**
* @brief set position for the next text writen
* @param[in] _pos Position of the text (in 3D)
*/
void setPos(const vec3& _pos) {
m_position = _pos;
};
inline void setPos(const vec2& _pos) {
setPos(vec3(_pos.x(),_pos.y(),0));
};
/**
* @brief set relative position for the next text writen
* @param[in] _pos ofset apply of the text (in 3D)
*/
void setRelPos(const vec3& _pos) {
m_position += _pos;
};
inline void setRelPos(const vec2& _pos) {
setRelPos(vec3(_pos.x(),_pos.y(),0));
};
/**
* @brief set the Color of the current foreground font
* @param[in] _color Color to set on foreground (for next print)
*/
void setColor(const etk::Color<>& _color) {
m_color = _color;
};
/**
* @brief Request a clipping area for the text (next draw only)
* @param[in] _pos Start position of the clipping
* @param[in] _width Width size of the clipping
*/
void setClippingWidth(const vec3& _pos, vec3 _width) {
setClipping(_pos, _pos+_width);
};
inline void setClippingWidth(const vec2& _pos, const vec2& _width) {
setClippingWidth(vec3(_pos.x(),_pos.y(),0), vec3(_width.x(),_width.y(),0));
};
/**
* @brief Request a clipping area for the text (next draw only)
* @param[in] _pos Start position of the clipping
* @param[in] _posEnd End position of the clipping
*/
void setClipping(const vec3& _pos, vec3 _posEnd);
inline void setClipping(const vec2& _pos, const vec2& _posEnd) {
setClipping(vec3(_pos.x(),_pos.y(),0), vec3(_posEnd.x(),_posEnd.y(),0));
};
/**
* @brief enable/Disable the clipping (without lose the current clipping position)
* @brief _newMode The new status of the clipping
*/
void setClippingMode(bool _newMode) {
m_clippingEnable = _newMode;
};
/**
* @brief set a unique rotation of this element (not set in the rotate Generic system)
* @param[in] _angle Angle to set in radiant.
*/
void setAngle(float _angleRad);
/**
* @brief add a compleate of the image to display with the requested size
* @param[in] _size size of the output image
*/
void print(const ivec2& _size) {
print(vec2(_size.x(),_size.y()));
};
void print(const vec2& _size);
/**
* @brief add a part of the image to display with the requested size
* @param[in] _size size of the output image
* @param[in] _sourcePosStart Start position in the image [0..1] (can be bigger but this repeate the image).
* @param[in] _sourcePosStop Stop position in the image [0..1] (can be bigger but this repeate the image).
*/
void printPart(const vec2& _size,
vec2 _sourcePosStart,
vec2 _sourcePosStop);
/**
* @brief change the image Source == > can not be done to display 2 images at the same time ...
* @param[in] _uri New file of the Image
* @param[in] _size for the image when Verctorial image loading is requested
*/
void setSource(const etk::Uri& _uri, int32_t _size=32) {
setSource(_uri, vec2(_size,_size));
};
void setSource(const etk::Uri& _uri, const vec2& _size);
void setSource(egami::Image _image);
/**
* @brief Sometimes the user declare an image but not allocate the ressources all the time, this is to know it ..
* @return the validity od the resources.
*/
bool hasSources();
/**
* @brief get the source image registered size in the file (<0 when multiple size image)
* @return tre image registered size
*/
vec2 getRealSize();
public:
/**
* @brief Set render mode of the image
* @param[in] _mode Activation of distance field mode
*/
void setDistanceFieldMode(bool _mode);
/**
* @brief Get the render methode.
* @return The render mode of the image.
*/
bool getDistanceFieldMode() const {
return m_distanceFieldMode;
}
};
};
};

View File

@ -0,0 +1,693 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/uri/uri.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Shaper.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::Shaper);
// VBO table property:
const int32_t ewol::compositing::Shaper::m_vboIdCoord(0);
const int32_t ewol::compositing::Shaper::m_vboIdPos(1);
#define NB_VBO (2)
ewol::compositing::Shaper::Shaper(const etk::Uri& _uri) :
m_uri(_uri),
m_config(null),
m_confIdMode(-1),
m_confIdDisplayOutside(-1),
m_confIdChangeTime(-1),
m_confProgramFile(-1),
m_confColorFile(-1),
m_confImageFile(-1),
m_GLprogram(null),
m_GLPosition(-1),
m_GLMatrix(-1),
m_GLStateActivate(-1),
m_GLStateOld(-1),
m_GLStateNew(-1),
m_GLStateTransition(-1),
m_resourceTexture(null),
m_nextStatusRequested(-1),
m_propertyOrigin(0,0),
m_propertySize(0,0),
m_propertyInsidePosition(0,0),
m_propertyInsideSize(0,0),
m_stateActivate(0),
m_stateOld(0),
m_stateNew(0),
m_stateTransition(1.0),
m_nbVertexToDisplay(0) {
for (size_t iii=0; iii<shaperPosCount; ++iii) {
m_confIdPaddingOut[iii] = -1;
m_confIdBorder[iii] = -1;
m_confIdPaddingIn[iii] = -1;
}
// Create the VBO:
m_VBO = gale::resource::VirtualBufferObject::create(NB_VBO);
if (m_VBO == null) {
EWOL_ERROR("can not instanciate VBO ...");
return;
}
// TO facilitate some debugs we add a name of the VBO:
m_VBO->setName("[VBO] of ewol::compositing::Shaper");
loadProgram();
}
ewol::compositing::Shaper::~Shaper() {
unLoadProgram();
}
void ewol::compositing::Shaper::unLoadProgram() {
m_GLprogram.reset();
m_resourceTexture.reset();
m_config.reset();
m_colorProperty.reset();
for (size_t iii=0; iii<shaperPosCount; ++iii) {
m_confIdPaddingOut[iii] = -1;
m_confIdBorder[iii] = -1;
m_confIdPaddingIn[iii] = -1;
}
m_VBO->clear();
m_confIdMode = -1;
m_confIdDisplayOutside = -1;
m_nbVertexToDisplay = 0;
m_confIdChangeTime = -1;
m_confProgramFile = -1;
m_confImageFile = -1;
m_listAssiciatedId.clear();
}
void ewol::compositing::Shaper::loadProgram() {
if (m_uri.isEmpty() == true) {
EWOL_DEBUG("no Shaper set for loading resources ...");
return;
}
m_config = ewol::resource::ConfigFile::create(m_uri.get());
if (m_config != null) {
m_confIdMode = m_config->request("mode");
m_confIdDisplayOutside = m_config->request("display-outside");
m_confIdPaddingOut[shaperPosLeft] = m_config->request("padding-out-left");
m_confIdPaddingOut[shaperPosRight] = m_config->request("padding-out-right");
m_confIdPaddingOut[shaperPosTop] = m_config->request("padding-out-top");
m_confIdPaddingOut[shaperPosButtom] = m_config->request("padding-out-buttom");
m_confIdBorder[shaperPosLeft] = m_config->request("border-left");
m_confIdBorder[shaperPosRight] = m_config->request("border-right");
m_confIdBorder[shaperPosTop] = m_config->request("border-top");
m_confIdBorder[shaperPosButtom] = m_config->request("border-buttom");
m_confIdPaddingIn[shaperPosLeft] = m_config->request("padding-in-left");
m_confIdPaddingIn[shaperPosRight] = m_config->request("padding-in-right");
m_confIdPaddingIn[shaperPosTop] = m_config->request("padding-in-top");
m_confIdPaddingIn[shaperPosButtom] = m_config->request("padding-in-buttom");
m_confIdChangeTime = m_config->request("change-time");
m_confProgramFile = m_config->request("program");
m_confImageFile = m_config->request("image");
m_confColorFile = m_config->request("color");
}
etk::String basicShaderFile = m_config->getString(m_confProgramFile);
if (basicShaderFile != "") {
etk::String tmpFilename(basicShaderFile);
if (tmpFilename.find(':') == etk::String::npos) {
// get the relative position of the current file ...
etk::Uri tmpUri = m_uri;
tmpUri.setPath(m_uri.getPath().getParent() / basicShaderFile);
tmpFilename = tmpUri.get();
EWOL_DEBUG("Shaper try load shader : '" << tmpFilename << "' with base : '" << basicShaderFile << "'");
} else {
EWOL_DEBUG("Shaper try load shader : '" << tmpFilename << "'");
}
// get the shader resource :
m_GLPosition = 0;
m_GLprogram = gale::resource::Program::create(tmpFilename);
if (m_GLprogram != null) {
m_GLPosition = m_GLprogram->getAttribute("EW_coord2d");
m_GLMatrix = m_GLprogram->getUniform("EW_MatrixTransformation");
// Widget property == > for the Vertex shader
m_GLPropertyPos = m_GLprogram->getAttribute("EW_widgetPropertyPos");
// status property == > for the fragment shader
m_GLStateActivate = m_GLprogram->getUniform("EW_status.activate");
m_GLStateOld = m_GLprogram->getUniform("EW_status.stateOld");
m_GLStateNew = m_GLprogram->getUniform("EW_status.stateNew");
m_GLStateTransition = m_GLprogram->getUniform("EW_status.transition");
// for the texture ID :
m_GLtexID = m_GLprogram->getUniform("EW_texID");
}
etk::String basicImageFile = m_config->getString(m_confImageFile);
if (basicImageFile != "") {
etk::String tmpFilename(basicImageFile);
if (tmpFilename.find(':') == etk::String::npos) {
// get the relative position of the current file ...
etk::Uri tmpUri = m_uri;
tmpUri.setPath(m_uri.getPath().getParent() / basicImageFile);
tmpFilename = tmpUri.get();
EWOL_DEBUG("Shaper try load shaper image : '" << tmpFilename << "' with base : '" << basicImageFile << "'");
} else {
EWOL_DEBUG("Shaper try load shaper image : '" << tmpFilename << "'");
}
ivec2 size(64,64);
m_resourceTexture = ewol::resource::TextureFile::create(tmpFilename, size);
}
}
etk::String basicColorFile = m_config->getString(m_confColorFile);
if (basicColorFile != "") {
etk::String tmpFilename(basicColorFile);
if (tmpFilename.find(':') == etk::String::npos) {
// get the relative position of the current file ...
etk::Uri tmpUri = m_uri;
tmpUri.setPath(m_uri.getPath().getParent() / basicColorFile);
tmpFilename = tmpUri.get();
EWOL_DEBUG("Shaper try load colorFile : '" << tmpFilename << "' with base : '" << basicColorFile << "'");
} else {
EWOL_DEBUG("Shaper try load colorFile : '" << tmpFilename << "'");
}
m_colorProperty = ewol::resource::ColorFile::create(tmpFilename);
if ( m_GLprogram != null
&& m_colorProperty != null) {
etk::Vector<etk::String> listColor = m_colorProperty->getColors();
for (auto tmpColor : listColor) {
int32_t glId = m_GLprogram->getUniform(tmpColor);
int32_t colorID = m_colorProperty->request(tmpColor);
m_listAssiciatedId.pushBack(ivec2(glId, colorID));
}
}
}
}
void ewol::compositing::Shaper::draw(bool _disableDepthTest) {
if (m_config == null) {
// this is a normale case ... the user can choice to have no config basic file ...
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
if (m_VBO->bufferSize(m_vboIdCoord) <= 0) {
return;
}
//glScalef(m_scaling.x, m_scaling.y, 1.0);
m_GLprogram->use();
// set Matrix : translation/positionMatrix
mat4 tmpMatrix = gale::openGL::getMatrix();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// position:
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
// property
m_GLprogram->sendAttributePointer(m_GLPropertyPos, m_VBO, m_vboIdPos);
// all entry parameters :
m_GLprogram->uniform1i(m_GLStateActivate, m_stateActivate);
m_GLprogram->uniform1i(m_GLStateOld, m_stateOld);
m_GLprogram->uniform1i(m_GLStateNew, m_stateNew);
m_GLprogram->uniform1f(m_GLStateTransition, m_stateTransition);
for (auto element : m_listAssiciatedId) {
m_GLprogram->uniform(element.x(), m_colorProperty->get(element.y()));
}
if (m_resourceTexture != null) {
// TextureID
m_GLprogram->setTexture0(m_GLtexID, m_resourceTexture->getRendererId());
}
// Request the draw of the elements :
//gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, SHAPER_NB_MAX_VERTEX);
gale::openGL::drawArrays(gale::openGL::renderMode::triangleStrip, 0, m_nbVertexToDisplay);
m_GLprogram->unUse();
}
void ewol::compositing::Shaper::clear() {
// nothing to do ...
m_propertySize = vec2(0,0);
m_propertyOrigin = vec2(0,0);
m_propertyInsidePosition = vec2(0,0);
m_propertyInsideSize = vec2(0,0);
m_VBO->clear();
}
bool ewol::compositing::Shaper::setState(int32_t _newState) {
if (m_stateActivate == _newState) {
return false;
}
m_stateActivate = _newState;
return true;
}
bool ewol::compositing::Shaper::changeStatusIn(int32_t _newStatusId) {
if (_newStatusId != m_stateNew) {
m_nextStatusRequested = _newStatusId;
return true;
}
if( m_nextStatusRequested != -1
|| m_stateNew != m_stateOld) {
return true;
}
return false;
}
bool ewol::compositing::Shaper::periodicCall(const ewol::event::Time& _event) {
EWOL_VERBOSE("call=" << _event << "state transition=" << m_stateTransition << " speedTime=" << m_config->getNumber(m_confIdChangeTime));
// start :
if (m_stateTransition >= 1.0) {
m_stateOld = m_stateNew;
if( m_nextStatusRequested != -1
&& m_nextStatusRequested != m_stateOld) {
m_stateNew = m_nextStatusRequested;
m_nextStatusRequested = -1;
m_stateTransition = 0.0;
EWOL_VERBOSE(" ##### START ##### ");
} else {
m_nextStatusRequested = -1;
// disable periodic call ...
return false;
}
}
if (m_stateTransition<1.0) {
// check if no new state requested:
if (m_nextStatusRequested != -1 && m_stateTransition<0.5) {
// invert sources with destination
int32_t tmppp = m_stateOld;
m_stateOld = m_stateNew;
m_stateNew = tmppp;
m_stateTransition = 1.0 - m_stateTransition;
if (m_nextStatusRequested == m_stateNew) {
m_nextStatusRequested = -1;
}
}
float timeRelativity = 0.0f;
if (m_config != null) {
timeRelativity = m_config->getNumber(m_confIdChangeTime) / 1000.0;
}
m_stateTransition += _event.getDeltaCall() / timeRelativity;
//m_stateTransition += _event.getDeltaCall();
m_stateTransition = etk::avg(0.0f, m_stateTransition, 1.0f);
EWOL_VERBOSE("relative=" << timeRelativity << " Transition : " << m_stateTransition);
}
return true;
}
//Create Line:
void ewol::compositing::Shaper::addVertexLine(float _yTop,
float _yButtom,
float _x1,
float _x2,
float _x3,
float _x4,
float _x5,
float _x6,
float _x7,
float _x8,
float _yValTop,
float _yValButtom,
const float* _table,
bool _displayOutside) {
if (m_nbVertexToDisplay != 0) {
// change line ...
m_VBO->pushOnBuffer(m_vboIdCoord,
m_VBO->getOnBufferVec2(m_vboIdCoord, m_nbVertexToDisplay-1));
m_VBO->pushOnBuffer(m_vboIdPos,
m_VBO->getOnBufferVec2(m_vboIdPos, m_nbVertexToDisplay-1));
m_nbVertexToDisplay++;
if (_displayOutside == true) {
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x1, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[0],_yValButtom));
m_nbVertexToDisplay++;
} else {
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x2, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[1],_yValButtom));
m_nbVertexToDisplay++;
}
}
if (_displayOutside == true) {
// A
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x1, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[0],_yValButtom));
m_nbVertexToDisplay++;
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x1, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[0],_yValTop));
m_nbVertexToDisplay++;
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x2, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[1],_yValButtom));
m_nbVertexToDisplay++;
// B
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x2, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[1],_yValTop));
m_nbVertexToDisplay++;
// C
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x3, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[2],_yValButtom));
m_nbVertexToDisplay++;
} else {
// C
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x2, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[1],_yValButtom));
m_nbVertexToDisplay++;
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x2, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[1],_yValTop));
m_nbVertexToDisplay++;
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x3, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[2],_yValButtom));
m_nbVertexToDisplay++;
}
// D
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x3, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[2],_yValTop));
m_nbVertexToDisplay++;
// E
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x4, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[3],_yValButtom));
m_nbVertexToDisplay++;
// F
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x4, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[3],_yValTop));
m_nbVertexToDisplay++;
// G
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x5, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[4],_yValButtom));
m_nbVertexToDisplay++;
// H
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x5, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[4],_yValTop));
m_nbVertexToDisplay++;
// I
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x6, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[5],_yValButtom));
m_nbVertexToDisplay++;
// J
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x6, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[5],_yValTop));
m_nbVertexToDisplay++;
// K
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x7, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[6],_yValButtom));
m_nbVertexToDisplay++;
// L
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x7, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[6],_yValTop));
m_nbVertexToDisplay++;
if (_displayOutside == true) {
// M
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x8, _yButtom));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[7],_yValButtom));
m_nbVertexToDisplay++;
// N
m_VBO->pushOnBuffer(m_vboIdCoord, vec2(_x8, _yTop));
m_VBO->pushOnBuffer(m_vboIdPos, vec2(_table[7],_yValTop));
m_nbVertexToDisplay++;
}
}
const float modeDisplay[][8] = {
/* !! 0 !!
* / *******
* / ****** /
* ****** /
*/
{ 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f },
/* !! 1 !!
* ****** \
* \ ****** \
* \ *******
*/
{ 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f },
/* !! 2 !!
* / ****** \
* ****** / \ *******
*/
{ 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
/* !! 3 !!
* ****** \ / *******
* \ ****** /
*/
{ 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f },
/* !! 4 !!
* / *******
* / ****** /
* ****** /
*/
{ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f },
/* !! 5 !!
* ****** \
* \ ****** \
* \ *******
*/
{ 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, -1.0f },
/* !! 6 !!
* / ****** \
* ****** / \ *******
*/
{ -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f },
/* !! 7 !!
* ****** \ / *******
* \ ****** /
*/
{ 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f }
};
void ewol::compositing::Shaper::setShape(const vec2& _origin, const vec2& _size, const vec2& _insidePos, const vec2& _insideSize) {
m_VBO->clear();
ewol::Padding borderTmp = getBorder();
ewol::Padding paddingIn = getPaddingIn();
ewol::Padding paddingOut = getPaddingOut();
ewol::Padding padding = paddingIn + borderTmp + paddingOut;
ewol::Padding enveloppe(_origin.x(),
_origin.y() + _size.y(),
_origin.x() + _size.x(),
_origin.y());
#if 0
ewol::Padding inside(_insidePos.x(),
_insidePos.y() + _insideSize.y(),
_insidePos.x() + _insideSize.x(),
_insidePos.y());
ewol::Padding insideBorder(inside.xLeft() - paddingIn.xLeft(),
inside.yTop() + paddingIn.yTop(),
inside.xRight() + paddingIn.xRight(),
inside.yButtom() - paddingIn.yButtom());
ewol::Padding border(insideBorder.xLeft() - borderTmp.xLeft(),
insideBorder.yTop() + borderTmp.yTop(),
insideBorder.xRight() + borderTmp.xRight(),
insideBorder.yButtom() - borderTmp.yButtom());
#else
ewol::Padding border(_insidePos.x() - padding.xLeft() + paddingOut.xLeft(),
_insidePos.y() + _insideSize.y() + padding.yTop() - paddingOut.yTop(),
_insidePos.x() + _insideSize.x() + padding.xRight() - paddingOut.xRight(),
_insidePos.y() - padding.yButtom() + paddingOut.yButtom());
ewol::Padding insideBorder(border.xLeft() + borderTmp.xLeft(),
border.yTop() - borderTmp.yTop(),
border.xRight() - borderTmp.xRight(),
border.yButtom() + borderTmp.yButtom());
ewol::Padding inside(insideBorder.xLeft() + etk::max(0.0f, paddingIn.xLeft()),
insideBorder.yTop() - etk::max(0.0f, paddingIn.yTop()),
insideBorder.xRight() - etk::max(0.0f, paddingIn.xRight()),
insideBorder.yButtom() + etk::max(0.0f, paddingIn.yButtom()));
#endif
/*
EWOL_ERROR(" enveloppe = " << enveloppe);
EWOL_ERROR(" border = " << border);
EWOL_ERROR(" inside = " << inside);
*/
int32_t mode = 0;
bool displayOutside = false;
if (m_config != null) {
mode = m_config->getNumber(m_confIdMode);
displayOutside = m_config->getBoolean(m_confIdDisplayOutside);
}
m_nbVertexToDisplay = 0;
if (displayOutside == true) {
addVertexLine(enveloppe.yTop(), border.yTop(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][7], modeDisplay[mode][6],
modeDisplay[mode],
displayOutside);
}
addVertexLine(border.yTop(), insideBorder.yTop(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][6], modeDisplay[mode][5],
modeDisplay[mode],
displayOutside);
addVertexLine(insideBorder.yTop(), inside.yTop(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][5], modeDisplay[mode][4],
modeDisplay[mode],
displayOutside);
addVertexLine(inside.yTop(), inside.yButtom(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][4], modeDisplay[mode][3],
modeDisplay[mode],
displayOutside);
addVertexLine(inside.yButtom(), insideBorder.yButtom(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][3], modeDisplay[mode][2],
modeDisplay[mode],
displayOutside);
addVertexLine(insideBorder.yButtom(), border.yButtom(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][2], modeDisplay[mode][1],
modeDisplay[mode],
displayOutside);
if (displayOutside == true) {
addVertexLine(border.yButtom(), enveloppe.yButtom(),
enveloppe.xLeft(),
border.xLeft(),
insideBorder.xLeft(),
inside.xLeft(),
inside.xRight(),
insideBorder.xRight(),
border.xRight(),
enveloppe.xRight(),
modeDisplay[mode][1], modeDisplay[mode][0],
modeDisplay[mode],
displayOutside);
}
m_VBO->flush();
}
ewol::Padding ewol::compositing::Shaper::getPadding() {
return getPaddingOut() + getBorder() + getPaddingIn();
}
ewol::Padding ewol::compositing::Shaper::getPaddingIn() {
ewol::Padding padding(0,0,0,0);
if (m_config != null) {
padding.setValue(m_config->getNumber(m_confIdPaddingIn[shaperPosLeft]),
m_config->getNumber(m_confIdPaddingIn[shaperPosTop]),
m_config->getNumber(m_confIdPaddingIn[shaperPosRight]),
m_config->getNumber(m_confIdPaddingIn[shaperPosButtom]));
}
return padding;
}
ewol::Padding ewol::compositing::Shaper::getPaddingOut() {
ewol::Padding padding(0,0,0,0);
if (m_config != null) {
padding.setValue(m_config->getNumber(m_confIdPaddingOut[shaperPosLeft]),
m_config->getNumber(m_confIdPaddingOut[shaperPosTop]),
m_config->getNumber(m_confIdPaddingOut[shaperPosRight]),
m_config->getNumber(m_confIdPaddingOut[shaperPosButtom]));
}
return padding;
}
ewol::Padding ewol::compositing::Shaper::getBorder() {
ewol::Padding padding(0,0,0,0);
if (m_config != null) {
padding.setValue(m_config->getNumber(m_confIdBorder[shaperPosLeft]),
m_config->getNumber(m_confIdBorder[shaperPosTop]),
m_config->getNumber(m_confIdBorder[shaperPosRight]),
m_config->getNumber(m_confIdBorder[shaperPosButtom]));
}
return padding;
}
void ewol::compositing::Shaper::setSource(const etk::Uri& _uri) {
clear();
unLoadProgram();
m_uri = _uri;
loadProgram();
}
bool ewol::compositing::Shaper::hasSources() {
return m_GLprogram != null;
}
const etk::Color<float>& ewol::compositing::Shaper::getColor(int32_t _id) {
static const etk::Color<float> errorValue(0,0,0,0);
if (m_colorProperty == null) {
EWOL_WARNING("null of m_colorProperty ==> return #0000 for id " << _id);
return errorValue;
}
return m_colorProperty->get(_id);
}
int32_t ewol::compositing::Shaper::requestColor(const etk::String& _name) {
if (m_colorProperty == null) {
EWOL_WARNING("null of m_colorProperty ==> return -1 for name " << _name);
return -1;
}
return m_colorProperty->request(_name);
}
int32_t ewol::compositing::Shaper::requestConfig(const etk::String& _name) {
if (m_config == null) {
EWOL_WARNING("null of m_config ==> return -1 for name " << _name);
return -1;
}
return m_config->request(_name);
}
double ewol::compositing::Shaper::getConfigNumber(int32_t _id) {
if ( _id == -1
|| m_config == null) {
EWOL_WARNING("null of m_config ==> return 0.0 for id " << _id);
return 0.0;
}
return m_config->getNumber(_id);
}
namespace etk {
template<> etk::String toString<ewol::compositing::Shaper>(const ewol::compositing::Shaper& _obj) {
return _obj.getSource().get();
}
template<> etk::UString toUString<ewol::compositing::Shaper>(const ewol::compositing::Shaper& _obj) {
return etk::toUString(etk::toString(_obj));
}
template<> bool from_string<ewol::compositing::Shaper>(ewol::compositing::Shaper& _variableRet, const etk::String& _value) {
_variableRet.setSource(_value);
return true;
}
template<> bool from_string<ewol::compositing::Shaper>(ewol::compositing::Shaper& _variableRet, const etk::UString& _value) {
return from_string(_variableRet, etk::toString(_value));
}
};

View File

@ -0,0 +1,296 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <gale/resource/Program.hpp>
#include <ewol/resource/ConfigFile.hpp>
#include <ewol/resource/ColorFile.hpp>
#include <ewol/resource/TextureFile.hpp>
#include <ewol/event/Time.hpp>
#include <ewol/Padding.hpp>
namespace ewol {
namespace compositing {
enum renderMode {
renderSingleSquare, //!< basic historic render mode
renderBorder, //!< Render 4 squares for coiner, and renctangle for border, a big rentangle for background and 8 rectangle for the outside part
renderOneBorder,
};
#define SHAPER_NB_MAX_QUAD (5*5)
#define SHAPER_NB_MAX_TRIANGLE (SHAPER_NB_MAX_QUAD*2)
#define SHAPER_NB_MAX_VERTEX (SHAPER_NB_MAX_TRIANGLE*3)
enum shaperPos {
shaperPosLeft,
shaperPosRight,
shaperPosTop,
shaperPosButtom,
shaperPosCount,
};
/**
* @brief the Shaper system is a basic theme configuration for every widget, it corespond at a background display described by a pool of files
*/
// TODO : load image
// TODO : Abstaraction between states (call by name and the system greate IDs
class Shaper : public ewol::Compositing {
private:
etk::Uri m_uri; //!< Name of the configuration of the shaper.
// External theme config:
ememory::SharedPtr<ewol::resource::ConfigFile> m_config; //!< pointer on the config file resources
int32_t m_confIdPaddingOut[shaperPosCount]; //!< Padding out property : X-left X-right Y-top Y-buttom
int32_t m_confIdBorder[shaperPosCount]; //!< border property : X-left X-right Y-top Y-buttom
int32_t m_confIdPaddingIn[shaperPosCount]; //!< Padding in property : X-left X-right Y-top Y-buttom
int32_t m_confIdMode; //!< Display mode
int32_t m_confIdDisplayOutside; //!< Display outside of the shape...
int32_t m_confIdChangeTime; //!< ConfigFile padding transition time property
int32_t m_confProgramFile; //!< ConfigFile opengGl program Name
int32_t m_confColorFile; //!< ConfigFile opengGl color file Name
int32_t m_confImageFile; //!< ConfigFile opengGl program Name
// openGL shaders programs:
ememory::SharedPtr<gale::resource::Program> m_GLprogram; //!< pointer on the opengl display program
int32_t m_GLPosition; //!< openGL id on the element (vertex buffer)
int32_t m_GLMatrix; //!< openGL id on the element (transformation matrix)
int32_t m_GLPropertyPos; //!< openGL id on the element (simple ratio position in the widget : ____/-----\_____ on vec2(X,Y))
int32_t m_GLStateActivate; //!< openGL id on the element (activate state displayed)
int32_t m_GLStateOld; //!< openGL id on the element (old state displayed)
int32_t m_GLStateNew; //!< openGL id on the element (new state displayed)
int32_t m_GLStateTransition; //!< openGL id on the element (transition ofset [0.0..1.0] )
int32_t m_GLtexID; //!< openGL id on the element (texture image)
// For the Image :
ememory::SharedPtr<ewol::resource::TextureFile> m_resourceTexture; //!< texture resources (for the image)
// internal needed data :
int32_t m_nextStatusRequested; //!< when status is changing, this represent the next step of it
vec2 m_propertyOrigin; //!< widget origin
vec2 m_propertySize; //!< widget size
vec2 m_propertyInsidePosition; //!< internal subwidget position
vec2 m_propertyInsideSize; //!< internal subwidget size
int32_t m_stateActivate; //!< Activate state of the element
int32_t m_stateOld; //!< previous state
int32_t m_stateNew; //!< destination state
float m_stateTransition; //!< working state between 2 states
int32_t m_nbVertexToDisplay;
// color management theme:
ememory::SharedPtr<ewol::resource::ColorFile> m_colorProperty; //!< input resource for color management
etk::Vector<ivec2> m_listAssiciatedId; //!< Corellation ID between ColorProperty (Y) and OpenGL Program (X)
protected:
static const int32_t m_vboIdCoord;
static const int32_t m_vboIdPos;
ememory::SharedPtr<gale::resource::VirtualBufferObject> m_VBO;
private:
/**
* @brief load the openGL program and get all the ID needed
*/
void loadProgram();
/**
* @brief Un-Load the openGL program and get all the ID needed
*/
void unLoadProgram();
public:
/**
* @brief generic constructor
* @param[in] _uri URI of the file that might be loaded
*/
Shaper(const etk::Uri& _uri="");
/**
* @brief generic destructor
*/
virtual ~Shaper();
public:
/**
* @brief draw All the refistered text in the current element on openGL
*/
void draw(bool _disableDepthTest=true);
/**
* @brief clear alll tre registered element in the current element
*/
void clear();
/**
* @brief Change the current state
* @param[in] _newState Current state of the configuration
* @return true Need redraw.
* @return false No need redraw.
*/
bool setState(int32_t _newState);
/**
* @brief change the current status in an other
* @param[in] _newStatusId the next new status requested
* @return true The widget must call this fuction periodicly (and redraw itself)
* @return false No need to request the periodic call.
*/
bool changeStatusIn(int32_t _newStatusId);
/**
* @brief get the current displayed status of the shaper
* @return The Status Id
*/
int32_t getCurrentDisplayedStatus() {
return m_stateNew;
};
/**
* @brief get the next displayed status of the shaper
* @return The next status Id (-1 if no status in next)
*/
int32_t getNextDisplayedStatus() {
return m_nextStatusRequested;
};
/**
* @brief get the current trasion status
* @return value of the transition status (0.0f when no activity)
*/
float getTransitionStatus() {
return m_stateTransition;
};
/**
* @brief Same as the widfget periodic call (this is for change display)
* @param[in] _event The current time of the call.
* @return true The widget must call this fuction periodicly (and redraw itself)
* @return false No need to request the periodic call.
*/
bool periodicCall(const ewol::event::Time& _event);
/**
* @brief get the padding declared by the user in the config file
* @return the padding property
*/
ewol::Padding getPadding();
ewol::Padding getPaddingIn();
ewol::Padding getPaddingOut();
/**
* @brief get the padding declared by the user in the config file
* @return the padding property
*/
ewol::Padding getBorder();
/**
* @brief change the shaper Source
* @param[in] _uri New file of the shaper
*/
void setSource(const etk::Uri& _uri);
/**
* @brief get the shaper file Source
* @return the shapper file name
*/
const etk::Uri& getSource() const {
return m_uri;
};
/**
* @brief Sometimes the user declare an image but not allocate the ressources all the time, this is to know it ..
* @return the validity od the resources.
*/
bool hasSources();
public:
/**
* @brief set the shape property:
*
* ********************************************************************************
* * _size *
* * *
* * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * *
* * | | *
* * *************************************************** *
* * | * * | *
* * * * *
* * | * * - - - - - - - - - - - - - - - - - - * * | *
* * * _insideSize * *
* * | * | | * | *
* * * * *
* * | * | | * | *
* * * * *
* * | * | | * | *
* * * * *
* * | * | | * | *
* * * * *
* * | * | | * | *
* * * * *
* * | * | | * | *
* * * _insidePos * *
* * | * * - - - - - - - - - - - - - - - - - - * * | *
* * * * *
* * | *************************************************** | *
* * *
* * | | *
* * *
* * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * *
* * *
* ********************************************************************************
* _origin
*
*
* @param[in] _origin Origin of the display
* @param[in] _size Size of the display
* @param[in] _insidePos Positin of the internal data
* @param[in] _insideSize Size of the internal data
*/
void setShape(const vec2& _origin, const vec2& _size, const vec2& _insidePos, const vec2& _insideSize);
// @previous
void setShape(const vec2& _origin, const vec2& _size) {
ewol::Padding tmp = getPadding();
setShape(_origin, _size, _origin+vec2(tmp.xLeft(), tmp.yButtom()), _size - vec2(tmp.x(), tmp.y()));
}
public:
/**
* @brief Get an ID on the color instance element
* @param[in] _name Name of the element requested
* @return The Id of the color
*/
int32_t requestColor(const etk::String& _name);
/**
* @brief Get The color associated at an ID.
* @param[in] _id Id of the color
* @return the reference on the color
*/
const etk::Color<float>& getColor(int32_t _id);
public:
/**
* @brief Get an ID on the configuration instance element
* @param[in] _name Name of the element requested
* @return The Id of the element
*/
int32_t requestConfig(const etk::String& _name);
/**
* @brief Get The number associated at an ID.
* @param[in] _id Id of the parameter
* @return the requested number.
*/
double getConfigNumber(int32_t _id);
public:
/**
* @brief Set activate state of the element
* @param[in] _status New activate status
*/
void setActivateState(int32_t _status) {
m_stateActivate = _status;
}
private:
void addVertexLine(float _yTop,
float _yButtom,
float _x1,
float _x2,
float _x3,
float _x4,
float _x5,
float _x6,
float _x7,
float _x8,
float _yValTop,
float _yValButtom,
const float* _table,
bool _displayOutside);
public:
/* ****************************************************
* == operator
*****************************************************/
bool operator== (const Shaper& _obj) const {
return _obj.m_uri == m_uri;
}
bool operator!= (const Shaper& _obj) const {
return _obj.m_uri != m_uri;
}
};
}
}

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/compositing/Sprite.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::Sprite);
ewol::compositing::Sprite::Sprite(const etk::String& _imageName, const ivec2& _nbSprite, int32_t _size) :
ewol::compositing::Image(_imageName, false, _size),
m_nbSprite(_nbSprite),
m_unitarySpriteSize(0,0) {
/*
vec2 imageSize = getRealSize();
m_unitarySpriteSize.setValue(imageSize.x()/(float)m_nbSprite.x(),
imageSize.y()/(float)m_nbSprite.y());
*/
m_unitarySpriteSize.setValue(1.0/(float)m_nbSprite.x(),
1.0/(float)m_nbSprite.y());
}
void ewol::compositing::Sprite::printSprite(const ivec2& _spriteID, const vec3& _size) {
if( _spriteID.x()<0
|| _spriteID.y()<0
|| _spriteID.x() >= m_nbSprite.x()
|| _spriteID.y() >= m_nbSprite.y()) {
return;
}
printPart(vec2(_size.x(),_size.y()),
vec2((float)(_spriteID.x() )*m_unitarySpriteSize.x(), (float)(_spriteID.y() )*m_unitarySpriteSize.y()),
vec2((float)(_spriteID.x()+1)*m_unitarySpriteSize.x(), (float)(_spriteID.y()+1)*m_unitarySpriteSize.y()));
}

View File

@ -0,0 +1,29 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/debug.hpp>
#include <ewol/compositing/Image.hpp>
namespace ewol {
namespace compositing {
class Sprite : public ewol::compositing::Image {
protected:
ivec2 m_nbSprite; //!< number of sprite in vertical and horizontal
vec2 m_unitarySpriteSize; //!< size of a unique sprite
public:
Sprite(const etk::String& _imageName,
const ivec2& _nbSprite,
int32_t _size=ewol::compositing::Image::sizeAuto);
virtual ~Sprite() {};
void printSprite(const ivec2& _spriteID, const vec2& _size) {
printSprite(_spriteID, vec3(_size.x(), _size.y(),0));
};
void printSprite(const ivec2& _spriteID, const vec3& _size);
};
}
}

View File

@ -0,0 +1,372 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/compositing/Text.hpp>
#include <ewol/context/Context.hpp>
#include <etk/types.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::Text);
ewol::compositing::Text::Text(const etk::String& _fontName, int32_t _fontSize) :
m_font(null) {
setFont(_fontName, _fontSize);
}
ewol::compositing::Text::~Text() {
}
void ewol::compositing::Text::drawMT(const mat4& _transformationMatrix, bool _enableDepthTest) {
// draw BG in any case:
m_vectorialDraw.draw();
if ( m_VBO->bufferSize(m_vboIdCoord) <= 0
|| m_font == null) {
// TODO : set it back ...
//EWOL_WARNING("Nothink to draw...");
return;
}
if (m_font == null) {
EWOL_WARNING("no font...");
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
if (_enableDepthTest == true) {
gale::openGL::enable(gale::openGL::flag_depthTest);
}
// set Matrix : translation/positionMatrix
mat4 projMatrix = gale::openGL::getMatrix();
mat4 camMatrix = gale::openGL::getCameraMatrix();
mat4 tmpMatrix = projMatrix * camMatrix * _transformationMatrix;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// Texture:
m_GLprogram->setTexture0(m_GLtexID, m_font->getRendererId());
m_GLprogram->uniform1i(m_GLtextWidth, m_font->getOpenGlSize().x());
m_GLprogram->uniform1i(m_GLtextHeight, m_font->getOpenGlSize().x());
// position:
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
// Texture:
m_GLprogram->sendAttributePointer(m_GLtexture, m_VBO, m_vboIdCoordText);
// color:
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdColor);
// Request the draw od the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
if (_enableDepthTest == true) {
gale::openGL::disable(gale::openGL::flag_depthTest);
}
}
void ewol::compositing::Text::drawD(bool _disableDepthTest) {
// draw BG in any case:
m_vectorialDraw.draw(_disableDepthTest);
if ( m_VBO->bufferSize(m_vboIdCoord) <= 0
|| m_font == null) {
//EWOL_WARNING("Nothink to draw...");
return;
}
if (m_font == null) {
EWOL_WARNING("no font...");
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
// set Matrix : translation/positionMatrix
mat4 tmpMatrix = gale::openGL::getMatrix()*m_matrixApply;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// Texture :
m_GLprogram->setTexture0(m_GLtexID, m_font->getRendererId());
m_GLprogram->uniform1i(m_GLtextWidth, m_font->getOpenGlSize().x());
m_GLprogram->uniform1i(m_GLtextHeight, m_font->getOpenGlSize().x());
// position:
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
// Texture:
m_GLprogram->sendAttributePointer(m_GLtexture, m_VBO, m_vboIdCoordText);
// color:
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdColor);
// Request the draw od the elements :
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
}
float ewol::compositing::Text::getSize() {
if (m_font == null) {
EWOL_WARNING("no font...");
return 1.0f;
}
return m_font->getFontSize();
}
float ewol::compositing::Text::getHeight() {
if (m_font == null) {
EWOL_WARNING("no font...");
return 10.0f;
}
return m_font->getHeight(m_mode);
}
ewol::GlyphProperty * ewol::compositing::Text::getGlyphPointer(char32_t _charcode) {
if (m_font == null) {
EWOL_WARNING("no font...");
return null;
}
return m_font->getGlyphPointer(_charcode, m_mode);
}
void ewol::compositing::Text::setFontSize(int32_t _fontSize) {
// get old size
etk::String fontName = "";
if (m_font != null) {
fontName = m_font->getName();
// Remove the :XX for the size ...
size_t pos = fontName.rfind(':');
fontName.erase(pos, fontName.size()-pos);
}
setFont(fontName, _fontSize);
}
void ewol::compositing::Text::setFontName(const etk::String& _fontName) {
// get old size
int32_t fontSize = -1;
if (m_font != null) {
fontSize = m_font->getFontSize();
}
setFont(_fontName, fontSize);
}
void ewol::compositing::Text::setFont(etk::String _fontName, int32_t _fontSize) {
clear();
// remove old one
ememory::SharedPtr<ewol::resource::TexturedFont> previousFont = m_font;
if (_fontSize <= 0) {
_fontSize = ewol::getContext().getFontDefault().getSize();
}
if (_fontName == "") {
_fontName = ewol::getContext().getFontDefault().getName();
}
_fontName += ":";
_fontName += etk::toString(_fontSize);
EWOL_VERBOSE("plop : " << _fontName << " size=" << _fontSize << " result :" << _fontName);
// link to new one
m_font = ewol::resource::TexturedFont::create(_fontName);
if (m_font == null) {
EWOL_ERROR("Can not get font resource");
m_font = previousFont;
}
}
void ewol::compositing::Text::setFontMode(enum ewol::font::mode _mode) {
if (m_font != null) {
m_mode = m_font->getWrappingMode(_mode);
}
}
void ewol::compositing::Text::printChar(const char32_t& _charcode) {
// get a pointer on the glyph property :
ewol::GlyphProperty* myGlyph = getGlyphPointer(_charcode);
if (null == myGlyph) {
EWOL_ERROR(" font does not really existed ...");
return;
}
int32_t fontSize = getSize();
int32_t fontHeigh = getHeight();
// get the kerning ofset :
float kerningOffset = 0;
if (m_kerning == true) {
kerningOffset = myGlyph->kerningGet(m_previousCharcode);
if (kerningOffset != 0) {
//EWOL_DEBUG("Kerning between : '" << m_previousCharcode << "'&'" << myGlyph->m_UVal << "' value : " << kerningOffset);
}
}
// 0x01 == 0x20 == ' ';
if (_charcode != 0x01) {
/* Bitmap position
* xA xB
* yC *------*
* | |
* | |
* yD *------*
*/
float dxA = m_position.x() + myGlyph->m_bearing.x() + kerningOffset;
float dxB = dxA + myGlyph->m_sizeTexture.x();
float dyC = m_position.y() + myGlyph->m_bearing.y() + fontHeigh - fontSize;
float dyD = dyC - myGlyph->m_sizeTexture.y();
float tuA = myGlyph->m_texturePosStart.x();
float tuB = tuA + myGlyph->m_texturePosSize.x();
float tvC = myGlyph->m_texturePosStart.y();
float tvD = tvC + myGlyph->m_texturePosSize.y();
// Clipping and drawing area
if( m_clippingEnable == true
&& ( dxB < m_clippingPosStart.x()
|| dxA > m_clippingPosStop.x()
|| dyC < m_clippingPosStart.y()
|| dyD > m_clippingPosStop.y() ) ) {
// Nothing to diplay ...
} else {
if (m_clippingEnable == true) {
// generata positions...
float TexSizeX = tuB - tuA;
if (dxA < m_clippingPosStart.x()) {
// clip display
float drawSize = m_clippingPosStart.x() - dxA;
// update element start display
dxA = m_clippingPosStart.x();
float addElement = TexSizeX * drawSize / (float)myGlyph->m_sizeTexture.x();
// update texture start X Pos
tuA += addElement;
}
if (dxB > m_clippingPosStop.x()) {
// clip display
float drawSize = dxB - m_clippingPosStop.x();
// update element start display
dxB = m_clippingPosStop.x();
float addElement = TexSizeX * drawSize / (float)myGlyph->m_sizeTexture.x();
// update texture start X Pos
tuB -= addElement;
}
float TexSizeY = tvC - tvD;
if (dyC > m_clippingPosStop.y()) {
// clip display
float drawSize = dyC - m_clippingPosStop.y();
// update element start display
dyC = m_clippingPosStop.y();
float addElement = TexSizeY * drawSize / (float)myGlyph->m_sizeTexture.y();
// update texture start X Pos
tvC -= addElement;
}
if (dyD < m_clippingPosStart.y()) {
// clip display
float drawSize = m_clippingPosStart.y() - dyD;
// update element start display
dyD = m_clippingPosStart.y();
float addElement = TexSizeY * drawSize / (float)myGlyph->m_sizeTexture.y();
// update texture start X Pos
tvD += addElement;
}
}
if( dxB <= dxA
|| dyD >= dyC) {
// nothing to do ...
} else {
/* Bitmap position
* 0------1
* | |
* | |
* 3------2
*/
if (m_needDisplay == true) {
vec3 bitmapDrawPos[4];
bitmapDrawPos[0].setValue((int32_t)dxA, (int32_t)dyC, 0);
bitmapDrawPos[1].setValue((int32_t)dxB, (int32_t)dyC, 0);
bitmapDrawPos[2].setValue((int32_t)dxB, (int32_t)dyD, 0);
bitmapDrawPos[3].setValue((int32_t)dxA, (int32_t)dyD, 0);
/* texture Position :
* 0------1
* | |
* | |
* 3------2
*/
vec2 texturePos[4];
texturePos[0].setValue(tuA+m_mode, tvC);
texturePos[1].setValue(tuB+m_mode, tvC);
texturePos[2].setValue(tuB+m_mode, tvD);
texturePos[3].setValue(tuA+m_mode, tvD);
// NOTE : Android does not support the Quads elements ...
/* Step 1 :
* ********
* ******
* ****
* **
*
*/
// set texture coordonates :
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[0]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[1]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[2]);
// set display positions :
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[0]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[1]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[2]);
// set the color
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
/* Step 2 :
*
* **
* ****
* ******
* ********
*/
// set texture coordonates :
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[0]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[2]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[3]);
// set display positions :
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[0]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[2]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[3]);
// set the color
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
}
}
}
}
// move the position :
//EWOL_DEBUG(" 5 pos=" << m_position << " advance=" << myGlyph->m_advance.x() << " kerningOffset=" << kerningOffset);
m_position.setX(m_position.x() + myGlyph->m_advance.x() + kerningOffset);
//EWOL_DEBUG(" 6 print '" << charcode << "' : start=" << m_sizeDisplayStart << " stop=" << m_sizeDisplayStop << " pos=" << m_position);
// Register the previous character
m_previousCharcode = _charcode;
m_VBO->flush();
return;
}
vec3 ewol::compositing::Text::calculateSizeChar(const char32_t& _charcode) {
// get a pointer on the glyph property :
ewol::GlyphProperty * myGlyph = getGlyphPointer(_charcode);
int32_t fontHeigh = getHeight();
if (myGlyph == null) {
if (m_font == null) {
EWOL_WARNING("no Glyph... in no font");
} else {
EWOL_WARNING("no Glyph... in font : " << m_font->getName());
}
return vec3((float)(0.2),
(float)(fontHeigh),
(float)(0.0));
}
// get the kerning ofset :
float kerningOffset = 0.0;
if (m_kerning == true) {
kerningOffset = myGlyph->kerningGet(m_previousCharcode);
}
vec3 outputSize((float)(myGlyph->m_advance.x() + kerningOffset),
(float)(fontHeigh),
(float)(0.0));
// Register the previous character
m_previousCharcode = _charcode;
return outputSize;
}

View File

@ -0,0 +1,56 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/Color.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/resource/TexturedFont.hpp>
#include <ewol/compositing/TextBase.hpp>
#include <exml/exml.hpp>
#include <etk/String.hpp>
#include <etk/Color.hpp>
namespace ewol {
namespace compositing {
class Text : public ewol::compositing::TextBase {
protected:
ememory::SharedPtr<ewol::resource::TexturedFont> m_font; //!< Font resources
public:
/**
* @brief generic constructor
* @param[in] _fontName Name of the font that might be loaded
* @param[in] _fontSize size of the font that might be loaded
*/
Text(const etk::String& _fontName="", int32_t _fontSize=-1);
/**
* @brief generic destructor
*/
virtual ~Text();
public:
virtual void drawD(bool _disableDepthTest);
virtual void drawMT(const mat4& _transformationMatrix, bool _enableDepthTest);
protected:
float m_size;
public:
virtual float getHeight();
virtual float getSize();
virtual ewol::GlyphProperty * getGlyphPointer(char32_t _charcode);
public:
virtual void setFontSize(int32_t _fontSize);
virtual void setFontName(const etk::String& _fontName);
virtual void setFont(etk::String _fontName, int32_t _fontSize);
virtual void setFontMode(enum ewol::font::mode _mode);
virtual void printChar(const char32_t& _charcode);
virtual vec3 calculateSizeChar(const char32_t& _charcode);
};
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,478 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/Color.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/resource/TexturedFont.hpp>
#include <exml/exml.hpp>
#include <etk/String.hpp>
namespace ewol {
namespace compositing {
/**
* @brief This class represent the specific display for every char in the string ...
* @not_in_doc
*/
class TextDecoration {
public:
etk::Color<float,4> m_colorBg; //!< display background color
etk::Color<float,4> m_colorFg; //!< display foreground color
enum ewol::font::mode m_mode; //!< display mode Regular/Bold/Italic/BoldItalic
TextDecoration() {
m_colorBg = etk::color::blue;
m_colorBg = etk::color::green;
m_mode = ewol::font::Regular;
}
};
enum aligneMode {
alignDisable,
alignRight,
alignLeft,
alignCenter,
alignJustify
};
class TextBase : public ewol::Compositing {
protected:
ewol::compositing::Drawing m_vectorialDraw; //!< This is used to draw background selection and other things ...
public:
virtual ewol::compositing::Drawing& getDrawing() {
return m_vectorialDraw;
};
protected:
int32_t m_nbCharDisplayed; //!< prevent some error in calculation size.
vec3 m_sizeDisplayStart; //!< The start windows of the display.
vec3 m_sizeDisplayStop; //!< The end windows of the display.
bool m_needDisplay; //!< This just need the display and not the size rendering.
vec3 m_position; //!< The current position to draw
vec3 m_clippingPosStart; //!< Clipping start position
vec3 m_clippingPosStop; //!< Clipping stop position
bool m_clippingEnable; //!< true if the clipping must be activated
protected:
etk::Color<float,4> m_defaultColorFg; //!< The text foreground color
etk::Color<float,4> m_defaultColorBg; //!< The text background color
protected:
etk::Color<float,4> m_color; //!< The text foreground color
etk::Color<float,4> m_colorBg; //!< The text background color
etk::Color<float,4> m_colorCursor; //!< The text cursor color
etk::Color<float,4> m_colorSelection; //!< The text Selection color
protected:
enum ewol::font::mode m_mode; //!< font display property : Regular/Bold/Italic/BoldItalic
bool m_kerning; //!< Kerning enable or disable on the next elements displayed
char32_t m_previousCharcode; //!< we remember the previous charcode to perform the kerning. @ref Kerning
protected:
float m_startTextpos; //!< start position of the Alignement (when \n the text return at this position)
float m_stopTextPos; //!< end of the alignement (when a string is too hight it cut at the word previously this virtual line and the center is perform with this one)
enum aligneMode m_alignement; //!< Current Alignement mode (justify/left/right ...)
protected:
ememory::SharedPtr<gale::resource::Program> m_GLprogram; //!< pointer on the opengl display program
int32_t m_GLPosition; //!< openGL id on the element (vertex buffer)
int32_t m_GLMatrix; //!< openGL id on the element (transformation matrix)
int32_t m_GLColor; //!< openGL id on the element (color buffer)
int32_t m_GLtexture; //!< openGL id on the element (Texture position)
int32_t m_GLtexID; //!< openGL id on the element (texture ID)
int32_t m_GLtextWidth; //!< openGL Id on the texture width
int32_t m_GLtextHeight; //!< openGL Id on the texture height
protected:
int32_t m_selectionStartPos; //!< start position of the Selection (if == m_cursorPos ==> no selection)
int32_t m_cursorPos; //!< Cursor position (default no cursor == > -100)
protected: // Text
static const int32_t m_vboIdCoord;
static const int32_t m_vboIdCoordText;
static const int32_t m_vboIdColor;
static const int32_t m_vboIdGlyphLevel;
ememory::SharedPtr<gale::resource::VirtualBufferObject> m_VBO;
public:
/**
* @brief load the openGL program and get all the ID needed
*/
virtual void loadProgram(const etk::String& _shaderName);
public:
/**
* @brief generic constructor
*/
TextBase(const etk::String& _shaderName = "DATA:///text.prog?lib=ewol", bool _loadProgram = true);
/**
* @brief generic destructor
*/
virtual ~TextBase();
public: // Derived function
void translate(const vec3& _vect);
void rotate(const vec3& _vect, float _angle);
void scale(const vec3& _vect);
public:
/**
* @brief draw All the refistered text in the current element on openGL
*/
void draw(bool _disableDepthTest=true) {
drawD(_disableDepthTest);
}
//! @previous
void draw(const mat4& _transformationMatrix, bool _enableDepthTest=false) {
drawMT(_transformationMatrix, _enableDepthTest);
}
/**
* @brief draw All the refistered text in the current element on openGL
*/
virtual void drawD(bool _disableDepthTest) = 0;
//! @previous
virtual void drawMT(const mat4& _transformationMatrix, bool _enableDepthTest) = 0;
/**
* @brief clear all the registered element in the current element
*/
virtual void clear();
/**
* @brief clear all the intermediate result detween 2 prints
*/
virtual void reset();
/**
* @brief get the current display position (sometime needed in the gui control)
* @return the current position.
*/
const vec3& getPos() {
return m_position;
};
/**
* @brief set position for the next text writen
* @param[in] _pos Position of the text (in 3D)
*/
void setPos(const vec3& _pos);
//! @previous
inline void setPos(const vec2& _pos) {
setPos(vec3(_pos.x(),_pos.y(),0));
};
/**
* @brief set relative position for the next text writen
* @param[in] _pos ofset apply of the text (in 3D)
*/
void setRelPos(const vec3& _pos);
//! @previous
inline void setRelPos(const vec2& _pos) {
setRelPos(vec3(_pos.x(),_pos.y(),0));
};
/**
* @brief set the default background color of the font (when reset, set this value ...)
* @param[in] _color Color to set on background
*/
void setDefaultColorBg(const etk::Color<>& _color) {
m_defaultColorBg = _color;
}
/**
* @brief set the default Foreground color of the font (when reset, set this value ...)
* @param[in] _color Color to set on foreground
*/
void setDefaultColorFg(const etk::Color<>& _color) {
m_defaultColorFg = _color;
}
/**
* @brief set the Color of the current foreground font
* @param[in] _color Color to set on foreground (for next print)
*/
void setColor(const etk::Color<>& _color) {
m_color = _color;
};
/**
* @brief set the background color of the font (for selected Text (not the global BG))
* @param[in] _color Color to set on background (for next print)
*/
void setColorBg(const etk::Color<>& _color);
/**
* @brief Request a clipping area for the text (next draw only)
* @param[in] _pos Start position of the clipping
* @param[in] _width Width size of the clipping
*/
void setClippingWidth(const vec3& _pos, const vec3& _width) {
setClipping(_pos, _pos+_width);
}
//! @previous
void setClippingWidth(const vec2& _pos, const vec2& _width) {
setClipping(_pos, _pos+_width);
};
/**
* @brief Request a clipping area for the text (next draw only)
* @param[in] _pos Start position of the clipping
* @param[in] _posEnd End position of the clipping
*/
void setClipping(const vec3& _pos, const vec3& _posEnd);
//! @previous
void setClipping(const vec2& _pos, const vec2& _posEnd) {
setClipping(vec3(_pos.x(),_pos.y(),-1), vec3(_posEnd.x(),_posEnd.y(),1) );
};
/**
* @brief enable/Disable the clipping (without lose the current clipping position)
* @brief _newMode The new status of the clipping
*/
// TODO : Rename setClippingActivity
void setClippingMode(bool _newMode);
/**
* @brief Specify the font size (this reset the internal element of the current text (system requirement)
* @param[in] _fontSize New font size
*/
virtual void setFontSize(int32_t _fontSize) = 0;
/**
* @brief Specify the font name (this reset the internal element of the current text (system requirement)
* @param[in] _fontName Current name of the selected font
*/
virtual void setFontName(const etk::String& _fontName) = 0;
/**
* @brief Specify the font property (this reset the internal element of the current text (system requirement)
* @param[in] fontName Current name of the selected font
* @param[in] fontSize New font size
*/
virtual void setFont(etk::String _fontName, int32_t _fontSize) = 0;
/**
* @brief Specify the font mode for the next @ref print
* @param[in] mode The font mode requested
*/
virtual void setFontMode(enum ewol::font::mode _mode) = 0;
/**
* @brief get the current font mode
* @return The font mode applied
*/
enum ewol::font::mode getFontMode() {
return m_mode;
};
virtual float getHeight() = 0;
virtual float getSize() = 0;
virtual ewol::GlyphProperty * getGlyphPointer(char32_t _charcode) = 0;
/**
* @brief enable or disable the bold mode
* @param[in] _status The new status for this display property
*/
void setFontBold(bool _status);
/**
* @brief enable or disable the italic mode
* @param[in] _status The new status for this display property
*/
void setFontItalic(bool _status);
/**
* @brief set the activation of the Kerning for the display (if it existed)
* @param[in] _newMode enable/Diasable the kerning on this font.
*/
void setKerningMode(bool _newMode);
/**
* @brief display a compleat string in the current element.
* @param[in] _text The string to display.
*/
void print(const etk::String& _text);
//! @previous
void print(const etk::UString& _text);
/**
* @brief display a compleat string in the current element with the generic decoration specification. (basic html data)
*
* [code style=xml]
* <br/>
* <br/><br/><br/>
* <center>
* text exemple <b>in bold</b> other text <b>bold part <i>boldItalic part</i></b> an other thext
* <font color="#FF0000">colored text <b>bold color text</b> <i>bold italic text</i> normal color text</font> the end of the string<br/>
* an an other thext
* </center>
* <br/><br/><br/>
* <left>
* plop 1
* </left>
* <br/><br/><br/>
* <right>
* plop 2
* </right>
* <br/><br/><br/>
* <justify>
* Un exemple de text
* </justify>
* [/code]
*
* @note This is parsed with tiny xml, then be carfull that the XML is correct, and all balises are closed ... otherwite the display can not be done
* @param[in] _text The string to display.
* @TODO : implementation not done ....
*/
void printDecorated(const etk::String& _text);
//! @previous
void printDecorated(const etk::UString& _text);
/**
* @brief display a compleat string in the current element with the generic decoration specification. (basic html data)
*
* [code style=xml]
* <html>
* <body>
* <br/>
* <br/><br/><br/>
* <center>
* text exemple <b>in bold</b> other text <b>bold part <i>boldItalic part</i></b> an other thext
* <font color="#FF0000">colored text <b>bold color text</b> <i>bold italic text</i> normal color text</font> the end of the string<br/>
* an an other thext
* </center>
* <br/><br/><br/>
* <left>
* plop 1
* </left>
* <br/><br/><br/>
* <right>
* plop 2
* </right>
* <br/><br/><br/>
* <justify>
* Un exemple de text
* </justify>
* </body>
* </html>
* [/code]
*
* @note This is parsed with tiny xml, then be carfull that the XML is correct, and all balises are closed ... otherwite the display can not be done
* @param[in] _text The string to display.
* @TODO : implementation not done ....
*/
void printHTML(const etk::String& _text);
//! @previous
void printHTML(const etk::UString& _text);
/**
* @brief display a compleat string in the current element whith specific decorations (advence mode).
* @param[in] _text The string to display.
* @param[in] _decoration The text decoration for the text that might be display (if the vector is smaller, the last parameter is get)
*/
void print(const etk::String& _text, const etk::Vector<TextDecoration>& _decoration);
//! @previous
void print(const etk::UString& _text, const etk::Vector<TextDecoration>& _decoration);
/**
* @brief display the current char in the current element (note that the kerning is availlable if the position is not changed)
* @param[in] _charcode Char that might be dispalyed
*/
virtual void printChar(const char32_t& _charcode) = 0;
/**
* @brief This generate the line return == > it return to the alignement position start and at the correct line position ==> it might be use to not know the line height
*/
void forceLineReturn();
protected:
/**
* @brief This parse a tinyXML node (void pointer to permit to hide tiny XML in include).
* @param[in] _element the exml element.
*/
void parseHtmlNode(const exml::Element& _element);
public:
/**
* @brief This generate the possibility to generate the big text property
* @param[in] _startTextpos The x text start position of the display.
* @param[in] _stopTextPos The x text stop position of the display.
* @param[in] _alignement mode of alignement for the Text.
* @note The text align in center change of line every display done (even if it was just a char)
*/
void setTextAlignement(float _startTextpos, float _stopTextPos, enum ewol::compositing::aligneMode _alignement=ewol::compositing::alignDisable);
/**
* @brief disable the alignement system
*/
void disableAlignement();
/**
* @brief get the current alignement property
* @return the curent alignement type
*/
enum ewol::compositing::aligneMode getAlignement();
/**
* @brief calculate a theoric text size
* @param[in] _text The string to calculate dimention.
* @return The theoric size used.
*/
vec3 calculateSizeHTML(const etk::String& _text);
//! @previous
vec3 calculateSizeHTML(const etk::UString& _text);
/**
* @brief calculate a theoric text size
* @param[in] _text The string to calculate dimention.
* @return The theoric size used.
*/
vec3 calculateSizeDecorated(const etk::String& _text);
//! @previous
vec3 calculateSizeDecorated(const etk::UString& _text);
/**
* @brief calculate a theoric text size
* @param[in] _text The string to calculate dimention.
* @return The theoric size used.
*/
vec3 calculateSize(const etk::String& _text);
//! @previous
vec3 calculateSize(const etk::UString& _text);
/**
* @brief calculate a theoric charcode size
* @param[in] _charcode The Unicode value to calculate dimention.
* @return The theoric size used.
*/
inline vec3 calculateSize(const char32_t& _charcode) {
return calculateSizeChar(_charcode);
};
protected:
//! @previous
virtual vec3 calculateSizeChar(const char32_t& _charcode) = 0;
public:
/**
* @brief draw a cursor at the specify position
* @param[in] _isInsertMode True if the insert mode is activated
* @param[in] _cursorSize The sizae of the cursor that might be set when insert mode is set [default 20]
*/
void printCursor(bool _isInsertMode, float _cursorSize = 20.0f);
protected:
/**
* @brief calculate the element number that is the first out the alignement range
* (start at the specify ID, and use start pos with current one)
* @param[in] _text The string that might be parsed.
* @param[in] _start The first elemnt that might be used to calculate.
* @param[out] _stop The last Id availlable in the current string.
* @param[out] _space Number of space in the string.
* @param[out] _freespace This represent the number of pixel present in the right white space.
* @return true if the rifht has free space that can be use for jystify.
* @return false if we find '\n'
*/
bool extrapolateLastId(const etk::String& _text, const int32_t _start, int32_t& _stop, int32_t& _space, int32_t& _freeSpace);
//! @previous
bool extrapolateLastId(const etk::UString& _text, const int32_t _start, int32_t& _stop, int32_t& _space, int32_t& _freeSpace);
protected:
// this section is reserved for HTML parsing and display:
etk::UString m_htmlCurrrentLine; //!< current line for HTML display
etk::Vector<TextDecoration> m_htmlDecoration; //!< current decoration for the HTML display
TextDecoration m_htmlDecoTmp; //!< current decoration
/**
* @brief add a line with the current m_htmlDecoTmp decoration
* @param[in] _data The cuurent data to add.
*/
void htmlAddData(const etk::UString& _data);
/**
* @brief draw the current line
*/
void htmlFlush();
public:
/**
* @brief remove the cursor display
*/
void disableCursor();
/**
* @brief set a cursor at a specific position:
* @param[in] _cursorPos id of the cursor position
*/
void setCursorPos(int32_t _cursorPos);
/**
* @brief set a cursor at a specific position with his associated selection:
* @param[in] _cursorPos id of the cursor position
* @param[in] _selectionStartPos id of the starting of the selection
*/
void setCursorSelection(int32_t _cursorPos, int32_t _selectionStartPos);
/**
* @brief change the selection color
* @param[in] _color New color for the Selection
*/
void setSelectionColor(const etk::Color<>& _color);
/**
* @brief change the cursor color
* @param[in] _color New color for the Selection
*/
void setCursorColor(const etk::Color<>& _color);
};
}
}

View File

@ -0,0 +1,407 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/compositing/TextDF.hpp>
#include <ewol/context/Context.hpp>
#include <etk/types.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::compositing::TextDF);
ewol::compositing::TextDF::TextDF(const etk::String& _fontName, int32_t _fontSize) :
ewol::compositing::TextBase("", false),
m_fontDF(null),
m_GLglyphLevel(-1),
m_size(12.0) {
setFont(_fontName, _fontSize);
loadProgram("DATA:///fontDistanceField/font1.prog?lib=ewol");
}
ewol::compositing::TextDF::~TextDF() {
}
void ewol::compositing::TextDF::updateSizeToRender(const vec2& _size) {
float minSize = etk::min(_size.x(), _size.y());
if (m_fontDF != null) {
setFontSize(m_fontDF->getSize(minSize));
}
}
void ewol::compositing::TextDF::drawMT(const mat4& _transformationMatrix, bool _enableDepthTest) {
// draw BG in any case:
m_vectorialDraw.draw();
if ( m_VBO->bufferSize(m_vboIdCoord) <= 0
|| m_fontDF == null) {
//EWOL_WARNING("Nothink to draw...");
return;
}
if (m_fontDF == null) {
EWOL_WARNING("no font...");
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
if (_enableDepthTest == true) {
gale::openGL::enable(gale::openGL::flag_depthTest);
}
// set Matrix: translation/positionMatrix
mat4 projMatrix = gale::openGL::getMatrix();
mat4 camMatrix = gale::openGL::getCameraMatrix();
mat4 tmpMatrix = projMatrix * camMatrix * _transformationMatrix;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// Texture:
m_GLprogram->setTexture0(m_GLtexID, m_fontDF->getRendererId());
m_GLprogram->uniform1i(m_GLtextWidth, m_fontDF->getOpenGlSize().x());
m_GLprogram->uniform1i(m_GLtextHeight, m_fontDF->getOpenGlSize().x());
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
m_GLprogram->sendAttributePointer(m_GLtexture, m_VBO, m_vboIdCoordText);
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdColor);
m_GLprogram->sendAttributePointer(m_GLglyphLevel, m_VBO, m_vboIdGlyphLevel);
// Request the draw od the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
if (_enableDepthTest == true) {
gale::openGL::disable(gale::openGL::flag_depthTest);
}
}
void ewol::compositing::TextDF::drawD(bool _disableDepthTest) {
// draw BG in any case:
m_vectorialDraw.draw();
if ( m_VBO->bufferSize(m_vboIdCoord) <= 0
|| m_fontDF == null) {
// TODO : Set it back
//EWOL_WARNING("Nothink to draw...");
return;
}
if (m_fontDF == null) {
EWOL_WARNING("no font...");
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
// set Matrix: translation/positionMatrix
mat4 tmpMatrix = gale::openGL::getMatrix()*m_matrixApply;
m_GLprogram->use();
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// Texture:
m_GLprogram->setTexture0(m_GLtexID, m_fontDF->getRendererId());
m_GLprogram->uniform1i(m_GLtextWidth, m_fontDF->getOpenGlSize().x());
m_GLprogram->uniform1i(m_GLtextHeight, m_fontDF->getOpenGlSize().x());
m_GLprogram->sendAttributePointer(m_GLPosition, m_VBO, m_vboIdCoord);
m_GLprogram->sendAttributePointer(m_GLtexture, m_VBO, m_vboIdCoordText);
m_GLprogram->sendAttributePointer(m_GLColor, m_VBO, m_vboIdColor);
m_GLprogram->sendAttributePointer(m_GLglyphLevel, m_VBO, m_vboIdGlyphLevel);
// Request the draw od the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, m_VBO->bufferSize(m_vboIdCoord));
m_GLprogram->unUse();
}
void ewol::compositing::TextDF::loadProgram(const etk::String& _shaderName) {
ewol::compositing::TextBase::loadProgram(_shaderName);
if (m_GLprogram != null) {
m_GLglyphLevel = m_GLprogram->getAttribute("EW_glyphLevel");
}
}
float ewol::compositing::TextDF::getHeight() {
if (m_fontDF == null) {
EWOL_WARNING("no font...");
return 1;
}
return m_fontDF->getHeight(m_size);
}
ewol::GlyphProperty * ewol::compositing::TextDF::getGlyphPointer(char32_t _charcode) {
if (m_fontDF == null) {
EWOL_WARNING("no font...");
return null;
}
return m_fontDF->getGlyphPointer(_charcode);
}
void ewol::compositing::TextDF::setFontSize(int32_t _fontSize) {
clear();
EWOL_VERBOSE("Set font Size: " << _fontSize);
if (_fontSize <= 1) {
m_size = ewol::getContext().getFontDefault().getSize();
} else {
m_size = _fontSize;
}
}
void ewol::compositing::TextDF::setFontName(const etk::String& _fontName) {
clear();
// remove old one
ememory::SharedPtr<ewol::resource::DistanceFieldFont> previousFont = m_fontDF;
etk::String fontName;
if (_fontName == "") {
fontName = ewol::getContext().getFontDefault().getName();
} else {
fontName = _fontName;
}
EWOL_VERBOSE("Set font name: '" << fontName << "'");
// link to new one
m_fontDF = ewol::resource::DistanceFieldFont::create(fontName);
if (m_fontDF == null) {
EWOL_ERROR("Can not get find resource");
m_fontDF = previousFont;
}
}
void ewol::compositing::TextDF::setFont(etk::String _fontName, int32_t _fontSize) {
setFontSize(_fontSize);
setFontName(_fontName);
}
void ewol::compositing::TextDF::setFontMode(enum ewol::font::mode _mode) {
m_mode = _mode;
}
//#define ANGLE_OF_ITALIC (tan(0.4))
#define ANGLE_OF_ITALIC (0.00698143f)
void ewol::compositing::TextDF::printChar(const char32_t& _charcode) {
// get a pointer on the glyph property :
ewol::GlyphProperty* myGlyph = getGlyphPointer(_charcode);
if (null == myGlyph) {
EWOL_ERROR(" font does not really existed ...");
return;
}
float fontSize = getSize();
float fontHeigh = getHeight();
float factorDisplay = m_fontDF->getDisplayRatio(fontSize);
// get the kerning ofset :
float kerningOffset = 0;
if (true == m_kerning) {
kerningOffset = myGlyph->kerningGet(m_previousCharcode);
if (kerningOffset != 0) {
//EWOL_DEBUG("Kerning between : '" << m_previousCharcode << "'&'" << myGlyph->m_UVal << "' value : " << kerningOffset);
}
}
// 0x01 == 0x20 == ' ';
if ( _charcode != 0x01
&& _charcode != 0x20) {
float glyphLevel = 0.5f;
if ( m_mode == ewol::font::BoldItalic
|| m_mode == ewol::font::Bold) {
glyphLevel = 0.41f;
}
float italicMove = 0.0f;
if ( m_mode == ewol::font::BoldItalic
|| m_mode == ewol::font::Italic) {
// This is a simple version of Italic mode, in theory we need to move the up and the down...
italicMove = (float)myGlyph->m_sizeTexture.y() * factorDisplay * ANGLE_OF_ITALIC;
// TODO : pb on the clipper...
}
/* Bitmap position
* xA xB
* yC *------*
* | |
* | |
* yD *------*
*/
#if 0
float dxA = m_position.x() + (myGlyph->m_bearing.x() + kerningOffset) * factorDisplay;
float dxB = dxA + myGlyph->m_sizeTexture.x() * factorDisplay;
float dyC = m_position.y() + (myGlyph->m_bearing.y() + fontHeigh - fontSize) * factorDisplay;
float dyD = dyC - myGlyph->m_sizeTexture.y() * factorDisplay;
#else
//EWOL_DEBUG(" plop : fontHeigh" << fontHeigh << " fontSize=" << fontSize);
float dxA = m_position.x() + ((float)myGlyph->m_bearing.x() + kerningOffset - (float)m_fontDF->getPixelBorderSize()*0.5f) * factorDisplay;
float dxB = dxA + ((float)myGlyph->m_sizeTexture.x() + (float)m_fontDF->getPixelBorderSize()) * factorDisplay;
float dyC = m_position.y() + (fontHeigh - fontSize + ((float)myGlyph->m_bearing.y() + (float)m_fontDF->getPixelBorderSize()*0.5f) * factorDisplay);
float dyD = dyC - ((float)myGlyph->m_sizeTexture.y() + (float)m_fontDF->getPixelBorderSize()) * factorDisplay;
#endif
float tuA = myGlyph->m_texturePosStart.x();
float tuB = tuA + myGlyph->m_texturePosSize.x();
float tvC = myGlyph->m_texturePosStart.y();
float tvD = tvC + myGlyph->m_texturePosSize.y();
/*
vec3 drawingPos = m_vectorialDraw.getPos();
etk::Color<> backColor = m_vectorialDraw.getColor();
m_vectorialDraw.setPos(vec2(dxA, dyC));
m_vectorialDraw.setColor(etk::Color<>(0.0,1.0,0.0,1.0));
m_vectorialDraw.rectangle(vec2(dxB, dyD));
m_vectorialDraw.setPos(drawingPos);
m_vectorialDraw.setColor(backColor);
*/
// Clipping and drawing area
if( m_clippingEnable == true
&& ( dxB < m_clippingPosStart.x()
|| dxA > m_clippingPosStop.x()
|| dyC < m_clippingPosStart.y()
|| dyD > m_clippingPosStop.y() ) ) {
// Nothing to diplay ...
} else {
if (m_clippingEnable == true) {
// generata positions...
float TexSizeX = tuB - tuA;
if (dxA < m_clippingPosStart.x()) {
// clip display
float drawSize = m_clippingPosStart.x() - dxA;
// update element start display
dxA = m_clippingPosStart.x();
float addElement = TexSizeX * drawSize / ((float)myGlyph->m_sizeTexture.x() * factorDisplay);
// update texture start X Pos
tuA += addElement;
}
if (dxB > m_clippingPosStop.x()) {
// clip display
float drawSize = dxB - m_clippingPosStop.x();
// update element start display
dxB = m_clippingPosStop.x();
float addElement = TexSizeX * drawSize / ((float)myGlyph->m_sizeTexture.x() * factorDisplay);
// update texture start X Pos
tuB -= addElement;
}
float TexSizeY = tvC - tvD;
if (dyC > m_clippingPosStop.y()) {
// clip display
float drawSize = dyC - m_clippingPosStop.y();
// update element start display
dyC = m_clippingPosStop.y();
float addElement = TexSizeY * drawSize / ((float)myGlyph->m_sizeTexture.y() * factorDisplay);
// update texture start X Pos
tvC -= addElement;
}
if (dyD < m_clippingPosStart.y()) {
// clip display
float drawSize = m_clippingPosStart.y() - dyD;
// update element start display
dyD = m_clippingPosStart.y();
float addElement = TexSizeY * drawSize / ((float)myGlyph->m_sizeTexture.y() * factorDisplay);
// update texture start X Pos
tvD += addElement;
}
}
if( dxB <= dxA
|| dyD >= dyC) {
// nothing to do ...
} else {
/* Bitmap position
* 0------1
* | |
* | |
* 3------2
*/
if (m_needDisplay == true) {
vec3 bitmapDrawPos[4];
bitmapDrawPos[0].setValue(dxA+italicMove, dyC, 0);
bitmapDrawPos[1].setValue(dxB+italicMove, dyC, 0);
bitmapDrawPos[2].setValue(dxB, dyD, 0);
bitmapDrawPos[3].setValue(dxA, dyD, 0);
/* texture Position :
* 0------1
* | |
* | |
* 3------2
*/
vec2 texturePos[4];
texturePos[0].setValue(tuA+m_mode, tvC);
texturePos[1].setValue(tuB+m_mode, tvC);
texturePos[2].setValue(tuB+m_mode, tvD);
texturePos[3].setValue(tuA+m_mode, tvD);
// NOTE : Android does not support the Quads elements ...
/* Step 1 :
* ********
* ******
* ****
* **
*
*/
// set texture coordonates :
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[0]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[1]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[2]);
// set display positions :
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[0]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[1]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[2]);
// set the color
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
// set the bliph level
m_VBO->pushOnBuffer(m_vboIdGlyphLevel, glyphLevel);
m_VBO->pushOnBuffer(m_vboIdGlyphLevel, glyphLevel);
m_VBO->pushOnBuffer(m_vboIdGlyphLevel, glyphLevel);
/* Step 2 :
*
* **
* ****
* ******
* ********
*/
// set texture coordonates :
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[0]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[2]);
m_VBO->pushOnBuffer(m_vboIdCoordText, texturePos[3]);
// set display positions :
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[0]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[2]);
m_VBO->pushOnBuffer(m_vboIdCoord, bitmapDrawPos[3]);
// set the color
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
m_VBO->pushOnBuffer(m_vboIdColor, m_color);
// set the bliph level
m_VBO->pushOnBuffer(m_vboIdGlyphLevel, glyphLevel);
m_VBO->pushOnBuffer(m_vboIdGlyphLevel, glyphLevel);
m_VBO->pushOnBuffer(m_vboIdGlyphLevel, glyphLevel);
}
}
}
}
// move the position :
//EWOL_DEBUG(" 5 pos=" << m_position << " advance=" << myGlyph->m_advance.x() << " kerningOffset=" << kerningOffset);
m_position.setX(m_position.x() + (myGlyph->m_advance.x() + kerningOffset) * factorDisplay);
//EWOL_DEBUG(" 6 print '" << charcode << "' : start=" << m_sizeDisplayStart << " stop=" << m_sizeDisplayStop << " pos=" << m_position);
// Register the previous character
m_previousCharcode = _charcode;
m_VBO->flush();
return;
}
vec3 ewol::compositing::TextDF::calculateSizeChar(const char32_t& _charcode) {
// get a pointer on the glyph property :
ewol::GlyphProperty * myGlyph = getGlyphPointer(_charcode);
int32_t fontHeigh = getHeight();
// get the kerning ofset :
float kerningOffset = 0.0;
if (true == m_kerning) {
kerningOffset = myGlyph->kerningGet(m_previousCharcode);
}
vec3 outputSize((float)(myGlyph->m_advance.x() + kerningOffset)*m_fontDF->getDisplayRatio(getSize()),
(float)(fontHeigh),
(float)(0.0));
// Register the previous character
m_previousCharcode = _charcode;
return outputSize;
}

View File

@ -0,0 +1,70 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/Color.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Compositing.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/resource/DistanceFieldFont.hpp>
#include <ewol/compositing/TextBase.hpp>
#include <exml/exml.hpp>
#include <etk/String.hpp>
namespace ewol {
namespace compositing {
class TextDF : public ewol::compositing::TextBase {
protected:
ememory::SharedPtr<ewol::resource::DistanceFieldFont> m_fontDF; //!< Font resources
protected:
int32_t m_GLglyphLevel; //!< openGL Id on the glyph level display
public:
/**
* @brief generic constructor
* @param[in] _fontName Name of the font that might be loaded
* @param[in] _fontSize size of the font that might be loaded
*/
TextDF(const etk::String& _fontName="", int32_t _fontSize=-1);
/**
* @brief generic destructor
*/
virtual ~TextDF();
public:
/**
* @brief Calculate size to be at the best size for a render in this special size.
* @note special for Distance field mode.
* @param[in] _size request dimention.
*/
void updateSizeToRender(const vec2& _size);
public:
virtual void drawD(bool _disableDepthTest);
virtual void drawMT(const mat4& _transformationMatrix, bool _enableDepthTest);
protected:
float m_size;
public:
virtual float getHeight();
virtual float getSize() {
return m_size;
}
virtual void setSize(float _size) {
m_size = _size;
}
virtual ewol::GlyphProperty * getGlyphPointer(char32_t _charcode);
public:
virtual void loadProgram(const etk::String& _shaderName);
virtual void setFontSize(int32_t _fontSize);
virtual void setFontName(const etk::String& _fontName);
virtual void setFont(etk::String _fontName, int32_t _fontSize);
virtual void setFontMode(enum ewol::font::mode _mode);
virtual void printChar(const char32_t& _charcode);
virtual vec3 calculateSizeChar(const char32_t& _charcode);
};
}
}

View File

@ -0,0 +1,49 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/context/Application.hpp>
#include <ewol/context/Context.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::context::Application);
ewol::context::Application::Application() {
}
ewol::context::Application::~Application() {
}
void ewol::context::Application::onCreate(ewol::Context& _context) {
}
void ewol::context::Application::onStart(ewol::Context& _context) {
}
void ewol::context::Application::onResume(ewol::Context& _context) {
}
void ewol::context::Application::onPause(ewol::Context& _context) {
}
void ewol::context::Application::onStop(ewol::Context& _context) {
}
void ewol::context::Application::onDestroy(ewol::Context& _context) {
}
void ewol::context::Application::onKillDemand(ewol::Context& _context) {
_context.exit(0);
}

View File

@ -0,0 +1,54 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
namespace ewol {
class Context;
namespace context {
class Application {
public:
Application();
virtual ~Application();
public:
/**
* @brief The application is created.
* @param[in] _context Current ewol context.
*/
virtual void onCreate(ewol::Context& _context);
/**
* @brief The application is started.
* @param[in] _context Current ewol context.
*/
virtual void onStart(ewol::Context& _context);
/**
* @brief The application is resumed (now visible).
* @param[in] _context Current ewol context.
*/
virtual void onResume(ewol::Context& _context);
/**
* @brief The application is Hide / not visible.
* @param[in] _context Current ewol context.
*/
virtual void onPause(ewol::Context& _context);
/**
* @brief The application is stopped.
* @param[in] _context Current ewol context.
*/
virtual void onStop(ewol::Context& _context);
/**
* @brief The application is removed (call destructor just adter it.).
* @param[in] _context Current ewol context.
*/
virtual void onDestroy(ewol::Context& _context);
/**
* @brief The user request application removing.
* @param[in] _context Current ewol context.
*/
virtual void onKillDemand(ewol::Context& _context);
};
};
};

View File

@ -0,0 +1,43 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/context/ConfigFont.hpp>
#include <ewol/resource/FontFreeType.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::context::ConfigFont);
ewol::context::ConfigFont::ConfigFont() :
m_folder("DATA:///fonts?lib=ewol"),
m_name("Arial;Helvetica"),
m_size(10),
m_useExternal(false) {
#ifdef __TARGET_OS__Android
m_name = "Roboto;DroidSans";
#endif
ewol::resource::freeTypeInit();
}
ewol::context::ConfigFont::~ConfigFont() {
// UnInit FreeTypes
ewol::resource::freeTypeUnInit();
}
void ewol::context::ConfigFont::set(const etk::String& _fontName, int32_t _size) {
m_name = _fontName;
m_size = _size;
EWOL_DEBUG("Set default Font : '" << m_name << "' size=" << m_size);
}
void ewol::context::ConfigFont::setSize(int32_t _size) {
m_size = _size;
EWOL_DEBUG("Set default Font : '" << m_name << "' size=" << m_size << " (change size only)");
}
void ewol::context::ConfigFont::setName(const etk::String& _fontName) {
m_name = _fontName;
EWOL_DEBUG("Set default Font : '" << m_name << "' size=" << m_size << " (change name only)");
}

View File

@ -0,0 +1,92 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/debug.hpp>
#include <etk/uri/uri.hpp>
namespace ewol {
namespace context {
class ConfigFont {
public:
/**
* Constructor / destructor
*/
ConfigFont();
virtual ~ConfigFont();
private:
etk::Uri m_folder;
public:
/**
* @brief Specify the default font folder for the Ewol search system (only needed when embended font)
* @param[in] _folder basic folder of the font (ex: DATA:fonts)
*/
void setFolder(const etk::Uri& _folder) {
m_folder = _folder;
};
/**
* @brief get the default font folder.
* @return The default font folder.
*/
const etk::Uri& getFolder() {
return m_folder;
};
private:
etk::String m_name;
int32_t m_size;
public:
/**
* @brief set the defaut font for all the widgets and basics display.
* @param[in] _fontName The font name requested (not case sensitive) ex "Arial" or multiple separate by ';' ex : "Arial;Helvetica".
* @param[in] _size The default size of the font default=10.
*/
void set(const etk::String& _fontName, int32_t _size);
/**
* @brief get the current default font name
* @raturn a reference on the font name string
*/
const etk::String& getName() {
return m_name;
};
/**
* @brief Set the current default font name
* @param[in] _fontName The font name requested (not case sensitive) ex "Arial" or multiple separate by ';' ex : "Arial;Helvetica".
*/
void setName(const etk::String& _fontName);
/**
* @brief get the default font size.
* @return the font size.
*/
int32_t getSize() {
return m_size;
};
/**
* @brief Set the default font size.
* @param[in] _size new font size.
*/
void setSize(int32_t _size);
private:
bool m_useExternal;
public:
/**
* @brief set use of internal/external Font
* @param[in] _val true to enable search of internal data.
*/
void setUseExternal(bool _val) {
m_useExternal=_val;
};
/**
* @brief get the use of internal/external Font
* @return true to enable search of internal data.
*/
bool getUseExternal() {
return m_useExternal;
};
};
};
};

View File

@ -0,0 +1,382 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <etk/etk.hpp>
#include <etk/tool.hpp>
#include <etk/theme/theme.hpp>
#include <ethread/tools.hpp>
#include <ethread/Mutex.hpp>
#include <ewol/ewol.hpp>
#include <ewol/debug.hpp>
#include <gale/renderer/openGL/openGL.hpp>
#include <gale/Dimension.hpp>
#include <etranslate/etranslate.hpp>
#include <ewol/object/Object.hpp>
#include <ewol/object/Manager.hpp>
#include <ewol/widget/Widget.hpp>
#include <ewol/widget/Windows.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::Context);
static ewol::Context* l_curentInterface=null;
ewol::Context& ewol::getContext() {
gale::Context& context = gale::getContext();
ememory::SharedPtr<gale::Application> appl = context.getApplication();
if (appl == null) {
EWOL_CRITICAL("[CRITICAL] try acces at an empty GALE application (can not get Context)");
// ???
}
return *(ememory::staticPointerCast<ewol::Context>(appl));
}
void ewol::Context::setInitImage(const etk::Uri& _fileName) {
//m_initDisplayImageName = _fileName;
}
void ewol::Context::inputEventTransfertWidget(ewol::WidgetShared _source,
ewol::WidgetShared _destination) {
m_input.transfertEvent(_source, _destination);
}
void ewol::Context::inputEventGrabPointer(ewol::WidgetShared _widget) {
m_input.grabPointer(_widget);
}
void ewol::Context::inputEventUnGrabPointer() {
m_input.unGrabPointer();
}
void ewol::Context::onCreate(gale::Context& _context) {
EWOL_INFO(" == > Ewol system create (BEGIN)");
// Add basic ewol translation:
etranslate::addPath("ewol", "DATA:///translate/ewol/?lib=ewol");
etranslate::autoDetectLanguage();
// By default we set 2 themes (1 color and 1 shape ...) :
etk::theme::setNameDefault("GUI", "shape/square/");
etk::theme::setNameDefault("COLOR", "color/black/");
// parse for help:
for(int32_t iii = 0; iii < _context.getCmd().size() ; ++iii) {
if ( _context.getCmd().get(iii) == "-h"
|| _context.getCmd().get(iii) == "--help") {
EWOL_PRINT("ewol - help : ");
EWOL_PRINT(" " << etk::getApplicationName() << " [options]");
EWOL_PRINT(" -h/--help: Display this help");
EWOL_PRINT(" example:");
EWOL_PRINT(" " << etk::getApplicationName() << " --help");
// this is a global help system does not remove it
continue;
} else {
continue;
}
_context.getCmd().remove(iii);
--iii;
}
EWOL_INFO("EWOL v:" << ewol::getVersion());
// force a recalculation
/*
requestUpdateSize();
#if defined(__EWOL_ANDROID_ORIENTATION_LANDSCAPE__)
forceOrientation(ewol::screenLandscape);
#elif defined(__EWOL_ANDROID_ORIENTATION_PORTRAIT__)
forceOrientation(ewol::screenPortrait);
#else
forceOrientation(ewol::screenAuto);
#endif
*/
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl == null) {
EWOL_ERROR(" == > Create without application");
return;
}
appl->onCreate(*this);
EWOL_INFO(" == > Ewol system create (END)");
}
void ewol::Context::onStart(gale::Context& _context) {
EWOL_INFO(" == > Ewol system start (BEGIN)");
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl == null) {
// TODO : Request exit of the application .... with error ...
return;
}
appl->onStart(*this);
EWOL_INFO(" == > Ewol system start (END)");
}
void ewol::Context::onResume(gale::Context& _context) {
EWOL_INFO(" == > Ewol system resume (BEGIN)");
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl == null) {
return;
}
appl->onResume(*this);
EWOL_INFO(" == > Ewol system resume (END)");
}
void ewol::Context::onRegenerateDisplay(gale::Context& _context) {
//EWOL_INFO("REGENERATE_DISPLAY");
// check if the user selected a windows
ewol::widget::WindowsShared window = m_windowsCurrent;
if (window == null) {
EWOL_DEBUG("No windows ...");
return;
}
// Redraw all needed elements
window->onRegenerateDisplay();
if (m_widgetManager.isDrawingNeeded() == true) {
markDrawingIsNeeded();
}
//markDrawingIsNeeded();
}
void ewol::Context::onDraw(gale::Context& _context) {
//EWOL_INFO("DRAW");
// clean internal data...
m_objectManager.cleanInternalRemoved();
// real draw...
ewol::widget::WindowsShared window = m_windowsCurrent;
if (window == null) {
return;
}
window->sysDraw();
}
void ewol::Context::onPause(gale::Context& _context) {
EWOL_INFO(" == > Ewol system pause (BEGIN)");
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl == null) {
return;
}
appl->onPause(*this);
EWOL_INFO(" == > Ewol system pause (END)");
}
void ewol::Context::onStop(gale::Context& _context) {
EWOL_INFO(" == > Ewol system stop (BEGIN)");
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl == null) {
return;
}
appl->onStop(*this);
EWOL_INFO(" == > Ewol system stop (END)");
}
void ewol::Context::onDestroy(gale::Context& _context) {
EWOL_INFO(" == > Ewol system destroy (BEGIN)");
// Remove current windows
m_windowsCurrent.reset();
// clean all widget and sub widget with their resources:
m_objectManager.cleanInternalRemoved();
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl != null) {
// call application to uninit
appl->onDestroy(*this);
m_application.reset();
}
// internal clean elements
m_objectManager.cleanInternalRemoved();
EWOL_INFO("List of all widget of this context must be equal at 0 ==> otherwise some remove is missing");
m_objectManager.displayListObject();
// now All must be removed !!!
m_objectManager.unInit();
EWOL_INFO(" == > Ewol system destroy (END)");
}
void ewol::Context::onKillDemand(gale::Context& _context) {
EWOL_INFO(" == > User demand a destroy (BEGIN)");
ememory::SharedPtr<ewol::context::Application> appl = m_application;
if (appl == null) {
exit(0);
return;
}
appl->onKillDemand(*this);
EWOL_INFO(" == > User demand a destroy (END)");
}
void ewol::Context::onPointer(enum gale::key::type _type,
int32_t _pointerID,
const vec2& _pos,
gale::key::status _state) {
switch (_state) {
case gale::key::status::move:
//EWOL_DEBUG("Receive MSG : THREAD_INPUT_MOTION");
m_input.motion(_type, _pointerID, _pos);
break;
case gale::key::status::down:
case gale::key::status::downRepeate:
//EWOL_DEBUG("Receive MSG : THREAD_INPUT_STATE");
m_input.state(_type, _pointerID, true, _pos);
break;
case gale::key::status::up:
//EWOL_DEBUG("Receive MSG : THREAD_INPUT_STATE");
m_input.state(_type, _pointerID, false, _pos);
break;
default:
EWOL_DEBUG("Unknow state : " << _state);
break;
}
}
void ewol::Context::onKeyboard(const gale::key::Special& _special,
enum gale::key::keyboard _type,
char32_t _value,
gale::key::status _state) {
EWOL_VERBOSE("event {" << _special << "} " << _type << " " << _value << " " << _state);
// store the keyboard special key status for mouse event...
m_input.setLastKeyboardSpecial(_special);
if (m_windowsCurrent == null) {
// No windows ...
return;
}
bool repeate = (_state == gale::key::status::downRepeate);
bool isDown = (_state == gale::key::status::downRepeate)
|| (_state == gale::key::status::down);
if (m_windowsCurrent->onEventShortCut(_special,
_value,
_type,
isDown) == true) {
// Keep a shortcut ...
return;
}
// get the current focused Widget :
ewol::WidgetShared tmpWidget = m_widgetManager.focusGet();
if (tmpWidget == null) {
// no Widget ...
return;
}
// check if the widget allow repeating key events.
//EWOL_INFO("repeating test :" << repeate << " widget=" << tmpWidget->getKeyboardRepeate() << " state=" << isDown);
if( repeate == false
|| ( repeate == true
&& tmpWidget->getKeyboardRepeat() == true) ) {
// check Widget shortcut
if (tmpWidget->onEventShortCut(_special,
_value,
_type,
isDown) == false) {
// generate the direct event ...
if (_type == gale::key::keyboard::character) {
ewol::event::EntrySystem tmpEntryEvent(gale::key::keyboard::character,
gale::key::status::up,
_special,
_value);
if(isDown == true) {
tmpEntryEvent.m_event.setStatus(gale::key::status::down);
}
tmpWidget->systemEventEntry(tmpEntryEvent);
} else { // THREAD_KEYBORAD_MOVE
ewol::event::EntrySystem tmpEntryEvent(_type,
gale::key::status::up,
_special,
0);
if(isDown == true) {
tmpEntryEvent.m_event.setStatus(gale::key::status::down);
}
tmpWidget->systemEventEntry(tmpEntryEvent);
}
} else {
EWOL_DEBUG("remove Repeate key ...");
}
}
}
/*
void ewol::Context::processEvents() {
case eSystemMessage::msgResize:
//EWOL_DEBUG("Receive MSG : THREAD_RESIZE");
m_windowsSize = data->dimention;
ewol::Dimension::setPixelWindowsSize(m_windowsSize);
forceRedrawAll();
break;
*/
void ewol::Context::onClipboardEvent(enum gale::context::clipBoard::clipboardListe _clipboardId) {
ewol::WidgetShared tmpWidget = m_widgetManager.focusGet();
if (tmpWidget != null) {
tmpWidget->onEventClipboard(_clipboardId);
}
}
ewol::Context::Context(ewol::context::Application* _application) :
//m_application(ememory::makeShared<ewol::context::Application>(_application)),
m_application(_application),
m_objectManager(*this),
m_input(*this),
m_windowsCurrent(null),
m_initStepId(0) {
if (m_application == null) {
EWOL_CRITICAL("Can not start context with no Application ==> rtfm ...");
}
}
ewol::Context::~Context() {
// nothing to do ...
}
void ewol::Context::requestUpdateSize() {
gale::Context& context = gale::getContext();
context.requestUpdateSize();
}
void ewol::Context::onPeriod(const echrono::Clock& _time) {
m_objectManager.timeCall(_time);
}
void ewol::Context::resetIOEvent() {
m_input.newLayerSet();
}
void ewol::Context::setWindows(const ewol::widget::WindowsShared& _windows) {
EWOL_INFO("set New windows");
// remove current focus :
m_widgetManager.focusSetDefault(null);
m_widgetManager.focusRelease();
// set the new pointer as windows system
m_windowsCurrent = _windows;
// set the new default focus:
m_widgetManager.focusSetDefault(_windows);
// display the title of the Windows:
if (m_windowsCurrent != null) {
setTitle(m_windowsCurrent->propertyTitle.get());
}
// request all the widget redrawing
forceRedrawAll();
}
ewol::widget::WindowsShared ewol::Context::getWindows() {
return m_windowsCurrent;
};
void ewol::Context::onResize(const ivec2& _size) {
EWOL_VERBOSE("Resize: " << _size);
forceRedrawAll();
}
void ewol::Context::forceRedrawAll() {
if (m_windowsCurrent == null) {
return;
}
ivec2 size = getSize();
m_windowsCurrent->setSize(vec2(size.x(), size.y()));
m_windowsCurrent->onChangeSize();
}

View File

@ -0,0 +1,159 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <gale/key/key.hpp>
#include <gale/Application.hpp>
#include <gale/context/Context.hpp>
#include <gale/context/clipBoard.hpp>
#include <gale/context/commandLine.hpp>
#include <ewol/debug.hpp>
#include <ewol/ewol.hpp>
#include <ewol/object/Manager.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/widget/Windows.hpp>
#include <ewol/context/Application.hpp>
#include <ewol/context/ConfigFont.hpp>
#include <ewol/context/InputManager.hpp>
#include <ememory/memory.hpp>
namespace ewol {
// Here we hereted from the gale application to be agnostic of the OW where we work ...
class Context : public gale::Application {
private:
ememory::SharedPtr<ewol::context::Application> m_application; //!< Application handle
public:
ememory::SharedPtr<ewol::context::Application> getApplication() {
return m_application;
}
public:
gale::context::CommandLine& getCmd() {
return gale::getContext().getCmd();
};
private:
ewol::context::ConfigFont m_configFont; //!< global font configuration
public:
ewol::context::ConfigFont& getFontDefault() {
return m_configFont;
};
private:
ewol::object::Manager m_objectManager; //!< Object Manager main instance
public:
ewol::object::Manager& getEObjectManager() {
return m_objectManager;
};
private:
ewol::widget::Manager m_widgetManager; //!< global widget manager
public:
ewol::widget::Manager& getWidgetManager() {
return m_widgetManager;
};
public:
gale::resource::Manager& getResourcesManager() {
return gale::getContext().getResourcesManager();
};
public:
Context(ewol::context::Application* _application);
virtual ~Context();
private:
ewol::context::InputManager m_input;
public: // herited function:
void onCreate(gale::Context& _context) override;
void onStart(gale::Context& _context) override;
void onResume(gale::Context& _context) override;
void onRegenerateDisplay(gale::Context& _context) override;
void onDraw(gale::Context& _context) override;
void onPause(gale::Context& _context) override;
void onStop(gale::Context& _context) override;
void onDestroy(gale::Context& _context) override;
void onKillDemand(gale::Context& _context) override;
void onPointer(enum gale::key::type _type,
int32_t _pointerID,
const vec2& _pos,
gale::key::status _state) override;
void onKeyboard(const gale::key::Special& _special,
enum gale::key::keyboard _type,
char32_t _value,
gale::key::status _state) override;
void onClipboardEvent(enum gale::context::clipBoard::clipboardListe _clipboardId) override;
public:
/**
* @brief reset event management for the IO like Input ou Mouse or keyborad
*/
void resetIOEvent();
private:
ewol::widget::WindowsShared m_windowsCurrent; //!< curent displayed windows
public:
/**
* @brief set the current windows to display :
* @param _windows Windows that might be displayed
*/
void setWindows(const ewol::widget::WindowsShared& _windows);
/**
* @brief get the current windows that is displayed
* @return the current handle on the windows (can be null)
*/
ewol::widget::WindowsShared getWindows();
/**
* @brief Redraw all the windows
*/
void forceRedrawAll();
/**
* @brief This is to transfert the event from one widget to another one
* @param source the widget where the event came from
* @param destination the widget where the event mitgh be generated now
*/
void inputEventTransfertWidget(ewol::WidgetShared _source, ewol::WidgetShared _destination);
/**
* @brief This fonction lock the pointer properties to move in relative instead of absolute
* @param[in] widget The widget that lock the pointer events
*/
void inputEventGrabPointer(ewol::WidgetShared _widget);
/**
* @brief This fonction un-lock the pointer properties to move in relative instead of absolute
*/
void inputEventUnGrabPointer();
void onResize(const ivec2& _size) override;
public:
/**
* @brief This is the only one things the User might done in his main();
* @note : must be implemented in all system OPS implementation
* @note To answare you before you ask the question, this is really simple:
* Due to the fect that the current system is multiple-platform, you "main"
* Does not exist in the android platform, then ewol call other start
* and stop function, to permit to have only one code
* @note The main can not be in the ewol, due to the fact thet is an librairy
* @param[in] _argc Standard argc
* @param[in] _argv Standard argv
* @return normal error int for the application error management
*/
static int main(int _argc, const char *_argv[]);
private:
size_t m_initStepId;
size_t m_initTotalStep;
public:
/**
* @brief Special for init (main) set the start image when loading data
* @param[in] _fileName Name of the image to load
*/
void setInitImage(const etk::Uri& _fileName);
public:
/**
* @brief Request a display after call a resize
*/
void requestUpdateSize();
void onPeriod(const echrono::Clock& _time) override;
};
/**
* @brief From everyware in the program, we can get the context inteface.
* @return current reference on the instance.
*/
Context& getContext();
};

View File

@ -0,0 +1,502 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/ewol.hpp>
#include <ewol/object/Object.hpp>
#include <ewol/object/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <ewol/context/InputManager.hpp>
#include <ewol/resource/Texture.hpp>
#include <ewol/widget/Widget.hpp>
#include <ewol/widget/Windows.hpp>
#include <ewol/widget/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::context::InputManager);
#define EVENT_DEBUG EWOL_VERBOSE
//#define EVENT_DEBUG EWOL_DEBUG
void ewol::context::InputManager::calculateLimit() {
m_eventInputLimit.sepatateTime = echrono::Duration(echrono::milliseconds(300));
m_eventInputLimit.DpiOffset = m_dpi*100;
m_eventMouseLimit.sepatateTime = echrono::Duration(echrono::milliseconds(300));
m_eventMouseLimit.DpiOffset = float(m_dpi)*0.1f;
}
void ewol::context::InputManager::setDpi(int32_t newDPI) {
m_dpi = newDPI;
// recalculate the DPI system ...
calculateLimit();
}
bool ewol::context::InputManager::localEventInput(enum gale::key::type _type,
ewol::WidgetShared _destWidget,
int32_t _IdInput,
enum gale::key::status _status,
vec2 _pos) {
if (_destWidget != null) {
if ( _type == gale::key::type::mouse
|| _type == gale::key::type::finger) {
// create the system Event :
ewol::event::InputSystem tmpEventSystem(_type, _status, _IdInput, _pos, _destWidget, 0, m_specialKey); // TODO : set the real ID ...
// generate the event :
return _destWidget->systemEventInput(tmpEventSystem);
} else {
return false;
}
}
return false;
}
void ewol::context::InputManager::abortElement(InputPoperty *_eventTable,
int32_t _idInput,
enum gale::key::type _type) {
if (_eventTable == null) {
return;
}
if (_eventTable[_idInput].isUsed == true) {
localEventInput(_type,
_eventTable[_idInput].curentWidgetEvent.lock(),
_eventTable[_idInput].destinationInputId,
gale::key::status::abort,
_eventTable[_idInput].posEvent);
}
}
void ewol::context::InputManager::cleanElement(InputPoperty *_eventTable,
int32_t _idInput) {
if (_eventTable == null) {
return;
}
//EWOL_INFO("CleanElement[" << idInput << "] = @" << (int64_t)eventTable);
_eventTable[_idInput].isUsed = false;
_eventTable[_idInput].destinationInputId = 0;
_eventTable[_idInput].lastTimeEvent.reset();
_eventTable[_idInput].curentWidgetEvent.reset();
_eventTable[_idInput].origin.setValue(0,0);
_eventTable[_idInput].size.setValue(99999999,99999999);
_eventTable[_idInput].downStart.setValue(0,0);
_eventTable[_idInput].isDown = false;
_eventTable[_idInput].isInside = false;
_eventTable[_idInput].nbClickEvent = 0;
_eventTable[_idInput].posEvent.setValue(0,0);
}
void ewol::context::InputManager::transfertEvent(ewol::WidgetShared _source, ewol::WidgetShared _destination) {
if( _source == null
|| _destination == null) {
// prevent errors ...
return;
}
for(int32_t iii=0; iii<MAX_MANAGE_INPUT; iii++) {
ewol::WidgetShared tmpWidget = m_eventInputSaved[iii].curentWidgetEvent.lock();
if (tmpWidget == _source) {
// inform the widget that it does not receive the event now
EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventInputSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_ABORT] " << m_eventInputSaved[iii].posEvent);
localEventInput(gale::key::type::finger, tmpWidget, m_eventInputSaved[iii].destinationInputId, gale::key::status::abort, m_eventInputSaved[iii].posEvent);
// set the new widget ...
m_eventInputSaved[iii].curentWidgetEvent = _destination;
// inform the widget that he receive the event property now...
EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventInputSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_TRANSFERT] " << m_eventInputSaved[iii].posEvent);
localEventInput(gale::key::type::finger, _destination, m_eventInputSaved[iii].destinationInputId, gale::key::status::transfert, m_eventInputSaved[iii].posEvent);
}
tmpWidget = m_eventMouseSaved[iii].curentWidgetEvent.lock();
if (tmpWidget == _source) {
// inform the widget that it does not receive the event now
EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventMouseSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_ABORT] " << m_eventMouseSaved[iii].posEvent);
localEventInput(gale::key::type::mouse, tmpWidget, m_eventMouseSaved[iii].destinationInputId, gale::key::status::abort, m_eventMouseSaved[iii].posEvent);
// set the new widget ...
m_eventMouseSaved[iii].curentWidgetEvent = _destination;
// inform the widget that he receive the event property now...
EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventMouseSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_TRANSFERT] " << m_eventMouseSaved[iii].posEvent);
localEventInput(gale::key::type::mouse, _destination, m_eventMouseSaved[iii].destinationInputId, gale::key::status::transfert, m_eventMouseSaved[iii].posEvent);
}
}
}
void ewol::context::InputManager::grabPointer(ewol::WidgetShared _widget) {
if(_widget == null) {
return;
}
m_grabWidget = _widget;
/* TODO :
m_context.grabPointerEvents(true, _widget->getOrigin()
+ ivec2(_widget->getSize().x()/2.0f,
_widget->getSize().y()/2.0f) );
*/
}
void ewol::context::InputManager::unGrabPointer() {
m_grabWidget.reset();
// TODO: m_context.grabPointerEvents(false, vec2(0,0));
}
void ewol::context::InputManager::newLayerSet() {
for(int32_t iii=0; iii<MAX_MANAGE_INPUT; iii++) {
// remove the property of this input ...
abortElement(m_eventInputSaved, iii, gale::key::type::finger);
cleanElement(m_eventInputSaved, iii);
abortElement(m_eventMouseSaved, iii, gale::key::type::mouse);
cleanElement(m_eventMouseSaved, iii);
}
}
ewol::context::InputManager::InputManager(ewol::Context& _context) :
m_grabWidget(),
m_context(_context) {
setDpi(200);
EWOL_INFO("Init (start)");
for(int32_t iii=0; iii<MAX_MANAGE_INPUT; iii++) {
// remove the property of this input ...
cleanElement(m_eventInputSaved, iii);
cleanElement(m_eventMouseSaved, iii);
}
EWOL_INFO("Init (end)");
}
ewol::context::InputManager::~InputManager() {
EWOL_INFO("Un-Init (start)");
EWOL_INFO("Un-Init (end)");
}
int32_t ewol::context::InputManager::localGetDestinationId(enum gale::key::type _type,
ewol::WidgetShared _destWidget,
int32_t _realInputId) {
if (_type == gale::key::type::finger) {
int32_t lastMinimum = 0;
for(int32_t iii=0; iii<MAX_MANAGE_INPUT; iii++) {
if (true == m_eventInputSaved[iii].isUsed) {
ewol::WidgetShared tmpWidget = m_eventInputSaved[iii].curentWidgetEvent.lock();
if (tmpWidget == _destWidget) {
if (iii != _realInputId) {
lastMinimum = etk::max(lastMinimum, m_eventInputSaved[iii].destinationInputId);
}
}
}
}
return lastMinimum+1;
}
return _realInputId;
}
// note if id<0 == > the it was finger event ...
void ewol::context::InputManager::motion(enum gale::key::type _type,
int _pointerID,
vec2 _pos) {
EVENT_DEBUG("motion event : " << _type << " " << _pointerID << " " << _pos);
if (MAX_MANAGE_INPUT <= _pointerID) {
// reject pointer == > out of IDs...
return;
}
InputPoperty *eventTable = null;
if (_type == gale::key::type::mouse) {
eventTable = m_eventMouseSaved;
} else if (_type == gale::key::type::finger) {
eventTable = m_eventInputSaved;
} else {
EWOL_ERROR("Unknown type of event");
return;
}
if( _pointerID > MAX_MANAGE_INPUT
|| _pointerID < 0) {
// not manage input
return;
}
ewol::widget::WindowsShared tmpWindows = m_context.getWindows();
// special case for the mouse event 0 that represent the hover event of the system :
if ( _type == gale::key::type::mouse
&& _pointerID == 0) {
// this event is all time on the good widget ... and manage the enter and leave ...
// NOTE : the "layer widget" force us to get the widget at the specific position all the time :
ewol::WidgetShared tmpWidget;
if (m_grabWidget.lock() != null) {
// grab all events ...
tmpWidget = m_grabWidget.lock();
} else {
if (tmpWindows != null) {
tmpWidget = tmpWindows->getWidgetAtPos(_pos);
}
}
if( tmpWidget != eventTable[_pointerID].curentWidgetEvent.lock()
|| ( eventTable[_pointerID].isInside == true
&& ( eventTable[_pointerID].origin.x() > _pos.x()
|| eventTable[_pointerID].origin.y() > _pos.y()
|| (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) < _pos.x()
|| (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) < _pos.y()) ) ) {
eventTable[_pointerID].isInside = false;
EVENT_DEBUG("GUI : Input ID=" << _pointerID << " == >" << eventTable[_pointerID].destinationInputId << " [LEAVE] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
eventTable[_pointerID].curentWidgetEvent.lock(),
eventTable[_pointerID].destinationInputId,
gale::key::status::leave,
_pos);
}
if (eventTable[_pointerID].isInside == false) {
// set the element inside ...
eventTable[_pointerID].isInside = true;
// get destination widget :
eventTable[_pointerID].curentWidgetEvent = tmpWidget;
if (tmpWidget == null) {
eventTable[_pointerID].isInside = false;
} else {
eventTable[_pointerID].origin = tmpWidget->getOrigin();
eventTable[_pointerID].size = tmpWidget->getSize();
}
eventTable[_pointerID].destinationInputId = 0;
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [ENTER] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
tmpWidget,
eventTable[_pointerID].destinationInputId,
gale::key::status::enter,
_pos);
}
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [MOVE] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
tmpWidget,
eventTable[_pointerID].destinationInputId,
gale::key::status::move,
_pos);
} else if (eventTable[_pointerID].isUsed == true) {
if (eventTable[_pointerID].isInside == true) {
if( eventTable[_pointerID].origin.x() > _pos.x()
|| eventTable[_pointerID].origin.y() > _pos.y()
|| (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) < _pos.x()
|| (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) < _pos.y()) {
eventTable[_pointerID].isInside = false;
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [LEAVE] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
eventTable[_pointerID].curentWidgetEvent.lock(),
eventTable[_pointerID].destinationInputId,
gale::key::status::leave,
_pos);
}
} else {
if( ( eventTable[_pointerID].origin.x() <= _pos.x()
&& (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) >= _pos.x() )
&& ( eventTable[_pointerID].origin.y() <= _pos.y()
&& (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) >= _pos.y() ) ) {
eventTable[_pointerID].isInside = true;
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [ENTER] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
eventTable[_pointerID].curentWidgetEvent.lock(),
eventTable[_pointerID].destinationInputId,
gale::key::status::enter,
_pos);
}
}
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [MOVE] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
eventTable[_pointerID].curentWidgetEvent.lock(),
eventTable[_pointerID].destinationInputId,
gale::key::status::move,
_pos);
}
}
void ewol::context::InputManager::state(enum gale::key::type _type,
int _pointerID,
bool _isDown,
vec2 _pos) {
if (_pointerID >= MAX_MANAGE_INPUT) {
// reject pointer == > out of IDs...
return;
}
EVENT_DEBUG("event pointerId=" << _pointerID);
// convert position in open-GL coordonates ...
InputPoperty *eventTable = null;
InputLimit localLimit;
if (_type == gale::key::type::mouse) {
eventTable = m_eventMouseSaved;
localLimit = m_eventMouseLimit;
} else if (_type == gale::key::type::finger) {
eventTable = m_eventInputSaved;
localLimit = m_eventInputLimit;
} else {
EWOL_ERROR("Unknown type of event");
return;
}
if( _pointerID > MAX_MANAGE_INPUT
|| _pointerID <= 0) {
// not manage input
return;
}
// get the curent time ...
echrono::Clock currentTime = echrono::Clock::now();
ewol::widget::WindowsShared tmpWindows = m_context.getWindows();
if (_isDown == true) {
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [DOWN] " << _pos);
if(eventTable[_pointerID].isUsed == true) {
// we have an event previously ... check delay between click and offset position
if (currentTime - eventTable[_pointerID].lastTimeEvent > localLimit.sepatateTime) {
cleanElement(eventTable, _pointerID);
} else if( etk::abs(eventTable[_pointerID].downStart.x() - _pos.x()) >= localLimit.DpiOffset
|| etk::abs(eventTable[_pointerID].downStart.y() - _pos.y()) >= localLimit.DpiOffset ){
cleanElement(eventTable, _pointerID);
}
}
if(eventTable[_pointerID].isUsed == true) {
// save start time
eventTable[_pointerID].lastTimeEvent = currentTime;
// generate DOWN Event
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [DOWN] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
eventTable[_pointerID].curentWidgetEvent.lock(),
eventTable[_pointerID].destinationInputId,
gale::key::status::down,
_pos);
} else {
// Mark it used :
eventTable[_pointerID].isUsed = true;
// Save current position :
eventTable[_pointerID].downStart = _pos;
// save start time
eventTable[_pointerID].lastTimeEvent = currentTime;
// set the element inside ...
eventTable[_pointerID].isInside = true;
ewol::WidgetShared tmpWidget = m_grabWidget.lock();
// get destination widget :
if(tmpWindows != null) {
if ( tmpWidget != null
&& _type == gale::key::type::mouse) {
eventTable[_pointerID].curentWidgetEvent = tmpWidget;
} else {
tmpWidget = tmpWindows->getWidgetAtPos(_pos);
eventTable[_pointerID].curentWidgetEvent = tmpWidget;
if (tmpWidget != null) {
EVENT_DEBUG("Get widget at pos=" << _pos << " type: " << tmpWidget->getObjectType());
} else {
EVENT_DEBUG("Get widget at pos=" << _pos << " NO WIDGET");
}
}
} else {
eventTable[_pointerID].curentWidgetEvent.reset();
}
tmpWidget = eventTable[_pointerID].curentWidgetEvent.lock();
if (tmpWidget != null) {
eventTable[_pointerID].origin = tmpWidget->getOrigin();
eventTable[_pointerID].size = tmpWidget->getSize();
eventTable[_pointerID].destinationInputId = localGetDestinationId(_type, tmpWidget, _pointerID);
} else {
eventTable[_pointerID].destinationInputId = -1;
}
// generate DOWN Event
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [DOWN] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
tmpWidget,
eventTable[_pointerID].destinationInputId,
gale::key::status::down,
_pos);
}
} else {
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [UP] " << _pos);
ewol::WidgetShared tmpWidget = eventTable[_pointerID].curentWidgetEvent.lock();
if(eventTable[_pointerID].isUsed == false) {
// bad case ... ???
EWOL_DEBUG("Up event without previous down ... ");
// Mark it un-used :
eventTable[_pointerID].isUsed = false;
// revove the widget ...
eventTable[_pointerID].curentWidgetEvent.reset();
} else if (tmpWidget == null) {
// The widget has been removed:
EVENT_DEBUG(" Object Removed ...");
// Mark it un-used :
eventTable[_pointerID].isUsed = false;
// revove the widget ...
eventTable[_pointerID].curentWidgetEvent.reset();
} else {
// generate UP Event
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [UP] " << _pos);
eventTable[_pointerID].posEvent = _pos;
// send up event after the single event to prevent multiple widget getting elements
localEventInput(_type,
tmpWidget,
_pointerID,
gale::key::status::up,
_pos);
// generate event (single)
if( etk::abs(eventTable[_pointerID].downStart.x() - _pos.x()) < localLimit.DpiOffset
&& etk::abs(eventTable[_pointerID].downStart.y() - _pos.y()) < localLimit.DpiOffset ){
// Save current position :
eventTable[_pointerID].downStart = _pos;
// save start time
eventTable[_pointerID].lastTimeEvent = currentTime;
int32_t nbClickMax = 0;
if(tmpWidget != null) {
nbClickMax = tmpWidget->getMouseLimit();
if (nbClickMax>5) {
nbClickMax = 5;
}
}
// in grab mode the single to quinte event are not generated ....
if( ( m_grabWidget.lock() == null
|| _type != gale::key::type::mouse )
&& eventTable[_pointerID].nbClickEvent < nbClickMax) {
// generate event SINGLE :
eventTable[_pointerID].nbClickEvent++;
EVENT_DEBUG("GUI : Input ID=" << _pointerID
<< " == >" << eventTable[_pointerID].destinationInputId
<< " [" << eventTable[_pointerID].nbClickEvent << "] " << _pos);
eventTable[_pointerID].posEvent = _pos;
localEventInput(_type,
tmpWidget,
eventTable[_pointerID].destinationInputId,
(enum gale::key::status)(uint32_t(gale::key::status::pressSingle) + eventTable[_pointerID].nbClickEvent-1),
_pos);
if( eventTable[_pointerID].nbClickEvent >= nbClickMax) {
eventTable[_pointerID].nbClickEvent = 0;
}
} else {
eventTable[_pointerID].nbClickEvent = 0;
}
}
// send up event after the single event to prevent multiple widget getting elements
localEventInput(_type,
tmpWidget,
_pointerID,
gale::key::status::upAfter,
_pos);
// specific for tuch event
if (_type == gale::key::type::finger) {
cleanElement(eventTable, _pointerID);
}
}
}
}

View File

@ -0,0 +1,120 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/widget/Widget.hpp>
#define MAX_MANAGE_INPUT (15)
namespace ewol {
namespace context {
/**
* @brief internal structure
* @not_in_doc
*/
class InputPoperty {
public:
bool isUsed;
int32_t destinationInputId;
echrono::Clock lastTimeEvent;
ewol::WidgetWeak curentWidgetEvent;
vec2 origin;
vec2 size;
vec2 downStart;
vec2 posEvent;
bool isDown;
bool isInside;
int32_t nbClickEvent; // 0 .. 1 .. 2 .. 3
};
/**
* @brief internal structure
* @not_in_doc
*/
class InputLimit {
public:
echrono::Duration sepatateTime;
int32_t DpiOffset;
};
class Context;
class InputManager{
// special grab pointer mode :
private:
ewol::WidgetWeak m_grabWidget; //!< widget that grab the curent pointer.
private:
int32_t m_dpi;
InputLimit m_eventInputLimit;
InputLimit m_eventMouseLimit;
void calculateLimit();
InputPoperty m_eventInputSaved[MAX_MANAGE_INPUT];
InputPoperty m_eventMouseSaved[MAX_MANAGE_INPUT];
void abortElement(InputPoperty* _eventTable, int32_t _idInput, enum gale::key::type _type);
void cleanElement(InputPoperty* _eventTable, int32_t _idInput);
/**
* @brief generate the event on the destinated widget.
* @param[in] _type Type of the event that might be sended.
* @param[in] _destWidget Pointer on the requested widget that element might be sended
* @param[in] _IdInput Id of the event (PC : [0..9] and touch : [1..9])
* @param[in] _typeEvent type of the eventg generated
* @param[in] _pos position of the event
* @return true if event has been greped
*/
bool localEventInput(enum gale::key::type _type,
ewol::WidgetShared _destWidget,
int32_t _IdInput,
enum gale::key::status _typeEvent,
vec2 _pos);
/**
* @brief convert the system event id in the correct EWOL id depending of the system management mode
* This function find the next input id unused on the specifiic widget
* == > on PC, the ID does not change (GUI is not the same)
* @param[in] _type Type of the kay event.
* @param[in] _destWidget Pointer of the widget destination
* @param[in] _realInputId system Id
* @return the ewol input id
*/
int32_t localGetDestinationId(enum gale::key::type _type,
ewol::WidgetShared _destWidget,
int32_t _realInputId);
private:
ewol::Context& m_context;
public:
InputManager(ewol::Context& _context);
~InputManager();
void setDpi(int32_t _newDPI);
// note if id<0 == > the it was finger event ...
void motion(enum gale::key::type _type, int _pointerID, vec2 _pos );
void state(enum gale::key::type _type, int _pointerID, bool _isDown, vec2 _pos);
public:
/**
* @brief a new layer on the windows is set == > might remove all the property of the current element ...
*/
void newLayerSet();
/**
* @brief This is to transfert the event from one widget to another one
* @param _source the widget where the event came from
* @param _destination the widget where the event mitgh be generated now
*/
void transfertEvent(ewol::WidgetShared _source, ewol::WidgetShared _destination);
/**
* @brief This fonction lock the pointer properties to move in relative instead of absolute
* @param[in] _widget The widget that lock the pointer events
*/
void grabPointer(ewol::WidgetShared _widget);
/**
* @brief This fonction un-lock the pointer properties to move in relative instead of absolute
*/
void unGrabPointer();
private:
gale::key::Special m_specialKey;
public:
void setLastKeyboardSpecial(const gale::key::Special& _specialKey) {
m_specialKey = _specialKey;
}
};
};
};

View File

@ -0,0 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
int32_t ewol::getLogId() {
static int32_t g_val = elog::registerInstance("ewol");
return g_val;
}

View File

@ -0,0 +1,25 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/widget/Widget.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::event::Entry);
etk::Stream& ewol::event::operator <<(etk::Stream& _os, const ewol::event::Entry& _obj) {
_os << "{type=" << _obj.getType();
_os << " status=" << _obj.getStatus();
if (_obj.getType() == gale::key::keyboard::character) {
_os << " char=" << _obj.getChar();
}
_os << "}";
return _os;
}
etk::Stream& ewol::event::operator <<(etk::Stream& _os, const ewol::event::EntrySystem& _obj) {
_os << _obj.m_event;
return _os;
}

View File

@ -0,0 +1,70 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <gale/key/key.hpp>
namespace ewol {
namespace event {
class Entry {
private:
enum gale::key::keyboard m_type; //!< type of hardware event
enum gale::key::status m_status; //!< status of hardware event
gale::key::Special m_specialKey; //!< input key status (prevent change in time..)
char32_t m_unicodeData; //!< Unicode data (in some case)
public:
Entry(enum gale::key::keyboard _type,
enum gale::key::status _status,
gale::key::Special _specialKey,
char32_t _char) :
m_type(_type),
m_status(_status),
m_specialKey(_specialKey),
m_unicodeData(_char) {
};
void setType(enum gale::key::keyboard _type) {
m_type = _type;
};
inline const enum gale::key::keyboard& getType() const {
return m_type;
};
void setStatus(enum gale::key::status _status) {
m_status = _status;
};
inline const enum gale::key::status& getStatus() const {
return m_status;
};
void setSpecialKey(const gale::key::Special& _specialKey) {
m_specialKey = _specialKey;
};
inline const gale::key::Special& getSpecialKey() const {
return m_specialKey;
};
void setChar(char32_t _char) {
m_unicodeData = _char;
};
inline const char32_t& getChar() const {
return m_unicodeData;
};
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::event::Entry& _obj);
class EntrySystem {
public:
EntrySystem(enum gale::key::keyboard _type,
enum gale::key::status _status,
gale::key::Special _specialKey,
char32_t _char) :
m_event(_type, _status, _specialKey, _char) {
};
ewol::event::Entry m_event;
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::event::EntrySystem& _obj);
};
};

View File

@ -0,0 +1,24 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/widget/Widget.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::event::Input);
etk::Stream& ewol::event::operator <<(etk::Stream& _os, const ewol::event::Input& _obj) {
_os << "{type=" << _obj.getType();
_os << " status=" << _obj.getStatus();
_os << " id=" << etk::toString(_obj.getId());
_os << " pos=" << _obj.getPos();
_os << "}";
return _os;
}
etk::Stream& ewol::event::operator <<(etk::Stream& _os, const ewol::event::InputSystem& _obj) {
_os << _obj.m_event;
return _os;
}

View File

@ -0,0 +1,104 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
namespace ewol {
namespace event {
class Input {
private:
enum gale::key::type m_type;
enum gale::key::status m_status;
uint8_t m_inputId;
vec2 m_pos;
gale::key::Special m_specialKey; //!< input key status (prevent change in time..)
public:
Input(enum gale::key::type _type,
enum gale::key::status _status,
uint8_t _id,
const vec2& _pos,
gale::key::Special _specialKey):
m_type(_type),
m_status(_status),
m_inputId(_id),
m_pos(_pos),
m_specialKey(_specialKey) {
};
void setType(enum gale::key::type _type) {
m_type = _type;
};
inline const enum gale::key::type& getType() const {
return m_type;
};
void setStatus(enum gale::key::status _status) {
m_status = _status;
};
inline const enum gale::key::status& getStatus() const {
return m_status;
};
void setId(uint8_t _id) {
m_inputId = _id;
};
inline const uint8_t& getId() const {
return m_inputId;
};
void setPos(const vec2& _pos) {
m_pos = _pos;
};
inline const vec2& getPos() const {
return m_pos;
};
void setSpecialKey(const gale::key::Special& _specialKey) {
m_specialKey = _specialKey;
};
inline const gale::key::Special& getSpecialKey() const {
return m_specialKey;
};
/**
* @brief Reset the input property of the curent event.
*/
void reset() const {
// TODO : Call the entry element ant rest it ...
}
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::event::Input& _obj);
class InputSystem {
public:
InputSystem(enum gale::key::type _type,
enum gale::key::status _status,
uint8_t _id,
const vec2& _pos,
ewol::WidgetShared _dest,
int32_t _realIdEvent,
gale::key::Special _specialKey) :
m_event(_type, _status, _id, _pos, _specialKey),
m_dest(_dest),
m_realIdEvent(_realIdEvent) { };
ewol::event::Input m_event;
private:
ewol::WidgetShared m_dest;
int32_t m_realIdEvent;
public:
void setDestWidget(ewol::WidgetShared _dest) {
m_dest = _dest;
};
inline ewol::WidgetShared getDestWidget() const {
return m_dest;
};
void setRealId(int32_t _realIdEvent) {
m_realIdEvent = _realIdEvent;
};
inline int32_t getRealId() const {
return m_realIdEvent;
};
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::event::InputSystem& _obj);
};
};

View File

@ -0,0 +1,35 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/widget/Widget.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::event::Time);
etk::Stream& ewol::event::operator <<(etk::Stream& _os, const ewol::event::Time& _obj) {
_os << "{time=" << _obj.getTime();
_os << " uptime=" << _obj.getApplUpTime();
_os << " delta=" << _obj.getDelta();
_os << " deltaCall=" << _obj.getDeltaCall();
_os << "}";
return _os;
}
namespace etk {
template<> etk::String toString<ewol::event::Time>(ewol::event::Time const& _obj) {
etk::String out;
out = "{[ewol::event::Time]time=" + etk::toString(_obj.getTime());
out += ";uptime=" + etk::toString(_obj.getApplUpTime());
out += ";delta=" + etk::toString(_obj.getDelta());
out += ";deltaCall=" + etk::toString(_obj.getDeltaCall());
out += "}";
return out;
}
}
// declare for signal event
#include <esignal/details/Signal.hxx>
ESIGNAL_DECLARE_SIGNAL(ewol::event::Time);

View File

@ -0,0 +1,69 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <echrono/Clock.hpp>
#include <echrono/Duration.hpp>
namespace ewol {
namespace event {
class Time {
private:
echrono::Clock m_timeSystem; //!< Current system time (micro-second)
echrono::Clock m_timeUpAppl; //!< Current application wake up-time (micro-second)
echrono::Duration m_timeDelta; //!< Time from the last cycle call of the system (main appl tick) (second)
echrono::Duration m_timeDeltaCall; //!< Time from the last call (when we can manage periodic call with specifying periode) (second)
public:
Time(const echrono::Clock& _timeSystem,
const echrono::Clock& _timeUpAppl,
const echrono::Duration& _timeDelta,
const echrono::Duration& _timeDeltaCall) :
m_timeSystem(_timeSystem),
m_timeUpAppl(_timeUpAppl),
m_timeDelta(_timeDelta),
m_timeDeltaCall(_timeDeltaCall){
};
public:
void setTime(const echrono::Clock& _timeSystem) {
m_timeSystem = _timeSystem;
};
inline const echrono::Clock& getTime() const {
return m_timeSystem;
};
void setApplWakeUpTime(const echrono::Clock& _timeUpAppl) {
m_timeUpAppl = _timeUpAppl;
};
inline const echrono::Clock& getApplWakeUpTime() const {
return m_timeUpAppl;
};
inline echrono::Duration getApplUpTime() const {
return m_timeSystem-m_timeUpAppl;
};
void setDelta(const echrono::Duration& _timeDelta) {
m_timeDelta = _timeDelta;
};
inline const echrono::Duration& getDeltaDuration() const {
return m_timeDelta;
};
inline float getDelta() const {
return m_timeDelta.toSeconds();
};
void setDeltaCall(const echrono::Duration& _timeDeltaCall) {
m_timeDeltaCall = _timeDeltaCall;
};
inline const echrono::Duration& getDeltaCallDuration() const {
return m_timeDeltaCall;
};
inline float getDeltaCall() const {
return m_timeDeltaCall.toSeconds();
};
};
etk::Stream& operator <<(etk::Stream& _os, const ewol::event::Time& _obj);
}
}

View File

@ -0,0 +1,32 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <gale/gale.hpp>
#include <etranslate/etranslate.hpp>
#include <gale/context/commandLine.hpp>
#include <gale/Dimension.hpp>
#ifndef EWOL_VERSION
#define EWOL_VERSION "0.0.0"
#endif
etk::String ewol::getVersion() {
return EWOL_VERSION;
}
int32_t ewol::run(ewol::context::Application* _application,
int32_t _argc,
const char* _argv[]) {
etranslate::init(_argc, _argv);
return gale::run(ETK_NEW(ewol::Context, _application), _argc, _argv);
}

View File

@ -0,0 +1,30 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/context/Application.hpp>
namespace ewol {
/**
* @brief This is the only one things the User might done in his main();
* @note To answare you before you ask the question, this is really simple:
* Due to the fect that the current system is multiple-platform, you "main"
* Does not exist in the android platform, then ewol call other start
* and stop function, to permit to have only one code
* @note The main can not be in the ewol, due to the fact thet is an librairy
* @param[in] _application just created instance of the applicationo
* @param[in] _argc Standard argc
* @param[in] _argv Standard argv
* @return normal error int for the application error management
*/
int32_t run(ewol::context::Application* _application, int32_t _argc = 0, const char* _argv[] = null);
/**
* @brief get EWOL version
* @return The string that describe ewol version
*/
etk::String getVersion();
};

View File

@ -0,0 +1,86 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/gravity.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(enum ewol::gravity);
etk::String ewol::gravityToString(const enum ewol::gravity _obj) {
switch(_obj) {
case ewol::gravity_center:
return "center";
case ewol::gravity_topLeft:
return "top-left";
case ewol::gravity_top:
return "top";
case ewol::gravity_topRight:
return "top-right";
case ewol::gravity_right:
return "right";
case ewol::gravity_buttomRight:
return "buttom-right";
case ewol::gravity_buttom:
return "buttom";
case ewol::gravity_buttomLeft:
return "buttom-left";
case ewol::gravity_left:
return "left";
}
return "unknow";
}
enum ewol::gravity ewol::stringToGravity(const etk::String& _obj) {
if (_obj == "center") {
return ewol::gravity_center;
} else if (_obj == "top-left") {
return ewol::gravity_topLeft;
} else if (_obj == "top") {
return ewol::gravity_top;
} else if (_obj == "top-right") {
return ewol::gravity_topRight;
} else if (_obj == "right") {
return ewol::gravity_right;
} else if (_obj == "buttom-right") {
return ewol::gravity_buttomRight;
} else if (_obj == "buttom") {
return ewol::gravity_buttom;
} else if (_obj == "buttom-left") {
return ewol::gravity_buttomLeft;
} else if (_obj == "left") {
return ewol::gravity_left;
}
return ewol::gravity_center;
}
vec2 ewol::gravityGenerateDelta(const enum ewol::gravity _gravity, const vec2& _deltas) {
vec2 out(0.0f,0.0f);
if (_deltas.x() > 0.0001f) {
if ((uint32_t(_gravity) & uint32_t(ewol::gravity_left)) != 0) {
// nothing to do
} else if ((uint32_t(_gravity) & uint32_t(ewol::gravity_right)) != 0) {
out = vec2(int32_t(_deltas.x()), 0.0f);
} else {
out = vec2(int32_t(_deltas.x()*0.5f), 0.0f);
}
}
if (_deltas.y() > 0.0001f) {
if ((uint32_t(_gravity) & uint32_t(ewol::gravity_buttom)) != 0) {
// nothing to do
} else if ((uint32_t(_gravity) & uint32_t(ewol::gravity_top)) != 0) {
out += vec2(0.0f, int32_t(_deltas.y()));
} else {
out += vec2(0.0f, int32_t(_deltas.y()*0.5f));
}
}
return out;
}
etk::Stream& ewol::operator <<(etk::Stream& _os, const enum ewol::gravity _obj) {
_os << ewol::gravityToString(_obj);
return _os;
}

View File

@ -0,0 +1,31 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/math/Vector2D.hpp>
namespace ewol {
/**
* @brief Gravity of the widget property
* @not_in_doc
*/
enum gravity {
gravity_center = 0x00, //!< gravity is in center
gravity_top = 0x01, //!< gravity is in top
gravity_buttom = 0x02, //!< gravity is in buttom
gravity_right = 0x04, //!< gravity is in right
gravity_left = 0x08, //!< gravity is in left
gravity_topRight = gravity_top|gravity_right, //!< gravity is in top-right
gravity_topLeft = gravity_top|gravity_left, //!< gravity is in top-left
gravity_buttomRight = gravity_buttom|gravity_right, //!< gravity is in buttom-right
gravity_buttomLeft = gravity_buttom|gravity_left, //!< gravity is in buttom-left
};
etk::Stream& operator <<(etk::Stream& _os, const enum ewol::gravity _obj);
etk::String gravityToString(const enum ewol::gravity _obj);
enum ewol::gravity stringToGravity(const etk::String& _obj);
vec2 gravityGenerateDelta(const enum ewol::gravity _gravity, const vec2& _deltas);
}

View File

@ -0,0 +1,68 @@
package org.atriasoft.ewol.internal;
import io.scenarium.logger.LogLevel;
import io.scenarium.logger.Logger;
class Log {
private static final String LIB_NAME = "ewol";
private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME);
private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL);
private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR);
private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING);
private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO);
private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG);
private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE);
private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO);
private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT);
public static void critical(final String data) {
if (PRINT_CRITICAL) {
Logger.critical(LIB_NAME_DRAW, data);
}
}
public static void debug(final String data) {
if (PRINT_DEBUG) {
Logger.debug(LIB_NAME_DRAW, data);
}
}
public static void error(final String data) {
if (PRINT_ERROR) {
Logger.error(LIB_NAME_DRAW, data);
}
}
public static void info(final String data) {
if (PRINT_INFO) {
Logger.info(LIB_NAME_DRAW, data);
}
}
public static void print(final String data) {
if (PRINT_PRINT) {
Logger.print(LIB_NAME_DRAW, data);
}
}
public static void todo(final String data) {
if (PRINT_TODO) {
Logger.todo(LIB_NAME_DRAW, data);
}
}
public static void verbose(final String data) {
if (PRINT_VERBOSE) {
Logger.verbose(LIB_NAME_DRAW, data);
}
}
public static void warning(final String data) {
if (PRINT_WARNING) {
Logger.warning(LIB_NAME_DRAW, data);
}
}
private Log() {}
}

View File

@ -0,0 +1,161 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/object/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <ewol/ewol.hpp>
#include <etk/stdTools.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::object::Manager);
ewol::object::Manager::Manager(ewol::Context& _context) :
m_context(_context),
periodicCall(this, "periodic", "Call every time system render"),
m_applWakeUpTime(0),
m_lastPeriodicCallTime(0) {
EWOL_DEBUG(" == > init Object-Manager");
periodicCall.setPeriodic(true);
// set the basic time properties :
m_applWakeUpTime = echrono::Clock::now();
m_lastPeriodicCallTime = m_applWakeUpTime;
}
ewol::object::Manager::~Manager() {
ethread::RecursiveLock lock(m_mutex);
m_workerList.clear();
bool hasError = false;
if (m_eObjectList.size()!=0) {
EWOL_ERROR("Must not have anymore eObject !!!");
hasError = true;
}
if (hasError == true) {
EWOL_ERROR("Check if the function UnInit has been called !!!");
}
displayListObject();
}
void ewol::object::Manager::displayListObject() {
ethread::RecursiveLock lock(m_mutex);
EWOL_INFO("List loaded object : ");
for (auto &it : m_eObjectList) {
ewol::ObjectShared element = it.lock();
if (element != null) {
EWOL_INFO(" [" << element->getId() << "] ref=" << element.useCount()-1 << " name='" << element->propertyName.get() << "' type=" << element->getObjectType());
}
}
}
void ewol::object::Manager::unInit() {
ethread::RecursiveLock lock(m_mutex);
EWOL_DEBUG(" == > Un-Init Object-Manager");
if (m_workerList.size() > 0) {
EWOL_DEBUG(" == > Remove all workers");
m_workerList.clear();
}
for (auto &it : m_eObjectList) {
ewol::ObjectShared element = it.lock();
if (element != null) {
//it->removeObject();
}
}
if (m_eObjectList.size() != 0) {
EWOL_ERROR("Have " << m_eObjectList.size() << " active Object");
}
m_eObjectList.clear();
}
void ewol::object::Manager::add(const ewol::ObjectShared& _object) {
ethread::RecursiveLock lock(m_mutex);
if (_object == null) {
EWOL_ERROR("try to add an inexistant Object in manager");
}
m_eObjectList.pushBack(_object);
}
int32_t ewol::object::Manager::getNumberObject() {
ethread::RecursiveLock lock(m_mutex);
return m_eObjectList.size();
}
// clean all Object that request an autoRemove ...
void ewol::object::Manager::cleanInternalRemoved() {
ethread::RecursiveLock lock(m_mutex);
size_t nbObject = m_eObjectList.size();
EWOL_VERBOSE("Clean Object List (if needed) : " << m_eObjectList.size() << " elements");
auto it(m_eObjectList.begin());
while (it != m_eObjectList.end()) {
if (it->expired() == true) {
it = m_eObjectList.erase(it);
} else {
++it;
}
}
if (m_eObjectList.size() != nbObject) {
EWOL_VERBOSE(" remove " << nbObject - m_eObjectList.size() << " deprecated objects");
}
}
ewol::ObjectShared ewol::object::Manager::get(const etk::String& _name) {
ethread::RecursiveLock lock(m_mutex);
if (_name == "") {
return null;
}
for (auto &it : m_eObjectList) {
ewol::ObjectShared element = it.lock();
if ( element != null
&& element->propertyName.get() == _name) {
return element;
}
}
return null;
}
ewol::ObjectShared ewol::object::Manager::getObjectNamed(const etk::String& _name) {
ethread::RecursiveLock lock(m_mutex);
return ewol::object::Manager::get(_name);
}
void ewol::object::Manager::workerAdd(const ewol::ObjectShared& _worker) {
ethread::RecursiveLock lock(m_mutex);
m_workerList.pushBack(_worker);
}
void ewol::object::Manager::workerRemove(const ewol::ObjectShared& _worker) {
ethread::RecursiveLock lock(m_mutex);
auto it(m_workerList.begin());
while (it != m_workerList.end()) {
if (*it == _worker) {
it = m_workerList.erase(it);
} else {
++it;
}
}
}
void ewol::object::Manager::timeCall(const echrono::Clock& _localTime) {
ethread::RecursiveLock lock(m_mutex);
echrono::Clock previousTime = m_lastPeriodicCallTime;
m_lastPeriodicCallTime = _localTime;
if (periodicCall.size() <= 0) {
return;
}
echrono::Duration deltaTime = _localTime - previousTime;
ewol::event::Time myTime(_localTime, m_applWakeUpTime, deltaTime, deltaTime);
periodicCall.emit(myTime);
}
void ewol::object::Manager::timeCallResume(const echrono::Clock& _localTime) {
ethread::RecursiveLock lock(m_mutex);
m_lastPeriodicCallTime = _localTime;
}
bool ewol::object::Manager::timeCallHave() {
ethread::RecursiveLock lock(m_mutex);
return periodicCall.size() > 0;
}

View File

@ -0,0 +1,105 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/object/Object.hpp>
#include <esignal/Signal.hpp>
#include <ewol/event/Time.hpp>
#include <echrono/Steady.hpp>
#include <echrono/Duration.hpp>
#include <ethread/MutexRecursive.hpp>
namespace ewol {
class Context;
namespace object {
class Manager : public esignal::Interface {
protected:
ethread::MutexRecursive m_mutex;
private:
etk::Vector<ewol::ObjectWeak> m_eObjectList; // all widget allocated == > all time increment ... never removed ...
Context& m_context;
public:
Manager(Context& _context);
virtual ~Manager();
/**
* @brief remove all resources (un-init) out of the destructor (due to the system implementation)
*/
void unInit();
/**
* @brief Get the number of loaded object in the system
* @return number of Object
*/
int32_t getNumberObject();
/**
* @brief Display all object Open.
*/
void displayListObject();
private:
//! @not_in_doc
friend class ewol::Object;
/**
* @brief Internal API that used only with Object toi reference itself in the manager.
* @note The manager remove the object when the refecence Low down 1 (last keeper)
* @param[in] _object Reference shared pointer on the object
*/
void add(const ewol::ObjectShared& _object);
public:
/**
* @brief clean the weak pointer list (remove weak_ptr that is remoed)
*/
void cleanInternalRemoved();
/**
* @brief Retrive an Object with his name
* @param[in] _name Name of the Object
* @return Pointer on the finded Object.
*/
ewol::ObjectShared get(const etk::String& _name);
public:
/**
* @brief retrive an object with his name
* @param[in] _name Name of the object
* @return the requested object or null
*/
ewol::ObjectShared getObjectNamed(const etk::String& _name);
private:
etk::Vector<ewol::ObjectShared> m_workerList;
public:
/**
* @brief Add a worker on the system list.
* @param[in] _worker Worker to add in the list.
*/
void workerAdd(const ewol::ObjectShared& _worker);
/**
* @brief Remove a worker on the system list.
* @param[in] _worker Worker to add in the list.
*/
void workerRemove(const ewol::ObjectShared& _worker);
public:
esignal::Signal<ewol::event::Time> periodicCall;
private:
echrono::Clock m_applWakeUpTime; //!< Time of the application initialize
echrono::Clock m_lastPeriodicCallTime; //!< last call time ...
public: // ewol system internal :
/**
* @brief Call every time we can with the current time
* @param[in] _localTime Current system Time.
*/
void timeCall(const echrono::Clock& _localTime);
/**
* @brief If the application is suspended The Ewol Object manager does not know it, just call this to update delta call
* @param[in] _localTime Current system Time.
*/
void timeCallResume(const echrono::Clock& _localTime);
/**
* @breif check if the Interface have some user that request a periodic call
* @return true, have some periodic event...
*/
bool timeCallHave();
};
};
};

View File

@ -0,0 +1,186 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/object/Object.hpp>
#include <ewol/object/Manager.hpp>
#include <ewol/debug.hpp>
#include <ewol/context/Context.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::Object);
size_t ewol::Object::m_valUID = 0;
void ewol::Object::autoDestroy() {
if (m_objectHasBeenInit == false) {
EWOL_WARNING("try to auto destroy inside a constructor");
return;
}
EWOL_VERBOSE("Destroy object: [" << getId() << "] type:" << getObjectType());
ewol::ObjectShared parent = m_parent.lock();
// TODO : set a signal to do this ...
if (parent != null) {
EWOL_VERBOSE("Destroy object: Call parrent");
parent->requestDestroyFromChild(sharedFromThis());
}
//if no parent ==> noting to do ...
m_destroy = true;
}
bool ewol::Object::objectHasBeenCorectlyInit() {
return m_objectHasBeenInit;
}
void ewol::Object::requestDestroyFromChild(const ewol::ObjectShared& _child) {
EWOL_INFO("requestDestroyFromChild(...) is called when an object reference as a parent have a child that request quto-destroy ...");
EWOL_CRITICAL("Call From Child with no effects ==> must implement : requestDestroyFromChild(...)");
}
void ewol::Object::destroy() {
autoDestroy();
}
bool ewol::Object::isDestroyed() const {
return m_destroy;
}
void ewol::Object::setParent(const ewol::ObjectShared& _newParent) {
// TODO : Implement change of parent ...
m_parent = _newParent;
}
void ewol::Object::removeParent() {
m_parent.reset();
}
ewol::Object::Object() :
propertyName(this, "name", "", "Object name, might be a unique reference in all the program"),
m_objectHasBeenInit(false),
m_destroy(false),
m_static(false),
m_isResource(false) {
// note this is nearly atomic ... (but it is enough)
m_uniqueId = m_valUID++;
EWOL_DEBUG("new Object : [" << m_uniqueId << "]");
}
ewol::Object::~Object() {
EWOL_DEBUG("delete Object : [" << m_uniqueId << "] : " << getTypeDescription());
m_uniqueId = -1;
}
void ewol::Object::init() {
getObjectManager().add(sharedFromThis());
//parameterDisplay();
m_objectHasBeenInit = true;
}
const char * const ewol::Object::getObjectType() const {
if (m_listType.size() == 0) {
return "ewol::Object";
}
return m_listType.back();
}
void ewol::Object::addObjectType(const char* _type) {
if (_type == null) {
EWOL_ERROR(" try to add a type with no value...");
return;
}
m_listType.pushBack(_type);
}
etk::String ewol::Object::getTypeDescription() const {
etk::String ret("ewol::Object");
for(auto element : m_listType) {
ret += "|";
ret += element;
}
return ret;
}
bool ewol::Object::isTypeCompatible(const etk::String& _type) const {
if (_type == "ewol::Object") {
return true;
}
for(auto element : m_listType) {
if (_type == element) {
return true;
}
}
return false;
}
bool ewol::Object::loadXMLAttributes(const exml::Element& _node) {
if (_node.exist() == false) {
return false;
}
bool errorOccured = false;
for(const auto it : _node.attributes) {
auto pair = it.getPair();
if (pair.first == "") {
continue;
}
if (properties.set(pair.first, pair.second) == false) {
errorOccured = true;
}
}
return errorOccured;
}
bool ewol::Object::loadXML(const exml::Element& _node) {
return true; //loadXMLAttributes(_node);
}
bool ewol::Object::storeXML(exml::Element& _node) const {
if (_node.exist() == false) {
return false;
}
bool errorOccured = true;
for (auto &it : properties.getAll(true)) {
_node.attributes.set(it.first, it.second);
}
return errorOccured;
}
bool ewol::Object::propertySetOnWidgetNamed(const etk::String& _objectName, const etk::String& _config, const etk::String& _value) {
ewol::ObjectShared object = getObjectManager().get(_objectName);
if (object == null) {
return false;
}
return object->properties.set(_config, _value);
}
ewol::object::Manager& ewol::Object::getObjectManager() {
ewol::object::Manager& tmp = ewol::getContext().getEObjectManager();
return tmp;
}
ewol::Context& ewol::Object::getContext() {
return ewol::getContext();
}
ewol::ObjectShared ewol::Object::getObjectNamed(const etk::String& _objectName) {
return getObjectManager().getObjectNamed(_objectName);
}
ewol::ObjectShared ewol::Object::getSubObjectNamed(const etk::String& _objectName) {
EWOL_VERBOSE("check if name : " << _objectName << " ?= " << propertyName.get());
if (_objectName == propertyName.get()) {
return sharedFromThis();
}
return null;
}
bool ewol::propertySetOnObjectNamed(const etk::String& _objectName, const etk::String& _config, const etk::String& _value) {
ewol::ObjectShared object = ewol::getContext().getEObjectManager().get(_objectName);
if (object == null) {
return false;
}
return object->properties.set(_config, _value);
}

View File

@ -0,0 +1,339 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/Vector.hpp>
#include <exml/exml.hpp>
#include <ethread/Mutex.hpp>
#include <ememory/memory.hpp>
#include <ewol/debug.hpp>
#include <ememory/memory.hpp>
#include <eproperty/Interface.hpp>
#include <eproperty/Value.hpp>
#include <eproperty/Range.hpp>
#include <eproperty/List.hpp>
#include <esignal/Interface.hpp>
namespace ewol {
// some class need to define element befor other ...
class Object;
namespace object {
class Manager;
}
class Context;
}
template<class TYPE_OBJECT> static void baseInit(const ememory::SharedPtr<TYPE_OBJECT>& _object) {
// end of recurtion
return;
}
template<class TYPE_OBJECT, class TYPE_VAL, class ... TYPE> static void baseInit(const ememory::SharedPtr<TYPE_OBJECT>& _object, const etk::String& _name, const TYPE_VAL& _val, TYPE&& ... _all ) {
eproperty::Property* prop(null);
eproperty::PropertyType<TYPE_VAL>* propType(null);
if (_object == null) {
EWOL_ERROR("EMPTY pointer");
return;
}
prop = _object->properties.getRaw(_name);
if (prop == null) {
EWOL_ERROR("property does not exit ... '" << _name << "'");
goto exit_on_error;
}
propType = dynamic_cast<eproperty::PropertyType<TYPE_VAL>*>(prop);
if (propType == null) {
EWOL_ERROR("property does not cast in requested type ... '" << _name << "' require type : " << /*typeid(_val).name()*/ "?TODO?" << "' instead of '" << prop->getType() << "'");
goto exit_on_error;
}
propType->setDirectCheck(_val);
exit_on_error:
baseInit(_object, etk::forward<TYPE>(_all)... );
return;
}
#define UN_DECLARE_FACTORY(className) \
template<class ... EWOL_FACTORY_CREATE_TYPE> static ememory::SharedPtr<className> create(const EWOL_FACTORY_CREATE_TYPE& ... _all) = delete;
#define DECLARE_FACTORY(className) \
template<class ... EWOL_FACTORY_CREATE_TYPE> static ememory::SharedPtr<className> create(const EWOL_FACTORY_CREATE_TYPE& ... _all) { \
ememory::SharedPtr<className> object(ETK_NEW(className)); \
if (object == null) { \
EWOL_ERROR("Factory error"); \
return null; \
} \
baseInit(object, _all... ); \
object->init(); \
if (object->objectHasBeenCorectlyInit() == false) { \
EWOL_CRITICAL("Object Is not correctly init : " << #className ); \
} \
return object; \
} \
static ememory::SharedPtr<className> createXml(const exml::Element& _node) { \
ememory::SharedPtr<className> object(ETK_NEW(className)); \
if (object == null) { \
EWOL_ERROR("Factory error"); \
return null; \
} \
object->loadXMLAttributes(_node); \
object->init(); \
if (object->objectHasBeenCorectlyInit() == false) { \
EWOL_CRITICAL("Object Is not correctly init : " << #className ); \
} \
return object; \
}
#define DECLARE_SINGLE_FACTORY(className, uniqueName) \
template<class ... EWOL_FACTORY_CREATE_TYPE> static ememory::SharedPtr<className> create(const EWOL_FACTORY_CREATE_TYPE& ... _all) { \
ememory::SharedPtr<className> object; \
ememory::SharedPtr<ewol::Object> object2 = getObjectNamed(uniqueName); \
if (object2 != null) { \
object = ememory::dynamicPointerCast<className>(object2); \
if (object == null) { \
EWOL_CRITICAL("Request object element: '" << uniqueName << "' With the wrong type (dynamic cast error)"); \
return null; \
} \
} \
if (object != null) { \
return object; \
} \
object = ememory::SharedPtr<className>(ETK_NEW(className)); \
if (object == null) { \
EWOL_ERROR("Factory error"); \
return null; \
} \
baseInit(object, "name", etk::String(uniqueName), _all... ); \
object->init(); \
if (object->objectHasBeenCorectlyInit() == false) { \
EWOL_CRITICAL("Object Is not correctly init : " << #className ); \
} \
return object; \
}
namespace ewol {
using ObjectShared = ememory::SharedPtr<ewol::Object>;
using ObjectWeak = ememory::WeakPtr<ewol::Object>;
/**
* @brief Basic message classes for ewol system
* this class mermit at every Object to communicate between them.
*/
class Object : public ememory::EnableSharedFromThis<Object>,
public eproperty::Interface,
public esignal::Interface {
public: // Event list
public: // propertie list
eproperty::Value<etk::String> propertyName; //!< name of the element ...
private:
static size_t m_valUID; //!< Static used for the unique ID definition
private:
bool m_objectHasBeenInit; //!< Know if the init function has bben called
public:
/**
* @brief Destructor
*/
virtual ~Object();
protected:
/**
* @brief Constructor.
*/
Object();
virtual void init();
public:
/**
* @brief Factory
*/
DECLARE_FACTORY(Object);
bool objectHasBeenCorectlyInit();
protected:
ewol::ObjectWeak m_parent; //!< Reference on the current parrent.
bool m_destroy; //!< Flag to know if the object is requesting has destroy.
protected:
/**
* @brief Auto-destroy the object
*/
virtual void autoDestroy();
public:
/**
* @brief Destroy the current object
*/
virtual void destroy();
/**
* @brief Check if the current objetc his destroy (in removing)
* @return true The object is removed
* @return false The object is not removed
*/
bool isDestroyed() const;
protected:
/**
* @brief Called by a whild that want to remove pointer of itself from the current list of his parrent
* @param[in] _child Object of the child that want to remove itself
*/
virtual void requestDestroyFromChild(const ewol::ObjectShared& _child);
public:
/**
* @brief Set the Object has new parrent.
* @param[in] _newParent Object that requesting the parenting
*/
virtual void setParent(const ewol::ObjectShared& _newParent);
/**
* @brief Remove the current parenting.
*/
virtual void removeParent();
private:
etk::Vector<const char*> m_listType;
public:
/**
* @brief get the current Object type of the Object
* @return the last type name of the element
*/
const char * const getObjectType() const;
/**
* @brief Get the herarchie of the Object type.
* @return descriptive string.
*/
etk::String getTypeDescription() const;
/**
* @brief check if the element herited from a specific type
* @param[in] _type Type to check.
* @return true if the element is compatible.
*/
bool isTypeCompatible(const etk::String& _type) const;
protected:
/**
* @brief Add a type of the list of Object.
* @param[in] _type new type to add.
*/
void addObjectType(const char* _type);
protected:
bool m_static; //!< set this variable at true if this element must not be auto destroy (exemple : use static object)
public:
/**
* @brief get the static status of the Object == > mark at true if the user set the object mark as static allocated element ==> not auto remove element
* @return true if it might not be removed == > usefull for conficuration class
*/
bool getStatic(){
return m_static;
};
private:
int32_t m_uniqueId; //!< Object UniqueID == > TODO : Check if it use is needed
public:
/**
* @brief get the UniqueId of the Object
* @return the requested ID
*/
int32_t getId(){
return m_uniqueId;
};
public:
// TODO : Rework the position on this function ... This is a convignent function ...
bool propertySetOnWidgetNamed(const etk::String& _objectName, const etk::String& _config, const etk::String& _value);
public:
/**
* @brief load attribute properties with an XML node.
* @param[in] _node Reference on the XML node.
* @return true : All has been done corectly.
* @return false : An error occured.
*/
bool loadXMLAttributes(const exml::Element& _node);
/**
* @brief load properties with an XML node.
* @param[in] _node Reference on the XML node.
* @return true : All has been done corectly.
* @return false : An error occured.
*/
virtual bool loadXML(const exml::Element& _node);
/**
* @brief store properties in this XML node.
* @param[in,out] _node Reference on the XML node.
* @return true : All has been done corectly.
* @return false : An error occured.
*/
virtual bool storeXML(exml::Element& _node) const;
public:
/**
* @breif get the current Object manager.
* @return the requested object manager.
*/
static ewol::object::Manager& getObjectManager();
/**
* @brief get the curent the system inteface.
* @return current reference on the instance.
*/
static ewol::Context& getContext();
private:
bool m_isResource; //!< enable this when you want to declare this element is auto-remove
public:
/**
* @brief Declare this element as a resource (or singleton) this mean the element will
* not be auto Remove at the end of the programm. It just notify that it is not removed.
* @param[in] _val Value of the type of the element.
*/
void setStatusResource(bool _val) {
m_isResource = _val;
}
/**
* @brief Get the resource status of the element.
* @return the resource status.
*/
bool getStatusResource() const {
return m_isResource;
}
/**
* @brief Retrive an object with his name (in the global list)
* @param[in] _name Name of the object
* @return the requested object or null
*/
static ewol::ObjectShared getObjectNamed(const etk::String& _objectName);
/**
* @brief Retrive an object with his name (in the global list)
* @param[in] _name Name of the object
* @return the requested object or null
*/
virtual ewol::ObjectShared getSubObjectNamed(const etk::String& _objectName);
protected:
// TODO : Create a template ...
/**
* @brief link on an signal in the subwiget with his name
*/
#define subBind(_type, _name, _event, _shared_ptr, _func, ...) do {\
ememory::SharedPtr<_type> myObject = ememory::dynamicPointerCast<_type>(getSubObjectNamed(_name)); \
if (myObject != null) { \
myObject->_event.connect(_shared_ptr, _func, ##__VA_ARGS__); \
} else { \
EWOL_ERROR("object named='" << _name << "' not exit or can not be cast in : " << #_type); \
} \
} while (false)
};
bool propertySetOnObjectNamed(const etk::String& _objectName, const etk::String& _config, const etk::String& _value);
};
/**
* @brief link on an signal in the global object list with his name
*/
#define globalBind(_type, _name, _event, _obj, _func, ...) do {\
ememory::SharedPtr<_type> myObject = ememory::dynamicPointerCast<_type>(ewol::getContext().getEObjectManager().getObjectNamed(_name)); \
if (myObject != null) { \
myObject->_event.connect(_obj, _func, ##__VA_ARGS__); \
} else { \
EWOL_ERROR("object named='" << _name << "' not exit or can not be cast in : " << #_type); \
} \
} while (false)
/**
* @brief link on an signal in the subWidget of an object with his name
*/
#define externSubBind(_object, _type, _name, _event, _obj, _func, ...) do {\
ememory::SharedPtr<_type> myObject = ememory::dynamicPointerCast<_type>(_object->getObjectNamed(_name)); \
if (myObject != null) { \
myObject->_event.connect(_obj, _func, ##__VA_ARGS__); \
} else { \
EWOL_ERROR("object named='" << _name << "' not exit or can not be cast in : " << #_type); \
} \
} while (false)

View File

@ -0,0 +1,29 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/debug.hpp>
#include <ewol/object/Worker.hpp>
#include <ewol/object/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::object::Worker);
ewol::object::Worker::Worker() {
addObjectType("ewol::Worker");
}
void ewol::object::Worker::init() {
ewol::Object::init();
getObjectManager().workerAdd(sharedFromThis());
}
ewol::object::Worker::~Worker() {
// nothing to do ...
}
void ewol::object::Worker::destroy() {
ewol::Object::destroy();
getObjectManager().workerRemove(sharedFromThis());
}

View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/debug.hpp>
#include <ewol/object/Object.hpp>
namespace ewol {
namespace object {
class Worker;
using WorkerShared = ememory::SharedPtr<ewol::object::Worker>;
using WorkerWeak = ememory::WeakPtr<ewol::object::Worker>;
/**
* @brief A worker might not been possesed by someone, then the system might keep a pointer on it.
*/
class Worker : public ewol::Object {
protected:
/**
* @brief Constructor.
*/
Worker();
void init() override;
public:
/**
* @brief Factory
*/
DECLARE_FACTORY(Worker);
/**
* @brief Destructor
*/
virtual ~Worker();
public:
void destroy() override;
};
}
}

View File

@ -0,0 +1,86 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/uri/uri.hpp>
#include <ewol/debug.hpp>
#include <ewol/resource/ColorFile.hpp>
#include <ejson/ejson.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::ColorFile);
ewol::resource::ColorFile::ColorFile() :
gale::Resource(),
// Set the list unodered
m_list(0, false),
m_errorColor(etk::color::orange) {
addResourceType("ewol::ColorFile");
}
void ewol::resource::ColorFile::init(const etk::Uri& _uri) {
ethread::RecursiveLock lock(m_mutex);
gale::Resource::init(_uri.get());
EWOL_DEBUG("CF : load \"" << _uri << "\"");
reload();
EWOL_DEBUG("List of all color : " << m_list.getKeys());
}
ewol::resource::ColorFile::~ColorFile() {
// remove all element
m_list.clear();
}
void ewol::resource::ColorFile::reload() {
ethread::RecursiveLock lock(m_mutex);
// remove all previous set of value :
for (size_t iii = 0; iii < m_list.size() ; ++iii) {
m_list.getValue(iii) = m_errorColor;
}
// open and read all json elements:
ejson::Document doc;
if (doc.load(etk::Uri(m_name)) == false) {
EWOL_ERROR("Can not load file : '" << m_name << "'");
return;
}
ejson::Array baseArray = doc["color"].toArray();
if (baseArray.exist() == false) {
EWOL_ERROR("Can not get basic array : 'color' in file:" << m_name);
doc.display();
return;
}
bool findError = false;
for (const auto it : baseArray) {
ejson::Object tmpObj = it.toObject();
if (tmpObj.exist() == false) {
EWOL_ERROR(" can not get object in 'color' : " << it);
findError = true;
continue;
}
etk::String name = tmpObj["name"].toString().get();
etk::String color = tmpObj["color"].toString().get(m_errorColor.getHexString());
EWOL_DEBUG("find new color : '" << name << "' color='" << color << "'");
if (name.size() == 0) {
EWOL_ERROR("Drop an empty name");
findError = true;
continue;
}
m_list.add(name, etk::Color<float>(color));
}
if (findError == true) {
EWOL_ERROR("pb in parsing file:" << m_name);
doc.display();
}
}
int32_t ewol::resource::ColorFile::request(const etk::String& _paramName) {
ethread::RecursiveLock lock(m_mutex);
// check if the parameters existed :
if (m_list.exist(_paramName) == false) {
m_list.add(_paramName, m_errorColor);
}
return m_list.getId(_paramName);
}

View File

@ -0,0 +1,73 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/Color.hpp>
#include <etk/Map.hpp>
#include <ewol/debug.hpp>
#include <gale/resource/Resource.hpp>
namespace ewol {
namespace resource {
/**
* @brief ColorFile is a Resource designed to be specific with the theme (for example black, or white or orange ...)
*/
class ColorFile : public gale::Resource {
private:
etk::Map<etk::String, etk::Color<float> > m_list; //!< List of all color in the file
etk::Color<float> m_errorColor; //!< Error returned color
protected:
/**
* @brief Constructor of the color property file
* @param[in] _uri Name of the file needed
*/
ColorFile();
void init(const etk::Uri& _uri);
public:
DECLARE_RESOURCE_URI_FACTORY(ColorFile);
/**
* @brief Simple Destructor of this class (nothing specific ...)
*/
virtual ~ColorFile();
public:
/**
* @brief Set the error color.
* @param[in] _errorColor Color that might be set when not finding a color
*/
void setErrorColor(const etk::Color<float>& _errorColor) {
m_errorColor = _errorColor;
}
/**
* @brief Request the presence of a specific color.
* @param[in] _paramName Name of the color.
* @return A unique ID of the color (or -1 if an error occured).
*/
int32_t request(const etk::String& _paramName);
/**
* @brief Get the associated color of the ID.
* @param[in] _Id Id of the color.
* @return The requested color.
*/
const etk::Color<float>& get(int32_t _id) const {
if (_id < 0) {
return m_errorColor;
}
return m_list.getValue(_id);
};
/**
* @brief Get All color name
* @return list of all color existing
*/
etk::Vector<etk::String> getColors() const {
return m_list.getKeys();
}
public: // herited function:
void reload();
};
};
};

View File

@ -0,0 +1,527 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#ifndef __TARGET_OS__Web
#include <ewol/debug.hpp>
#include <ewol/resource/Colored3DObject.hpp>
#include <gale/resource/Manager.hpp>
#include <gale/renderer/openGL/openGL-include.hpp>
#include <esignal/Signal.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::Colored3DObject);
ewol::resource::Colored3DObject::Colored3DObject() :
m_GLprogram(null) {
addResourceType("ewol::Colored3DObject");
}
void ewol::resource::Colored3DObject::init() {
gale::Resource::init();
// get the shader resource :
m_GLPosition = 0;
m_GLprogram = gale::resource::Program::create("DATA:///simple3D.prog?lib=ewol");
if (m_GLprogram != null) {
m_GLPosition = m_GLprogram->getAttribute("EW_coord3d");
m_GLColor = m_GLprogram->getUniform("EW_color");
m_GLMatrix = m_GLprogram->getUniform("EW_MatrixTransformation");
}
}
ewol::resource::Colored3DObject::~Colored3DObject() {
}
void ewol::resource::Colored3DObject::draw(const etk::Vector<vec3>& _vertices,
const etk::Color<float>& _color,
bool _updateDepthBuffer,
bool _depthtest) {
if (_vertices.size() <= 0) {
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
if (true == _depthtest) {
gale::openGL::enable(gale::openGL::flag_depthTest);
if (false == _updateDepthBuffer) {
glDepthMask(GL_FALSE);
}
}
//EWOL_DEBUG(" display " << m_coord.size() << " elements" );
m_GLprogram->use();
// set Matrix: translation/positionMatrix
mat4 projMatrix = gale::openGL::getMatrix();
mat4 camMatrix = gale::openGL::getCameraMatrix();
mat4 tmpMatrix = projMatrix * camMatrix;
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// position :
m_GLprogram->sendAttribute(m_GLPosition, 3/*x,y,z,unused*/, &_vertices[0], 4*sizeof(float));
// color :
m_GLprogram->uniform4fv(m_GLColor, 1/*r,g,b,a*/, (float*)&_color);
// Request the draw od the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, _vertices.size());
m_GLprogram->unUse();
// Request the draw od the elements:
//glDrawArrays(GL_LINES, 0, vertices.size());
//m_GLprogram->UnUse();
if (true == _depthtest) {
if (false == _updateDepthBuffer) {
glDepthMask(GL_TRUE);
}
gale::openGL::disable(gale::openGL::flag_depthTest);
}
}
void ewol::resource::Colored3DObject::draw(const etk::Vector<vec3>& _vertices,
const etk::Color<float>& _color,
mat4& _transformationMatrix,
bool _updateDepthBuffer,
bool _depthtest) {
if (_vertices.size() <= 0) {
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
if (true == _depthtest) {
gale::openGL::enable(gale::openGL::flag_depthTest);
if (false == _updateDepthBuffer) {
glDepthMask(GL_FALSE);
}
}
//EWOL_DEBUG(" display " << m_coord.size() << " elements" );
m_GLprogram->use();
// set Matrix: translation/positionMatrix
mat4 projMatrix = gale::openGL::getMatrix();
mat4 camMatrix = gale::openGL::getCameraMatrix();
mat4 tmpMatrix = projMatrix * camMatrix * _transformationMatrix;
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// position :
m_GLprogram->sendAttribute(m_GLPosition, 3/*x,y,z*/, &_vertices[0], 4*sizeof(float));
// color :
m_GLprogram->uniform4fv(m_GLColor, 1/*r,g,b,a*/, (float*)&_color);
// Request the draw od the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, _vertices.size());
m_GLprogram->unUse();
if (true == _depthtest) {
if (false == _updateDepthBuffer) {
glDepthMask(GL_TRUE);
}
gale::openGL::disable(gale::openGL::flag_depthTest);
}
}
void ewol::resource::Colored3DObject::drawLine(etk::Vector<vec3>& _vertices,
const etk::Color<float>& _color,
mat4& _transformationMatrix,
bool _updateDepthBuffer,
bool _depthtest) {
if (_vertices.size() <= 0) {
return;
}
if (m_GLprogram == null) {
EWOL_ERROR("No shader ...");
return;
}
if (true == _depthtest) {
gale::openGL::enable(gale::openGL::flag_depthTest);
if (false == _updateDepthBuffer) {
glDepthMask(GL_FALSE);
}
}
//EWOL_DEBUG(" display " << m_coord.size() << " elements" );
m_GLprogram->use();
// set Matrix: translation/positionMatrix
mat4 projMatrix = gale::openGL::getMatrix();
mat4 camMatrix = gale::openGL::getCameraMatrix();
mat4 tmpMatrix = projMatrix * camMatrix * _transformationMatrix;
m_GLprogram->uniformMatrix(m_GLMatrix, tmpMatrix);
// position :
m_GLprogram->sendAttribute(m_GLPosition, 3/*x,y,z*/, &_vertices[0], 4*sizeof(float));
// color :
m_GLprogram->uniform4fv(m_GLColor, 1/*r,g,b,a*/, (float*)&_color);
// Request the draw od the elements:
gale::openGL::drawArrays(gale::openGL::renderMode::line, 0, _vertices.size());
m_GLprogram->unUse();
if (true == _depthtest) {
if (false == _updateDepthBuffer) {
glDepthMask(GL_TRUE);
}
gale::openGL::disable(gale::openGL::flag_depthTest);
}
}
void ewol::resource::Colored3DObject::drawCubeLine(const vec3& _min,
const vec3& _max,
const etk::Color<float>& _color,
mat4& _transformationMatrix,
bool _updateDepthBuffer,
bool _depthtest) {
etk::Vector<vec3> vertices;
vertices.pushBack(vec3(_min.x(), _min.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _min.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _min.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _min.y(),_max.z()));
vertices.pushBack(vec3(_max.x(), _min.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _min.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _min.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _min.y(),_min.z()));
vertices.pushBack(vec3(_min.x(), _max.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _max.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _max.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _max.y(),_max.z()));
vertices.pushBack(vec3(_max.x(), _max.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _max.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _max.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _max.y(),_min.z()));
vertices.pushBack(vec3(_min.x(), _min.y(),_min.z()));
vertices.pushBack(vec3(_min.x(), _max.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _min.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _max.y(),_min.z()));
vertices.pushBack(vec3(_max.x(), _min.y(),_max.z()));
vertices.pushBack(vec3(_max.x(), _max.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _min.y(),_max.z()));
vertices.pushBack(vec3(_min.x(), _max.y(),_max.z()));
drawLine(vertices, _color, _transformationMatrix, _updateDepthBuffer, _depthtest);
}
void ewol::resource::Colored3DObject::drawSquare(const vec3& _size,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor) {
etk::Vector<vec3> tmpVertices;
static int indices[36] = { 0,1,2, 3,2,1, 4,0,6,
6,0,2, 5,1,4, 4,1,0,
7,3,1, 7,1,5, 5,4,7,
7,4,6, 7,2,3, 7,6,2};
vec3 vertices[8]={ vec3(_size[0],_size[1],_size[2]),
vec3(-_size[0],_size[1],_size[2]),
vec3(_size[0],-_size[1],_size[2]),
vec3(-_size[0],-_size[1],_size[2]),
vec3(_size[0],_size[1],-_size[2]),
vec3(-_size[0],_size[1],-_size[2]),
vec3(_size[0],-_size[1],-_size[2]),
vec3(-_size[0],-_size[1],-_size[2])};
tmpVertices.clear();
for (int32_t iii=0 ; iii<36 ; iii+=3) {
// normal calculation :
//btVector3 normal = (vertices[indices[iii+2]]-vertices[indices[iii]]).cross(vertices[indices[iii+1]]-vertices[indices[iii]]);
//normal.normalize ();
tmpVertices.pushBack(vertices[indices[iii]]);
tmpVertices.pushBack(vertices[indices[iii+1]]);
tmpVertices.pushBack(vertices[indices[iii+2]]);
}
draw(tmpVertices, _tmpColor, _transformationMatrix);
}
void ewol::resource::Colored3DObject::drawSphere(float _radius,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor) {
etk::Vector<vec3> tmpVertices;
for(int32_t iii=0; iii<=_lats; ++iii) {
float lat0 = M_PI * (-0.5f + float(iii - 1) / _lats);
float z0 = _radius*sin(lat0);
float zr0 = _radius*cos(lat0);
float lat1 = M_PI * (-0.5f + float(iii) / _lats);
float z1 = _radius*sin(lat1);
float zr1 = _radius*cos(lat1);
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float x = cos(lng);
float y = sin(lng);
vec3 v1 = vec3(x * zr1, y * zr1, z1);
vec3 v4 = vec3(x * zr0, y * zr0, z0);
lng = 2 * M_PI * float(jjj) / _longs;
x = cos(lng);
y = sin(lng);
vec3 v2 = vec3(x * zr1, y * zr1, z1);
vec3 v3 = vec3(x * zr0, y * zr0, z0);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v4);
}
}
draw(tmpVertices, _tmpColor, _transformationMatrix);
}
void ewol::resource::Colored3DObject::drawCylinder(float _radius,
float _size,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor) {
etk::Vector<vec3> tmpVertices;
// center to border (TOP)
// center to border (TOP)
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float z = _size*0.5f;
vec3 v1 = vec3(0.0f, 0.0f, z);
float x = cos(lng)*_radius;
float y = sin(lng)*_radius;
vec3 v2 = vec3(x, y, z);
lng = 2.0f * M_PI * float(jjj) / _longs;
x = cos(lng)*_radius;
y = sin(lng)*_radius;
vec3 v3 = vec3(x, y, z);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v2);
}
// Cylinder
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float z = _size*0.5f;
float x = cos(lng)*_radius;
float y = sin(lng)*_radius;
vec3 v2 = vec3(x, y, z);
vec3 v2b = vec3(x, y, -z);
lng = 2.0f * M_PI * float(jjj) / _longs;
x = cos(lng)*_radius;
y = sin(lng)*_radius;
vec3 v3 = vec3(x, y, z);
vec3 v3b = vec3(x, y, -z);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v3b);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3b);
tmpVertices.pushBack(v2b);
}
// center to border (BUTTOM)
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float z = _size*-0.5f;
vec3 v1 = vec3(0.0f, 0.0f, z);
float x = cos(lng)*_radius;
float y = sin(lng)*_radius;
vec3 v2 = vec3(x, y, z);
lng = 2.0f * M_PI * float(jjj) / _longs;
x = cos(lng)*_radius;
y = sin(lng)*_radius;
vec3 v3 = vec3(x, y, z);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
}
draw(tmpVertices, _tmpColor, _transformationMatrix);
}
void ewol::resource::Colored3DObject::drawCapsule(float _radius,
float _size,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor) {
etk::Vector<vec3> tmpVertices;
_lats = int32_t(_lats / 2)*2;
// center to border (TOP)
float offset = _size*0.5f;
for(int32_t iii=_lats/2+1; iii<=_lats; ++iii) {
float lat0 = M_PI * (-0.5f + float(iii - 1) / _lats);
float z0 = _radius*sin(lat0);
float zr0 = _radius*cos(lat0);
float lat1 = M_PI * (-0.5f + float(iii) / _lats);
float z1 = _radius*sin(lat1);
float zr1 = _radius*cos(lat1);
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float x = cos(lng);
float y = sin(lng);
vec3 v1 = vec3(x * zr1, y * zr1, z1+offset);
vec3 v4 = vec3(x * zr0, y * zr0, z0+offset);
lng = 2 * M_PI * float(jjj) / _longs;
x = cos(lng);
y = sin(lng);
vec3 v2 = vec3(x * zr1, y * zr1, z1+offset);
vec3 v3 = vec3(x * zr0, y * zr0, z0+offset);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v4);
}
}
// Cylinder
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float z = _size*0.5f;
float x = cos(lng)*_radius;
float y = sin(lng)*_radius;
vec3 v2 = vec3(x, y, z);
vec3 v2b = vec3(x, y, -z);
lng = 2.0f * M_PI * float(jjj) / _longs;
x = cos(lng)*_radius;
y = sin(lng)*_radius;
vec3 v3 = vec3(x, y, z);
vec3 v3b = vec3(x, y, -z);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v3b);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3b);
tmpVertices.pushBack(v2b);
}
// center to border (BUTTOM)
offset = -_size*0.5f;
for(int32_t iii=0; iii<=_lats/2; ++iii) {
float lat0 = M_PI * (-0.5f + float(iii - 1) / _lats);
float z0 = _radius*sin(lat0);
float zr0 = _radius*cos(lat0);
float lat1 = M_PI * (-0.5f + float(iii) / _lats);
float z1 = _radius*sin(lat1);
float zr1 = _radius*cos(lat1);
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
float x = cos(lng);
float y = sin(lng);
vec3 v1 = vec3(x * zr1, y * zr1, z1+offset);
vec3 v4 = vec3(x * zr0, y * zr0, z0+offset);
lng = 2 * M_PI * float(jjj) / _longs;
x = cos(lng);
y = sin(lng);
vec3 v2 = vec3(x * zr1, y * zr1, z1+offset);
vec3 v3 = vec3(x * zr0, y * zr0, z0+offset);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v4);
}
}
draw(tmpVertices, _tmpColor, _transformationMatrix);
}
void ewol::resource::Colored3DObject::drawCone(float _radius,
float _size,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor) {
etk::Vector<vec3> tmpVertices;
// center to border (TOP)
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
vec3 v1 = vec3(0.0f, 0.0f, -_size/2);
float x = cos(lng)*_radius;
float y = sin(lng)*_radius;
vec3 v2 = vec3(x, y, _size/2);
lng = 2.0f * M_PI * float(jjj) / _longs;
x = cos(lng)*_radius;
y = sin(lng)*_radius;
vec3 v3 = vec3(x, y, _size/2);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v3);
tmpVertices.pushBack(v2);
}
// center to border (BUTTOM)
for(int32_t jjj=0; jjj<_longs; ++jjj) {
float lng = 2.0f * M_PI * float(jjj - 1) / _longs;
vec3 v1 = vec3(0.0f, 0.0f, _size/2);
float x = cos(lng)*_radius;
float y = sin(lng)*_radius;
vec3 v2 = vec3(x, y, _size/2);
lng = 2.0f * M_PI * float(jjj) / _longs;
x = cos(lng)*_radius;
y = sin(lng)*_radius;
vec3 v3 = vec3(x, y, _size/2);
tmpVertices.pushBack(v1);
tmpVertices.pushBack(v2);
tmpVertices.pushBack(v3);
}
draw(tmpVertices, _tmpColor, _transformationMatrix);
}
void ewol::resource::Colored3DObject::drawTriangles(const etk::Vector<vec3>& _vertex,
const etk::Vector<uint32_t>& _indice,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor,
const vec3& _offset) {
etk::Vector<vec3> tmpVertices;
for (size_t iii=0; iii<_indice.size()/3; ++iii) {
tmpVertices.pushBack(_vertex[_indice[iii*3 + 0]]+_offset);
tmpVertices.pushBack(_vertex[_indice[iii*3 + 1]]+_offset);
tmpVertices.pushBack(_vertex[_indice[iii*3 + 2]]+_offset);
//EWOL_INFO(" indices " << _indice[iii*3 + 0] << " " << _indice[iii*3 + 1] << " " << _indice[iii*3 + 2]);
//EWOL_INFO(" triangle " << _vertex[_indice[iii*3 + 0]] << " " << _vertex[_indice[iii*3 + 1]] << " " << _vertex[_indice[iii*3 + 2]]);
}
//EWOL_INFO("display " << tmpVertices.size() << " vertices form " << _indice.size());
draw(tmpVertices, _tmpColor, _transformationMatrix);
}
namespace etk {
template<> etk::String toString(ewol::resource::Colored3DObject const&) {
return "!!ewol::resource::Colored3DObject!ERROR!CAN_NOT_BE_CONVERT!!";
}
}
#include <esignal/details/Signal.hxx>
// declare for signal event
ESIGNAL_DECLARE_SIGNAL(ewol::resource::Colored3DObject);
ESIGNAL_DECLARE_SIGNAL(ememory::SharedPtr<ewol::resource::Colored3DObject>);
#endif

View File

@ -0,0 +1,89 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#ifndef __TARGET_OS__Web
#include <etk/types.hpp>
#include <gale/resource/Resource.hpp>
#include <ewol/resource/TextureFile.hpp>
#include <gale/resource/Program.hpp>
namespace ewol {
namespace resource {
/**
* @brief simple display of Colored3DObject ==> for DEBUG only Not availlable on ALL platform (like webGL)
*/
class Colored3DObject : public gale::Resource {
protected:
ememory::SharedPtr<gale::resource::Program> m_GLprogram;
int32_t m_GLPosition;
int32_t m_GLMatrix;
int32_t m_GLColor;
protected:
Colored3DObject();
void init();
public:
DECLARE_RESOURCE_FACTORY(Colored3DObject);
virtual ~Colored3DObject();
public:
virtual void draw(const etk::Vector<vec3>& _vertices,
const etk::Color<float>& _color,
bool _updateDepthBuffer=true,
bool _depthtest=true);
virtual void draw(const etk::Vector<vec3>& _vertices,
const etk::Color<float>& _color,
mat4& _transformationMatrix,
bool _updateDepthBuffer=true,
bool _depthtest=true);
virtual void drawLine(etk::Vector<vec3>& _vertices,
const etk::Color<float>& _color,
mat4& _transformationMatrix,
bool _updateDepthBuffer=true,
bool _depthtest=true);
virtual void drawCubeLine(const vec3& _min,
const vec3& _max,
const etk::Color<float>& _color,
mat4& _transformationMatrix,
bool _updateDepthBuffer=true,
bool _depthtest=true);
public:
void drawSquare(const vec3& _size,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor);
void drawSphere(float _radius,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor);
void drawCylinder(float _radius,
float _size,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor);
void drawCapsule(float _radius,
float _size,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor);
void drawCone(float _radius,
float _size,
int _lats,
int _longs,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor);
void drawTriangles(const etk::Vector<vec3>& _vertex,
const etk::Vector<uint32_t>& _indice,
mat4& _transformationMatrix,
const etk::Color<float>& _tmpColor,
const vec3& _offset=vec3(0,0,0.1));
};
};
};
#endif

View File

@ -0,0 +1,92 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/uri/uri.hpp>
#include <ewol/debug.hpp>
#include <ewol/resource/ConfigFile.hpp>
#include <gale/resource/Manager.hpp>
#include <ejson/ejson.hpp>
#include <ejson/Number.hpp>
#include <ejson/String.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::ConfigFile);
ewol::resource::ConfigFile::ConfigFile() :
gale::Resource(),
// set map unorderred
m_list(0, false) {
addResourceType("ewol::ConfigFile");
}
void ewol::resource::ConfigFile::init(const etk::Uri& _uri) {
ethread::RecursiveLock lock(m_mutex);
gale::Resource::init(_uri.get());
EWOL_DEBUG("SFP : load \"" << _uri << "\"");
reload();
}
ewol::resource::ConfigFile::~ConfigFile() {
m_list.clear();
}
void ewol::resource::ConfigFile::reload() {
ethread::RecursiveLock lock(m_mutex);
// reset all parameters
for (size_t iii=0; iii<m_list.size(); ++iii){
if (m_list.getValue(iii).exist() == true) {
m_list.getValue(iii) = ejson::empty();
}
}
m_doc.load(etk::Uri(m_name));
for (auto elementName : m_list.getKeys()) {
if (m_doc[elementName].exist() == true) {
m_list[elementName] = m_doc[elementName];
}
}
}
int32_t ewol::resource::ConfigFile::request(const etk::String& _paramName) {
ethread::RecursiveLock lock(m_mutex);
// check if the parameters existed :
if (m_list.exist(_paramName) == false) {
m_list.add(_paramName, ejson::empty());
}
if (m_doc[_paramName].exist() == true) {
m_list[_paramName] = m_doc[_paramName];
}
return m_list.getId(_paramName);
}
double ewol::resource::ConfigFile::getNumber(int32_t _id) {
ethread::RecursiveLock lock(m_mutex);
if ( _id < 0
|| m_list.getValue(_id).exist() == false) {
return 0.0;
}
return m_list.getValue(_id).toNumber().get();
}
etk::String ewol::resource::ConfigFile::getString(int32_t _id) {
ethread::RecursiveLock lock(m_mutex);
if ( _id < 0
|| m_list.getValue(_id).exist() == false) {
return "";
}
return m_list.getValue(_id).toString().get();
}
bool ewol::resource::ConfigFile::getBoolean(int32_t _id) {
ethread::RecursiveLock lock(m_mutex);
if ( _id < 0
|| m_list.getValue(_id).exist() == false) {
return false;
}
return m_list.getValue(_id).toBoolean().get();
}

View File

@ -0,0 +1,44 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/Map.hpp>
#include <ewol/debug.hpp>
#include <ejson/ejson.hpp>
#include <gale/resource/Resource.hpp>
namespace ewol {
namespace resource {
class ConfigFile : public gale::Resource {
private:
ejson::Document m_doc;
etk::Map<etk::String, ejson::Value> m_list;
protected:
ConfigFile();
void init(const etk::Uri& _filename);
public:
virtual ~ConfigFile();
DECLARE_RESOURCE_URI_FACTORY(ConfigFile);
public:
void reload();
int32_t request(const etk::String& _paramName);
double getNumber(int32_t _id);
etk::String getString(int32_t _id);
bool getBoolean(int32_t _id);
public:
/**
* @brief keep the resource pointer.
* @note Never free this pointer by your own...
* @param[in] _filename Name of the configuration file.
* @return pointer on the resource or null if an error occured.
*/
static ememory::SharedPtr<ewol::resource::ConfigFile> keep(const etk::String& _filename);
};
};
};

View File

@ -0,0 +1,470 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <etk/uri/uri.hpp>
#include <egami/egami.hpp>
#include <gale/resource/Manager.hpp>
#include <ewol/resource/font/FontBase.hpp>
#include <ewol/resource/TexturedFont.hpp>
#include <ewol/resource/FontFreeType.hpp>
#include <ewol/context/Context.hpp>
#include <ewol/resource/DistanceFieldFont.hpp>
#include <edtaa3/edtaa3func.h>
#include <ejson/ejson.hpp>
#define SIZE_GENERATION (30)
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::DistanceFieldFont);
ewol::resource::DistanceFieldFont::DistanceFieldFont() :
ewol::resource::Texture(),
m_borderSize(10),
m_textureBorderSize(0,0) {
addResourceType("ewol::resource::DistanceFieldFont");
m_font = null;
m_lastGlyphPos.setValue(1,1);
m_lastRawHeigh = 0;
m_sizeRatio = 1.0f;
}
/**
* @brief Get all the Path contain in the specidy path:
* @param[in] _path Generic path to parse ...
* @return The list of path found
* @example[start]
* auto out = explodeMultiplePath("DATA:///font?lib=ewol");
* // out contain: {"DATA:///font", "DATA:///font?lib=ewol"}
* @example[stop]
*/
static etk::Vector<etk::Uri> explodeMultiplePath(const etk::Uri& _uri) {
etk::Vector<etk::Uri> out;
out.pushBack(_uri);
if (_uri.getQuery().exist("lib") == true) {
etk::Uri tmp = _uri;
tmp.getQuery().erase("lib");
out.pushBack(tmp);
}
return out;
}
void ewol::resource::DistanceFieldFont::init(const etk::String& _fontName) {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::Texture::init(_fontName);
etk::String localName = _fontName;
etk::Vector<etk::Uri> folderList;
if (ewol::getContext().getFontDefault().getUseExternal() == true) {
#if defined(__TARGET_OS__Android)
folderList.pushBack(etk::Path("/system/fonts"));
#elif defined(__TARGET_OS__Linux)
folderList.pushBack(etk::Path("/usr/share/fonts"));
#endif
}
etk::Uri applicationBaseFont = ewol::getContext().getFontDefault().getFolder();
for (auto &it : explodeMultiplePath(applicationBaseFont)) {
folderList.pushBack(it);
}
for (size_t folderID = 0; folderID < folderList.size() ; folderID++) {
etk::Vector<etk::Uri> output = etk::uri::listRecursive(folderList[folderID]);
etk::Vector<etk::String> split = etk::split(localName, ';');
EWOL_INFO("try to find font named : " << split << " in: " << output);
//EWOL_CRITICAL("parse string : " << split);
bool hasFindAFont = false;
for (size_t jjj=0; jjj<split.size(); jjj++) {
EWOL_INFO(" try with : '" << split[jjj] << "'");
for (size_t iii=0; iii<output.size(); iii++) {
etk::String nameFolder = output[iii].getPath().getString();
//EWOL_DEBUG(" file : " << output[iii]);
if( true == etk::end_with(nameFolder, split[jjj]+"-"+"regular"+".ttf", false)
|| true == etk::end_with(nameFolder, split[jjj]+"-"+"r"+".ttf", false)
|| true == etk::end_with(nameFolder, split[jjj]+"regular"+".ttf", false)
|| true == etk::end_with(nameFolder, split[jjj]+"r"+".ttf", false)
|| true == etk::end_with(nameFolder, split[jjj]+".ttf", false)) {
EWOL_INFO(" find Font [Regular] : " << output[iii]);
m_fileName = output[iii];
hasFindAFont=true;
break;
}
}
if (hasFindAFont == true) {
EWOL_INFO(" find this font : '" << split[jjj] << "'");
break;
} else if (jjj == split.size()-1) {
EWOL_ERROR("Find NO font in the LIST ... " << split);
}
}
if (hasFindAFont == true) {
EWOL_INFO(" find this font : '" << folderList[folderID] << "'");
break;
} else if (folderID == folderList.size()-1) {
EWOL_ERROR("Find NO font in the LIST ... " << folderList);
}
}
if (m_fileName.isEmpty() == true) {
EWOL_ERROR("can not load FONT name : '" << _fontName << "'" );
m_font = null;
return;
}
EWOL_INFO("Load FONT name : '" << m_fileName << "'");
m_font = ewol::resource::FontFreeType::create(m_fileName);
if (m_font == null) {
EWOL_ERROR("Pb Loading FONT name : '" << m_fileName << "'" );
}
// set the bassic charset:
m_listElement.clear();
if (m_font == null) {
return;
}
if (importFromFile() == true) {
EWOL_INFO("GET distance field from previous file");
flush();
return;
}
m_sizeRatio = ((float)SIZE_GENERATION) / ((float)m_font->getHeight(SIZE_GENERATION));
// TODO : basic font use 512 is better ... == > maybe estimate it with the dpi ???
setImageSize(ivec2(512,32));
// now we can acces directly on the image
m_data.clear(etk::Color<>(0x00000000));
// add error glyph
addGlyph(0);
// by default we set only the first AINSI char availlable
for (int32_t iii=0x20; iii<0x7F; iii++) {
addGlyph(iii);
}
flush();
if (true) {
EWOL_ERROR("Save in cache the loaded data ..... ");
egami::store(m_data, "CACHE:///fileFont.bmp"); // ==> for debug test only ...
egami::store(m_data, "CACHE:///fileFont.png");
}
exportOnFile();
}
ewol::resource::DistanceFieldFont::~DistanceFieldFont() {
}
float ewol::resource::DistanceFieldFont::getDisplayRatio(float _size) {
ethread::RecursiveLock lock(m_mutex);
return _size / (float)SIZE_GENERATION;
}
void ewol::resource::DistanceFieldFont::generateDistanceField(const egami::ImageMono& _input, egami::Image& _output) {
EWOL_INFO("Generate Distance field font [START]");
EWOL_INFO(" _input.getSize()=" << _input.getSize());
ethread::RecursiveLock lock(m_mutex);
int32_t size = _input.getSize().x() * _input.getSize().y();
etk::Vector<short> xdist;
etk::Vector<short> ydist;
etk::Vector<double> gx;
etk::Vector<double> gy;
etk::Vector<double> data;
etk::Vector<double> outside;
etk::Vector<double> inside;
xdist.resize(size, 0);
ydist.resize(size, 0);
gx.resize(size, 0.0);
gy.resize(size, 0.0);
data.resize(size, 0.0);
outside.resize(size, 0.0);
inside.resize(size, 0.0);
EWOL_INFO(" size=" << size);
// Convert img into double (data)
double img_min = 255, img_max = -255;
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
int32_t iii = yyy * _input.getSize().x() + xxx;
double v = _input.get(ivec2(xxx, yyy));
data[iii] = v;
if (v > img_max) {
img_max = v;
}
if (v < img_min) {
img_min = v;
}
}
}
// Rescale image levels between 0 and 1
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
int32_t iii = yyy * _input.getSize().x() + xxx;
data[iii] = (_input.get(ivec2(xxx, yyy))-img_min)/img_max;
}
}
// Compute outside = edtaa3(bitmap); % Transform background (0's)
computegradient(&data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &outside[0]);
for(size_t iii = 0; iii < outside.size(); ++iii) {
if( outside[iii] < 0 ) {
outside[iii] = 0.0;
}
}
// Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
for(size_t iii = 0; iii < gx.size(); ++iii) {
gx[iii] = 0;
}
for(size_t iii = 0; iii < gy.size(); ++iii) {
gy[iii] = 0;
}
for(size_t iii = 0; iii < data.size(); ++iii) {
data[iii] = 1 - data[iii];
}
computegradient( &data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &inside[0]);
for(size_t iii = 0; iii < inside.size(); ++iii) {
if( inside[iii] < 0 ) {
inside[iii] = 0.0;
}
}
EWOL_INFO(" _output=" << _output);
_output.resize(_input.getSize(), etk::Color<>(0));
_output.clear(etk::Color<>(0));
for (int32_t xxx = 0; xxx < _output.getSize().x(); ++xxx) {
for (int32_t yyy = 0; yyy < _output.getSize().y(); ++yyy) {
int32_t iii = yyy * _output.getSize().x() + xxx;
outside[iii] -= inside[iii];
outside[iii] = 128+outside[iii]*16;
if( outside[iii] < 0 ) {
outside[iii] = 0;
}
if( outside[iii] > 255 ) {
outside[iii] = 255;
}
uint8_t val = 255 - (unsigned char) outside[iii];
// TODO : Remove multiple size of the map ...
_output.set(ivec2(xxx, yyy), etk::Color<>((int32_t)val,(int32_t)val,(int32_t)val,255));
}
}
EWOL_INFO(" _output=" << _output);
}
bool ewol::resource::DistanceFieldFont::addGlyph(const char32_t& _val) {
ethread::RecursiveLock lock(m_mutex);
bool hasChange = false;
if (m_font == null) {
return false;
}
// add the curent "char"
GlyphProperty tmpchar;
tmpchar.m_UVal = _val;
egami::ImageMono imageGlyphRaw;
egami::Image imageGlyphDistanceField(ivec2(32,32), egami::colorType::RGBA8);
EWOL_DEBUG("Generate Glyph : " << _val);
if (m_font->getGlyphProperty(SIZE_GENERATION, tmpchar) == true) {
//EWOL_DEBUG("load char: '" << _val << "'=" << _val);
hasChange = true;
// change line if needed ...
if (m_lastGlyphPos.x() + tmpchar.m_sizeTexture.x()+m_borderSize*2.0 > m_data.getSize().x()) {
m_lastGlyphPos.setX(1);
m_lastGlyphPos += ivec2(0, m_lastRawHeigh);
m_lastRawHeigh = 0;
}
while(m_lastGlyphPos.y()+tmpchar.m_sizeTexture.y()+m_borderSize*2.0 > m_data.getSize().y()) {
ivec2 size = m_data.getSize();
size.setY(size.y()*2);
EWOL_VERBOSE("resize " << m_data.getSize() << " => " << size);
m_data.resize(size, etk::Color<>(0));
// change the coordonate on the element in the texture
for (size_t jjj = 0; jjj < m_listElement.size(); ++jjj) {
m_listElement[jjj].m_texturePosStart *= vec2(1.0f, 0.5f);
m_listElement[jjj].m_texturePosSize *= vec2(1.0f, 0.5f);
}
}
m_textureBorderSize = vec2(m_borderSize/(float)m_data.getSize().x(),
m_borderSize/(float)m_data.getSize().y() );
// draw the glyph
m_font->drawGlyph(imageGlyphRaw, SIZE_GENERATION, tmpchar, m_borderSize);
generateDistanceField(imageGlyphRaw, imageGlyphDistanceField);
if (_val == 100) {
EWOL_DEBUG("print char: " << _val << " size=" << imageGlyphDistanceField.getSize());
for (int32_t yyy = 0; yyy < imageGlyphDistanceField.getSize().y(); ++yyy) {
for (int32_t xxx = 0; xxx < imageGlyphDistanceField.getSize().x(); ++xxx) {
EWOL_PRINT((int)(imageGlyphDistanceField.get(ivec2(xxx, yyy)).r()) << " ");
}
}
}
m_data.insert(m_lastGlyphPos, imageGlyphDistanceField);
// set image position
tmpchar.m_texturePosStart.setValue( ((float)m_lastGlyphPos.x()+(m_borderSize*0.5f)) / (float)m_data.getSize().x(),
((float)m_lastGlyphPos.y()+(m_borderSize*0.5f)) / (float)m_data.getSize().y() );
tmpchar.m_texturePosSize.setValue( ((float)imageGlyphRaw.getSize().x()-m_borderSize) / (float)m_data.getSize().x(),
((float)imageGlyphRaw.getSize().y()-m_borderSize) / (float)m_data.getSize().y() );
// update the maximum of the line hight :
if (m_lastRawHeigh < imageGlyphRaw.getSize().y()) {
// note : +1 is for the overlapping of the glyph (Part 2)
m_lastRawHeigh = imageGlyphRaw.getSize().y()+1;
}
// note : +1 is for the overlapping of the glyph (Part 3)
// update the Bitmap position drawing :
m_lastGlyphPos += ivec2(imageGlyphRaw.getSize().x()+1, 0);
} else {
EWOL_WARNING("Did not find char : '" << _val << "'=" << _val);
tmpchar.setNotExist();
}
m_listElement.pushBack(tmpchar);
//m_font[iii]->display();
// generate the kerning for all the characters :
if (tmpchar.exist() == true) {
// TODO : set the kerning back ...
//m_font[iii]->generateKerning(m_size, m_listElement[iii]);
}
if (hasChange == true) {
flush();
//EWOL_ERROR("Save in cache the loaded data ..... ");
//egami::store(m_data, "CACHE:///fileFont.bmp"); // ==> for debug test only ...
//egami::store(m_data, "CACHE:///fileFont.png");
}
return hasChange;
}
int32_t ewol::resource::DistanceFieldFont::getIndex(char32_t _charcode) {
ethread::RecursiveLock lock(m_mutex);
if (_charcode < 0x20) {
return 0;
} else if (_charcode < 0x80) {
return _charcode - 0x1F;
} else {
for (size_t iii=0x80-0x20; iii < m_listElement.size(); iii++) {
//EWOL_DEBUG("search : '" << charcode << "' =?= '" << (m_listElement[displayMode])[iii].m_UVal << "'");
if (_charcode == (m_listElement)[iii].m_UVal) {
//EWOL_DEBUG("search : '" << charcode << "'");
if ((m_listElement)[iii].exist()) {
//EWOL_DEBUG("return " << iii);
return iii;
} else {
return 0;
}
}
}
}
if (addGlyph(_charcode) == true) {
// TODO : This does not work due to the fact that the update of open GL is not done in the context main cycle !!!
ewol::getContext().forceRedrawAll();
}
return 0;
}
ewol::GlyphProperty* ewol::resource::DistanceFieldFont::getGlyphPointer(const char32_t& _charcode) {
ethread::RecursiveLock lock(m_mutex);
EWOL_VERBOSE("getGlyphPointer : " << uint32_t(_charcode));
int32_t index = getIndex(_charcode);
if( index < 0
|| (size_t)index >= m_listElement.size() ) {
EWOL_ERROR(" Try to get glyph index inexistant ... == > return the index 0 ... id=" << index);
if (m_listElement.size() > 0) {
return &((m_listElement)[0]);
}
return null;
}
//EWOL_ERROR(" index=" << index);
//EWOL_ERROR(" m_UVal=" << m_listElement[_displayMode][index].m_UVal);
//EWOL_ERROR(" m_glyphIndex=" << m_listElement[_displayMode][index].m_glyphIndex);
//EWOL_ERROR(" m_advance=" << m_listElement[_displayMode][index].m_advance);
//EWOL_ERROR(" m_bearing=" << m_listElement[_displayMode][index].m_bearing);
return &((m_listElement)[index]);
}
void ewol::resource::DistanceFieldFont::exportOnFile() {
ethread::RecursiveLock lock(m_mutex);
EWOL_DEBUG("EXPORT: DistanceFieldFont : file : '" << m_fileName << ".json'");
ejson::Document doc;
ejson::Array tmpList;
for (size_t iii=0; iii<m_listElement.size(); ++iii) {
ejson::Object tmpObj;
tmpObj.add("m_UVal", ejson::String(etk::toString(m_listElement[iii].m_UVal)));
tmpObj.add("m_glyphIndex", ejson::Number(m_listElement[iii].m_glyphIndex));
tmpObj.add("m_sizeTexture", ejson::String((etk::String)m_listElement[iii].m_sizeTexture));
tmpObj.add("m_bearing", ejson::String((etk::String)m_listElement[iii].m_bearing));
tmpObj.add("m_advance", ejson::String((etk::String)m_listElement[iii].m_advance));
tmpObj.add("m_texturePosStart", ejson::String((etk::String)m_listElement[iii].m_texturePosStart));
tmpObj.add("m_texturePosSize", ejson::String((etk::String)m_listElement[iii].m_texturePosSize));
tmpObj.add("m_exist", ejson::Boolean(m_listElement[iii].m_exist));
tmpList.add(tmpObj);
}
doc.add("m_listElement", tmpList);
doc.add("m_sizeRatio", ejson::Number(m_sizeRatio));
doc.add("m_lastGlyphPos", ejson::String(m_lastGlyphPos));
doc.add("m_lastRawHeigh", ejson::Number(m_lastRawHeigh));
doc.add("m_borderSize", ejson::Number(m_borderSize));
doc.add("m_textureBorderSize", ejson::String(m_textureBorderSize));
etk::Uri tmpUri = m_fileName;
tmpUri.setScheme("CACHE");
tmpUri.setPath(m_fileName.getPath() + ".json");
doc.store(tmpUri);
//tmpUri.setPath(m_fileName.getPath() + ".bmp");
//egami::store(m_data, tmpUri);
tmpUri.setPath(m_fileName.getPath() + ".png");
egami::store(m_data, tmpUri);
}
bool ewol::resource::DistanceFieldFont::importFromFile() {
ethread::RecursiveLock lock(m_mutex);
etk::Uri tmpUriJson = m_fileName;
tmpUriJson.setScheme("CACHE");
tmpUriJson.setPath(m_fileName.getPath() + ".json");
etk::Uri tmpUriBmp = m_fileName;
tmpUriBmp.setScheme("CACHE");
tmpUriBmp.setPath(m_fileName.getPath() + ".png");
EWOL_DEBUG("IMPORT: DistanceFieldFont : file : '" << tmpUriJson << "'");
// test file existance:
if ( etk::uri::exist(tmpUriJson) == false
|| etk::uri::exist(tmpUriBmp) == false) {
EWOL_DEBUG("Does not import file for distance field system");
return false;
}
ejson::Document doc;
if (doc.load(tmpUriJson) == false) {
return false;
}
egami::Image tmpImage = egami::load(tmpUriBmp);
if (tmpImage.exist() == false) {
return false;
}
m_data = tmpImage;
m_sizeRatio = doc["m_sizeRatio"].toNumber().get(0);
m_lastGlyphPos = doc["m_lastGlyphPos"].toString().get("0,0");
m_lastRawHeigh = doc["m_lastRawHeigh"].toNumber().get(0);
m_borderSize = doc["m_borderSize"].toNumber().get(2);
m_textureBorderSize = doc["m_textureBorderSize"].toString().get("0,0");
ejson::Array tmpList = doc["m_listElement"].toArray();
if (tmpList.exist() == false) {
EWOL_ERROR("null pointer array");
return false;
}
m_listElement.clear();
for (const auto it : tmpList) {
const ejson::Object tmpObj = it.toObject();
if (tmpObj.exist() == false) {
continue;
}
GlyphProperty prop;
prop.m_UVal = etk::string_to_int32_t(tmpObj["m_UVal"].toString().get("0"));
prop.m_glyphIndex = tmpObj["m_glyphIndex"].toNumber().get(0);
prop.m_sizeTexture = tmpObj["m_sizeTexture"].toString().get("0,0");
prop.m_bearing = tmpObj["m_bearing"].toString().get("0,0");
prop.m_advance = tmpObj["m_advance"].toString().get("0,0");
prop.m_texturePosStart = tmpObj["m_texturePosStart"].toString().get("0,0");
prop.m_texturePosSize = tmpObj["m_texturePosSize"].toString().get("0,0");
prop.m_exist = tmpObj["m_exist"].toBoolean().get(false);
m_listElement.pushBack(prop);
}
return m_data.exist();
}

View File

@ -0,0 +1,96 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/resource/font/FontBase.hpp>
#include <ewol/resource/Texture.hpp>
#include <ewol/resource/TexturedFont.hpp>
namespace ewol {
namespace resource {
class DistanceFieldFont : public ewol::resource::Texture {
private:
etk::Uri m_fileName;
float m_sizeRatio;
// specific element to have the the know if the specify element is known...
// == > otherwise I can just generate italic ...
// == > Bold is a little more complicated (maybe with the bordersize)
ememory::SharedPtr<ewol::resource::FontBase> m_font;
public:
etk::Vector<GlyphProperty> m_listElement;
private:
// for the texture generation :
ivec2 m_lastGlyphPos;
int32_t m_lastRawHeigh;
protected:
DistanceFieldFont();
void init(const etk::String& _fontName);
public:
DECLARE_RESOURCE_NAMED_FACTORY(DistanceFieldFont);
virtual ~DistanceFieldFont();
public:
float getDisplayRatio(float _size);
/**
* @brief get the display height of this font
* @param[in] _size Request font size
* @return Dimention of the font need between 2 lines
*/
float getHeight(float _size) {
return ((float)m_font->getHeight(_size));
};
/**
* @brief get the font size with a specific display size
* @param[in] _fontHeight Request font height
* @return Dimention of the font for this compleate line size.
*/
float getSize(float _fontHeight) {
return m_font->getSizeWithHeight(_fontHeight);
}
/**
* @brief get the ID of a unicode charcode
* @param[in] _charcode The unicodeValue
* @return The ID in the table (if it does not exist : return 0)
*/
int32_t getIndex(char32_t _charcode);
/**
* @brief get the pointer on the coresponding glyph
* @param[in] _charcode The unicodeValue
* @return The pointer on the glyph == > never null
*/
ewol::GlyphProperty* getGlyphPointer(const char32_t& _charcode);
public:
/**
* @brief keep the resource pointer.
* @note Never free this pointer by your own...
* @param[in] _filename Name of the texture font.
* @return pointer on the resource or null if an error occured.
*/
static ememory::SharedPtr<ewol::resource::DistanceFieldFont> keep(const etk::String& _filename);
private:
/**
* @brief add a glyph in a texture font.
* @param[in] _val Char value to add.
* @return true if the image size have change, false otherwise
*/
bool addGlyph(const char32_t& _val);
void generateDistanceField(const egami::ImageMono& _input, egami::Image& _output);
private:
float m_borderSize; //!< number of pixel added on the border of a glyph
vec2 m_textureBorderSize; //!< Transformed the border size in the texture dimention
public:
float getPixelBorderSize() {
return m_borderSize;
}
const vec2& getTextureBorderSize() {
return m_textureBorderSize;
}
public:
void exportOnFile();
bool importFromFile();
};
};
};

View File

@ -0,0 +1,384 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <etk/Vector.hpp>
#include <gale/renderer/openGL/openGL.hpp>
#include <ewol/resource/Texture.hpp>
#include <ewol/resource/FontFreeType.hpp>
#include <ewol/resource/font/FontBase.hpp>
#include <gale/resource/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::FontFreeType);
// free Font hnadle of librairies ... entry for acces ...
static int32_t l_countLoaded=0;
static FT_Library library;
void ewol::resource::freeTypeInit() {
EWOL_DEBUG(" == > init Font-Manager");
l_countLoaded++;
if (l_countLoaded>1) {
// already loaded ...
return;
}
int32_t error = FT_Init_FreeType( &library );
if(0 != error) {
EWOL_CRITICAL(" when loading FreeType Librairy ...");
}
}
void ewol::resource::freeTypeUnInit() {
EWOL_DEBUG(" == > Un-Init Font-Manager");
l_countLoaded--;
if (l_countLoaded>0) {
// already needed ...
return;
}
int32_t error = FT_Done_FreeType( library );
library = null;
if(0 != error) {
EWOL_CRITICAL(" when Un-loading FreeType Librairy ...");
}
}
ewol::resource::FontFreeType::FontFreeType() {
addResourceType("ewol::FontFreeType");
m_init = false;
m_FileSize = 0;
}
void ewol::resource::FontFreeType::init(const etk::Uri& _uri) {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::FontBase::init(_uri);
auto fileIO = etk::uri::get(_uri);
if (fileIO == null) {
EWOL_ERROR("File Does not exist : " << _uri);
return;
}
if (fileIO->open(etk::io::OpenMode::Read) == false) {
EWOL_ERROR("Can not open the file : " << _uri);
return;
}
m_FileBuffer = fileIO->readAll<FT_Byte>();
// close the file:
fileIO->close();
// load Face ...
int32_t error = FT_New_Memory_Face(library, &m_FileBuffer[0], m_FileBuffer.size(), 0, &m_fftFace );
if( FT_Err_Unknown_File_Format == error) {
EWOL_ERROR("... the font file could be opened and read, but it appears ... that its font format is unsupported");
} else if (0 != error) {
EWOL_ERROR("... another error code means that the font file could not ... be opened or read, or simply that it is broken...");
} else {
// all OK
EWOL_DEBUG("load font : \"" << _uri << "\" glyph count = " << (int)m_fftFace->num_glyphs);
m_init = true;
//display();
}
}
ewol::resource::FontFreeType::~FontFreeType() {
ethread::RecursiveLock lock(m_mutex);
// clean the tmp memory
m_FileBuffer.clear();
// must be deleted fftFace
FT_Done_Face(m_fftFace);
}
vec2 ewol::resource::FontFreeType::getSize(int32_t _fontSize, const etk::String& _unicodeString) {
ethread::RecursiveLock lock(m_mutex);
if (m_init == false) {
return vec2(0,0);
}
// TODO : ...
vec2 outputSize(0,0);
return outputSize;
}
int32_t ewol::resource::FontFreeType::getHeight(int32_t _fontSize) {
ethread::RecursiveLock lock(m_mutex);
return _fontSize*1.43f; // this is a really "magic" number ...
}
float ewol::resource::FontFreeType::getSizeWithHeight(float _fontHeight) {
ethread::RecursiveLock lock(m_mutex);
return _fontHeight*0.6993f; // this is a really "magic" number ...
}
bool ewol::resource::FontFreeType::getGlyphProperty(int32_t _fontSize, ewol::GlyphProperty& _property) {
ethread::RecursiveLock lock(m_mutex);
if(false == m_init) {
return false;
}
// 300dpi (hight quality) 96 dpi (normal quality)
int32_t fontQuality = 96;
// Select size ...
// note tha <<6 == *64 corespond with the 1/64th of points calculation of freetype
int32_t error = FT_Set_Char_Size(m_fftFace, _fontSize<<6, _fontSize<<6, fontQuality, fontQuality);
if (0!=error ) {
EWOL_ERROR("FT_Set_Char_Size == > error in settings ...");
return false;
}
// a small shortcut
FT_GlyphSlot slot = m_fftFace->glyph;
// retrieve glyph index from character code
int32_t glyph_index = FT_Get_Char_Index(m_fftFace, _property.m_UVal);
// load glyph image into the slot (erase previous one)
error = FT_Load_Glyph(m_fftFace, // handle to face object
glyph_index, // glyph index
FT_LOAD_DEFAULT );
if (0!=error ) {
EWOL_ERROR("FT_Load_Glyph specify Glyph");
return false;
}
// convert to an anti-aliased bitmap
error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL );
if (0!=error) {
EWOL_ERROR("FT_Render_Glyph");
return false;
}
// set properties :
_property.m_glyphIndex = glyph_index;
_property.m_sizeTexture.setValue(slot->bitmap.width, slot->bitmap.rows);
_property.m_bearing.setValue( slot->metrics.horiBearingX>>6 , slot->metrics.horiBearingY>>6 );
_property.m_advance.setValue( slot->metrics.horiAdvance>>6 , slot->metrics.vertAdvance>>6 );
return true;
}
bool ewol::resource::FontFreeType::drawGlyph(egami::Image& _imageOut,
int32_t _fontSize,
ivec2 _glyphPosition,
ewol::GlyphProperty& _property,
int8_t _posInImage) {
ethread::RecursiveLock lock(m_mutex);
if(m_init == false) {
return false;
}
// 300dpi (hight quality) 96 dpi (normal quality)
int32_t fontQuality = 96;
// Select size ...
// note tha <<6 == *64 corespond with the 1/64th of points calculation of freetype
int32_t error = FT_Set_Char_Size(m_fftFace, _fontSize<<6, _fontSize<<6, fontQuality, fontQuality);
if (0!=error ) {
EWOL_ERROR("FT_Set_Char_Size == > error in settings ...");
return false;
}
// a small shortcut
FT_GlyphSlot slot = m_fftFace->glyph;
// load glyph image into the slot (erase previous one)
error = FT_Load_Glyph(m_fftFace, // handle to face object
_property.m_glyphIndex, // glyph index
FT_LOAD_DEFAULT );
if (0!=error ) {
EWOL_ERROR("FT_Load_Glyph specify Glyph");
return false;
}
// convert to an anti-aliased bitmap
error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL );
if (0!=error) {
EWOL_ERROR("FT_Render_Glyph");
return false;
}
// draw it on the output Image :
etk::Color<> tlpppp(0xFF, 0xFF, 0xFF, 0x00);
for(size_t jjj=0; jjj < slot->bitmap.rows;jjj++) {
for(size_t iii=0; iii < slot->bitmap.width; iii++){
tlpppp = _imageOut.get(ivec2(_glyphPosition.x()+iii, _glyphPosition.y()+jjj));
uint8_t valueColor = slot->bitmap.buffer[iii + slot->bitmap.width*jjj];
// set only alpha :
switch(_posInImage) {
default:
case 0:
tlpppp.setA(valueColor);
break;
case 1:
tlpppp.setR(valueColor);
break;
case 2:
tlpppp.setG(valueColor);
break;
case 3:
tlpppp.setB(valueColor);
break;
}
// real set of color
_imageOut.set(ivec2(_glyphPosition.x()+iii, _glyphPosition.y()+jjj), tlpppp );
}
}
return true;
}
bool ewol::resource::FontFreeType::drawGlyph(egami::ImageMono& _imageOut,
int32_t _fontSize,
ewol::GlyphProperty& _property,
int32_t _borderSize) {
ethread::RecursiveLock lock(m_mutex);
if(false == m_init) {
return false;
}
// 300dpi (hight quality) 96 dpi (normal quality)
int32_t fontQuality = 96;
// Select size ...
// note tha <<6 == *64 corespond with the 1/64th of points calculation of freetype
int32_t error = FT_Set_Char_Size(m_fftFace, _fontSize<<6, _fontSize<<6, fontQuality, fontQuality);
if (0!=error ) {
EWOL_ERROR("FT_Set_Char_Size == > error in settings ...");
return false;
}
// a small shortcut
FT_GlyphSlot slot = m_fftFace->glyph;
// load glyph image into the slot (erase previous one)
error = FT_Load_Glyph(m_fftFace, // handle to face object
_property.m_glyphIndex, // glyph index
FT_LOAD_DEFAULT );
if (0!=error ) {
EWOL_ERROR("FT_Load_Glyph specify Glyph");
return false;
}
// convert to an anti-aliased bitmap
error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL ); // TODO : set FT_RENDER_MODE_MONO ==> 1 bit value ==> faster generation ...
if (0!=error) {
EWOL_ERROR("FT_Render_Glyph");
return false;
}
// resize output image :
_imageOut.resize(ivec2(slot->bitmap.width+2*_borderSize, slot->bitmap.rows+2*_borderSize), 0);
for(size_t jjj=0; jjj < slot->bitmap.rows;jjj++) {
for(size_t iii=0; iii < slot->bitmap.width; iii++){
uint8_t valueColor = slot->bitmap.buffer[iii + slot->bitmap.width*jjj];
// real set of color
_imageOut.set(ivec2(_borderSize+iii, _borderSize+jjj), valueColor );
}
}
return true;
}
void ewol::resource::FontFreeType::generateKerning(int32_t fontSize, etk::Vector<ewol::GlyphProperty>& listGlyph) {
ethread::RecursiveLock lock(m_mutex);
if(m_init == false) {
return;
}
if ((FT_FACE_FLAG_KERNING & m_fftFace->face_flags) == 0) {
EWOL_INFO("No kerning generation (disable) in the font");
}
// 300dpi (hight quality) 96 dpi (normal quality)
int32_t fontQuality = 96;
// Select size ...
// note tha <<6 == *64 corespond with the 1/64th of points calculation of freetype
int32_t error = FT_Set_Char_Size(m_fftFace, fontSize<<6, fontSize<<6, fontQuality, fontQuality);
if (0!=error ) {
EWOL_ERROR("FT_Set_Char_Size == > error in settings ...");
return;
}
// For all the kerning element we get the kerning value :
for(size_t iii=0; iii<listGlyph.size(); iii++) {
listGlyph[iii].kerningClear();
for(size_t kkk=0; kkk<listGlyph.size(); kkk++) {
FT_Vector kerning;
FT_Get_Kerning(m_fftFace, listGlyph[kkk].m_glyphIndex, listGlyph[iii].m_glyphIndex, FT_KERNING_UNFITTED, &kerning );
// add the kerning only if != 0 ...
if (kerning.x != 0) {
listGlyph[iii].kerningAdd(listGlyph[kkk].m_UVal,
kerning.x/32.0f );
//EWOL_DEBUG("Kerning between : '" << (char)listGlyph[iii].m_UVal << "'&'" << (char)listGlyph[kkk].m_UVal << "' value : " << kerning.x << " => " << (kerning.x/64.0f));
}
}
}
}
void ewol::resource::FontFreeType::display() {
ethread::RecursiveLock lock(m_mutex);
if(m_init == false) {
return;
}
EWOL_INFO(" number of glyph = " << (int)m_fftFace->num_glyphs);
if ((FT_FACE_FLAG_SCALABLE & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_SCALABLE (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_SCALABLE (disable)");
}
if ((FT_FACE_FLAG_FIXED_SIZES & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_FIXED_SIZES (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_FIXED_SIZES (disable)");
}
if ((FT_FACE_FLAG_FIXED_WIDTH & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_FIXED_WIDTH (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_FIXED_WIDTH (disable)");
}
if ((FT_FACE_FLAG_SFNT & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_SFNT (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_SFNT (disable)");
}
if ((FT_FACE_FLAG_HORIZONTAL & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_HORIZONTAL (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_HORIZONTAL (disable)");
}
if ((FT_FACE_FLAG_VERTICAL & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_VERTICAL (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_VERTICAL (disable)");
}
if ((FT_FACE_FLAG_KERNING & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_KERNING (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_KERNING (disable)");
}
/* Deprecated flag
if ((FT_FACE_FLAG_FAST_GLYPHS & face->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_FAST_GLYPHS (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_FAST_GLYPHS (disable)");
}
*/
if ((FT_FACE_FLAG_MULTIPLE_MASTERS & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_MULTIPLE_MASTERS (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_MULTIPLE_MASTERS (disable)");
}
if ((FT_FACE_FLAG_GLYPH_NAMES & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_GLYPH_NAMES (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_GLYPH_NAMES (disable)");
}
if ((FT_FACE_FLAG_EXTERNAL_STREAM & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_EXTERNAL_STREAM (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_EXTERNAL_STREAM (disable)");
}
if ((FT_FACE_FLAG_HINTER & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_HINTER (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_HINTER (disable)");
}
if ((FT_FACE_FLAG_CID_KEYED & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_CID_KEYED (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_CID_KEYED (disable)");
}
/*
if ((FT_FACE_FLAG_TRICKY & m_fftFace->face_flags) != 0) {
EWOL_INFO(" flags = FT_FACE_FLAG_TRICKY (enable)");
} else {
EWOL_DEBUG(" flags = FT_FACE_FLAG_TRICKY (disable)");
}
*/
EWOL_INFO(" unit per EM = " << m_fftFace->units_per_EM);
EWOL_INFO(" num of fixed sizes = " << m_fftFace->num_fixed_sizes);
//EWOL_INFO(" Availlable sizes = " << (int)m_fftFace->available_sizes);
//EWOL_INFO(" Current size = " << (int)m_fftFace->size);
}

View File

@ -0,0 +1,61 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/resource/font/FontBase.hpp>
#include <etk/uri/uri.hpp>
#include <egami/egami.hpp>
extern "C" {
#include <ft2build.h>
}
#include FT_FREETYPE_H
namespace ewol {
namespace resource {
// show : http://www.freetype.org/freetype2/docs/tutorial/step2.html
class FontFreeType : public ewol::resource::FontBase {
private:
etk::Vector<FT_Byte> m_FileBuffer;
int32_t m_FileSize;
FT_Face m_fftFace;
bool m_init;
void display();
protected:
FontFreeType();
void init(const etk::Uri& _uri);
public:
DECLARE_RESOURCE_URI_FACTORY(FontFreeType);
virtual ~FontFreeType();
public:
bool getGlyphProperty(int32_t _fontSize,
ewol::GlyphProperty& _property);
bool drawGlyph(egami::Image& _imageOut,
int32_t _fontSize,
ivec2 _glyphPosition,
ewol::GlyphProperty& _property,
int8_t _posInImage);
bool drawGlyph(egami::ImageMono& _imageOut,
int32_t _fontSize,
ewol::GlyphProperty& _property,
int32_t _borderSize = 0);
vec2 getSize(int32_t _fontSize, const etk::String& _unicodeString);
int32_t getHeight(int32_t _fontSize);
float getSizeWithHeight(float _fontHeight);
void generateKerning(int32_t _fontSize, etk::Vector<ewol::GlyphProperty>& _listGlyph);
};
void freeTypeInit();
void freeTypeUnInit();
};
};

View File

@ -0,0 +1,225 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <egami/egami.hpp>
#include <gale/resource/Manager.hpp>
#include <ewol/resource/ImageDF.hpp>
#include <ewol/resource/Texture.hpp>
#include <edtaa3/edtaa3func.h>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::ImageDF);
ewol::resource::ImageDF::ImageDF() {
addResourceType("ewol::resource::ImageDF");
}
void ewol::resource::ImageDF::init() {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::Texture::init();
}
void ewol::resource::ImageDF::init(etk::String _genName, const etk::Uri& _uri, const ivec2& _size) {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::Texture::init(_genName);
EWOL_DEBUG("create a new resource::Image : _genName=" << _genName << " _uri=" << _uri << " size=" << _size);
m_data = egami::load(_uri, _size);
if (m_data.exist() == false) {
EWOL_ERROR("ERROR when loading the image : " << _uri);
}
ivec2 tmp = m_data.getSize();
m_realImageSize = vec2(tmp.x(), tmp.y());
// distance field Generation
// TODO : if it is not a .edf ==> generate dynamicly ...
/*
egami::ImageMono input;
input.resize(tmp);
for (size_t yyy = 0; yyy < tmp.y(); ++yyy) {
for (size_t xxx = 0; xxx < tmp.x(); ++xxx) {
input.set(ivec2(xxx, yyy), m_data.get(ivec2(xxx, yyy)).a() );
}
}
generateDistanceField(input, m_data);
*/
flush();
}
void ewol::resource::ImageDF::generateDistanceField(const egami::ImageMono& _input, egami::Image& _output) {
ethread::RecursiveLock lock(m_mutex);
int32_t size = _input.getSize().x() * _input.getSize().y();
etk::Vector<short> xdist;
etk::Vector<short> ydist;
etk::Vector<double> gx;
etk::Vector<double> gy;
etk::Vector<double> data;
etk::Vector<double> outside;
etk::Vector<double> inside;
xdist.resize(size, 0);
ydist.resize(size, 0);
gx.resize(size, 0.0);
gy.resize(size, 0.0);
data.resize(size, 0.0);
outside.resize(size, 0.0);
inside.resize(size, 0.0);
// Convert img into double (data)
double img_min = 255, img_max = -255;
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
int32_t iii = yyy * _input.getSize().x() + xxx;
double v = _input.get(ivec2(xxx, yyy));
data[iii] = v;
if (v > img_max) {
img_max = v;
}
if (v < img_min) {
img_min = v;
}
}
}
// Rescale image levels between 0 and 1
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
int32_t iii = yyy * _input.getSize().x() + xxx;
data[iii] = (_input.get(ivec2(xxx, yyy))-img_min)/img_max;
}
}
// Compute outside = edtaa3(bitmap); % Transform background (0's)
computegradient(&data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &outside[0]);
for(size_t iii = 0; iii < outside.size(); ++iii) {
if( outside[iii] < 0 ) {
outside[iii] = 0.0;
}
}
// Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
for(size_t iii = 0; iii < gx.size(); ++iii) {
gx[iii] = 0;
}
for(size_t iii = 0; iii < gy.size(); ++iii) {
gy[iii] = 0;
}
for(size_t iii = 0; iii < data.size(); ++iii) {
data[iii] = 1 - data[iii];
}
computegradient( &data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &inside[0]);
for(size_t iii = 0; iii < inside.size(); ++iii) {
if( inside[iii] < 0 ) {
inside[iii] = 0.0;
}
}
_output.resize(_input.getSize(), etk::Color<>(0));
_output.clear(etk::Color<>(0));
for (int32_t xxx = 0; xxx < _output.getSize().x(); ++xxx) {
for (int32_t yyy = 0; yyy < _output.getSize().y(); ++yyy) {
int32_t iii = yyy * _output.getSize().x() + xxx;
outside[iii] -= inside[iii];
outside[iii] = 128+outside[iii]*16;
if( outside[iii] < 0 ) {
outside[iii] = 0;
}
if( outside[iii] > 255 ) {
outside[iii] = 255;
}
uint8_t val = 255 - (unsigned char) outside[iii];
// TODO : Remove multiple size of the map ...
_output.set(ivec2(xxx, yyy), etk::Color<>((int32_t)val,(int32_t)val,(int32_t)val,255));
}
}
}
#ifdef __TARGET_OS__Android
/**
* @brief get the next power 2 if the input
* @param[in] _value Value that we want the next power of 2
* @return result value
*/
static int32_t nextP2(int32_t _value) {
int32_t val=1;
for (int32_t iii=1; iii<31; iii++) {
if (_value <= val) {
return val;
}
val *=2;
}
EWOL_CRITICAL("impossible CASE.... request P2 of " << _value);
return val;
}
#endif
ememory::SharedPtr<ewol::resource::ImageDF> ewol::resource::ImageDF::create(const etk::Uri& _uri, ivec2 _size) {
EWOL_VERBOSE("KEEP: TextureFile: '" << _uri << "' size=" << _size);
if (_uri.isEmpty() == true) {
ememory::SharedPtr<ewol::resource::ImageDF> object(ETK_NEW(ewol::resource::ImageDF));
if (object == null) {
EWOL_ERROR("allocation error of a resource : ??TEX??");
return null;
}
object->init();
getManager().localAdd(object);
return object;
}
if (_size.x() == 0) {
_size.setX(-1);
//EWOL_ERROR("Error Request the image size.x() =0 ???");
}
if (_size.y() == 0) {
_size.setY(-1);
//EWOL_ERROR("Error Request the image size.y() =0 ???");
}
etk::Uri tmpFilename = _uri;
if (etk::toLower(_uri.getPath().getExtention()) != "svg") {
_size = ivec2(-1,-1);
}
#ifdef __TARGET_OS__MacOs
EWOL_ERROR("TODO : remove this strange hack");
_size = ivec2(64,64);
#endif
if ( _size.x() > 0
&& _size.y() > 0) {
EWOL_VERBOSE(" == > specific size : " << _size);
#ifdef __TARGET_OS__Android
_size.setValue(nextP2(_size.x()), nextP2(_size.y()));
#endif
tmpFilename.getQuery().set("x", etk::toString(_size.x()));
tmpFilename.getQuery().set("y", etk::toString(_size.y()));
}
EWOL_VERBOSE("KEEP: TextureFile: '" << tmpFilename << "' new size=" << _size);
ememory::SharedPtr<ewol::resource::ImageDF> object = null;
ememory::SharedPtr<gale::Resource> object2 = getManager().localKeep("DF__" + tmpFilename.getString());
if (object2 != null) {
object = ememory::dynamicPointerCast<ewol::resource::ImageDF>(object2);
if (object == null) {
EWOL_CRITICAL("Request resource file : '" << tmpFilename << "' With the wrong type (dynamic cast error)");
return null;
}
}
if (object != null) {
return object;
}
EWOL_INFO("CREATE: ImageDF: '" << tmpFilename << "' size=" << _size);
// need to crate a new one ...
object = ememory::SharedPtr<ewol::resource::ImageDF>(ETK_NEW(ewol::resource::ImageDF));
if (object == null) {
EWOL_ERROR("allocation error of a resource : " << _uri);
return null;
}
object->init("DF__" + tmpFilename.getString(), _uri, _size);
getManager().localAdd(object);
return object;
}

View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <egami/Image.hpp>
#include <egami/ImageMono.hpp>
#include <ewol/resource/Texture.hpp>
namespace ewol {
namespace resource {
class ImageDF : public ewol::resource::Texture {
protected:
vec2 m_realImageSize;
protected:
ImageDF();
void init();
void init(etk::String _genName, const etk::Uri& _uri, const ivec2& _size);
public:
virtual ~ImageDF() { };
protected:
/**
* @brief Generate distance field of this Image input.
* @param[in] _input Input image to change in distance field mode.
* @param[out] _output New image generate with this image _input.
*/
void generateDistanceField(const egami::ImageMono& _input, egami::Image& _output);
public:
const vec2& getRealSize() {
return m_realImageSize;
};
public:
/**
* @brief keep the resource pointer.
* @note Never free this pointer by your own...
* @param[in] _filename Name of the image file.
* @param[in] _requested size of the image (usefull when loading .svg to automatic rescale)
* @return pointer on the resource or null if an error occured.
*/
static ememory::SharedPtr<ewol::resource::ImageDF> create(const etk::Uri& _uri, ivec2 _size=ivec2(-1,-1));
};
};
};

View File

@ -0,0 +1,319 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/ewol.hpp>
#include <gale/renderer/openGL/openGL.hpp>
#include <gale/renderer/openGL/openGL-include.hpp>
#include <gale/resource/Manager.hpp>
#include <ewol/resource/Texture.hpp>
#include <echrono/Steady.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::Texture);
/**
* @brief get the next power 2 if the input
* @param[in] value Value that we want the next power of 2
* @return result value
*/
static int32_t nextP2(int32_t _value) {
int32_t val=1;
for (int32_t iii=1; iii<31; iii++) {
if (_value <= val) {
return val;
}
val *=2;
}
EWOL_CRITICAL("impossible CASE....");
return val;
}
void ewol::resource::Texture::init(const etk::String& _filename) {
gale::Resource::init(_filename);
}
void ewol::resource::Texture::init() {
gale::Resource::init();
}
ewol::resource::Texture::Texture() :
m_texId(0),
#ifdef EWOL_USE_FBO
m_texPboId(0),
#endif
m_data(ivec2(32,32),egami::colorType::RGBA8),
m_realImageSize(1,1),
m_lastSize(1,1),
m_loaded(false),
m_lastTypeObject(0),
m_lastSizeObject(0),
m_repeat(false),
m_filter(ewol::resource::TextureFilter::linear) {
addResourceType("ewol::compositing::Texture");
}
ewol::resource::Texture::~Texture() {
removeContext();
}
void ewol::resource::Texture::setRepeat(bool _value) {
m_repeat = _value;
}
void ewol::resource::Texture::setFilterMode(enum ewol::resource::TextureFilter _filter) {
m_filter = _filter;
}
#include <egami/egami.hpp>
bool ewol::resource::Texture::updateContext() {
EWOL_VERBOSE("updateContext [START]");
if (false) {
echrono::Steady tic = echrono::Steady::now();
gale::openGL::flush();
echrono::Steady toc = echrono::Steady::now();
EWOL_VERBOSE(" updateContext [FLUSH] ==> " << (toc - tic));
}
ethread::RecursiveLock lock(m_mutex, true);
echrono::Steady tic = echrono::Steady::now();
if (lock.tryLock() == false) {
//Lock error ==> try later ...
return false;
}
int32_t typeObject = GL_RGBA;
int32_t sizeObject = GL_UNSIGNED_BYTE;
int32_t sizeByte = 1;
switch (m_data.getType()) {
case egami::colorType::RGBA8:
typeObject = GL_RGBA;
sizeObject = GL_UNSIGNED_BYTE;
sizeByte = 4;
break;
case egami::colorType::RGB8:
typeObject = GL_RGB;
sizeObject = GL_UNSIGNED_BYTE;
sizeByte = 3;
break;
case egami::colorType::RGBAf:
typeObject = GL_RGBA;
sizeObject = GL_FLOAT;
sizeByte = 16;
break;
case egami::colorType::RGBf:
typeObject = GL_RGBA;
sizeObject = GL_FLOAT;
sizeByte = 12;
break;
case egami::colorType::unsignedInt16:
case egami::colorType::unsignedInt32:
case egami::colorType::float32:
case egami::colorType::float64:
EWOL_ERROR("Not manage the type " << m_data.getType() << " for texture");
break;
}
if (m_loaded == true) {
if ( m_lastTypeObject != typeObject
|| m_lastSizeObject != sizeObject
|| m_lastSize != m_data.getSize()) {
EWOL_WARNING("TEXTURE: Rm [" << getId() << "] texId=" << m_texId);
glDeleteTextures(1, &m_texId);
m_loaded = false;
}
}
if (m_loaded == false) {
// Request a new texture at openGl :
glGenTextures(1, &m_texId);
#ifdef EWOL_USE_FBO
EWOL_ERROR("CREATE PBO");
glGenBuffers(1, &m_texPboId);
EWOL_ERROR("CREATE PBO 1");
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_texPboId);
EWOL_ERROR("CREATE PBO 2");
glBufferData(GL_PIXEL_UNPACK_BUFFER, m_data.getGPUSize().x()*m_data.getGPUSize().y()*sizeByte, 0, GL_STREAM_DRAW);
EWOL_ERROR("CREATE PBO 3");
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
EWOL_ERROR("CREATE PBO 4 (done)");
#endif
m_lastSize = m_data.getSize();
m_lastTypeObject = typeObject;
m_lastSizeObject = sizeObject;
EWOL_DEBUG("TEXTURE: add [" << getId() << "]=" << m_data.getSize() << "=>" << m_data.getGPUSize() << " OGl_Id=" << m_texId << " type=" << m_data.getType());
} else {
EWOL_DEBUG("TEXTURE: update [" << getId() << "]=" << m_data.getSize() << "=>" << m_data.getGPUSize() << " OGl_Id=" << m_texId << " type=" << m_data.getType());
}
// in all case we set the texture properties :
// TODO : check error ???
glBindTexture(GL_TEXTURE_2D, m_texId);
if (m_loaded == false) {
if (m_repeat == false) {
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
}
if (m_filter == ewol::resource::TextureFilter::linear) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
}
//glPixelStorei(GL_UNPACK_ALIGNMENT,1);
echrono::Steady toc1 = echrono::Steady::now();
EWOL_VERBOSE(" BIND ==> " << (toc1 - tic));
//egami::store(m_data, etk::String("~/texture_") + etk::toString(getId()) + ".bmp");
#if defined(__TARGET_OS__Android) \
|| defined(__TARGET_OS__IOs)
// On some embended target, the texture size must be square of 2:
if (m_loaded == false) {
// 1: Create the square 2 texture:
int32_t bufferSize = m_data.getGPUSize().x() * m_data.getGPUSize().y() * 8;
static etk::Vector<float> tmpData;
if (tmpData.size() < bufferSize) {
tmpData.resize(bufferSize, 0.0f);
}
EWOL_DEBUG(" CREATE texture ==> " << m_data.getGPUSize());
// 2 create a new empty texture:
#ifdef EWOL_USE_FBO
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_texPboId);
void* pBuff = ::glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_data.getGPUSize().x() * m_data.getGPUSize().y() * sizeByte, GL_MAP_WRITE_BIT);
memcpy(pBuff, &tmpData[0], m_data.getGPUSize().x()*m_data.getGPUSize().y()*sizeByte);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glTexImage2D(GL_TEXTURE_2D, // Target
0, // Level
typeObject, // Format internal
m_data.getGPUSize().x(),
m_data.getGPUSize().y(),
0, // Border
typeObject, // format
sizeObject, // type
(void*)0 );
#else
glTexImage2D(GL_TEXTURE_2D, // Target
0, // Level
typeObject, // Format internal
m_data.getGPUSize().x(),
m_data.getGPUSize().y(),
0, // Border
typeObject, // format
sizeObject, // type
&tmpData[0] );
#endif
}
#ifdef EWOL_USE_FBO
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_texPboId);
void* pBuff = ::glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_data.getGPUSize().x() * m_data.getGPUSize().y() * sizeByte, GL_MAP_WRITE_BIT);
memcpy(pBuff, m_data.getTextureDataPointer(), m_data.getWidth()*m_data.getHeight()*sizeByte);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
//3 Flush all time the data:
glTexSubImage2D(GL_TEXTURE_2D, // Target
0, // Level
0, // x offset
0, // y offset
m_data.getWidth(),
m_data.getHeight(),
typeObject, // format
sizeObject, // type
(void *)0 );
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
#else
//3 Flush all time the data:
echrono::Steady tic1 = echrono::Steady::now();
glTexSubImage2D(GL_TEXTURE_2D, // Target
0, // Level
0, // x offset
0, // y offset
m_data.getWidth(),
m_data.getHeight(),
typeObject, // format
sizeObject, // type
(void*)((char*)m_data.getTextureDataPointer()) );
echrono::Steady toc2 = echrono::Steady::now();
EWOL_INFO(" updateContext [STOP] ==> " << (toc2 - tic1));
#endif
#else
// This is the normal case ==> set the image and after set just the update of the data
if (m_loaded == false) {
glTexImage2D(GL_TEXTURE_2D, // Target
0, // Level
typeObject, // Format internal
m_data.getWidth(),
m_data.getHeight(),
0, // Border
typeObject, // format
sizeObject, // type
m_data.getTextureDataPointer() );
} else {
glTexSubImage2D(GL_TEXTURE_2D, // Target
0, // Level
0, // x offset
0, // y offset
m_data.getWidth(),
m_data.getHeight(),
typeObject, // format
sizeObject, // type
m_data.getTextureDataPointer() );
}
#endif
// now the data is loaded
m_loaded = true;
echrono::Steady toc = echrono::Steady::now();
//EWOL_ERROR(" updateContext [STOP] ==> " << (toc - toc1));
return true;
}
void ewol::resource::Texture::removeContext() {
ethread::RecursiveLock lock(m_mutex);
if (m_loaded == true) {
// Request remove texture ...
EWOL_DEBUG("TEXTURE: Rm [" << getId() << "] texId=" << m_texId);
// TODO: Check if we are in the correct thread
glDeleteTextures(1, &m_texId);
m_loaded = false;
}
}
void ewol::resource::Texture::removeContextToLate() {
ethread::RecursiveLock lock(m_mutex);
m_loaded = false;
m_texId=0;
}
void ewol::resource::Texture::flush() {
ethread::RecursiveLock lock(m_mutex);
// request to the manager to be call at the next update ...
EWOL_VERBOSE("Request UPDATE of Element");
getManager().update(ememory::dynamicPointerCast<gale::Resource>(sharedFromThis()));
}
void ewol::resource::Texture::setImageSize(ivec2 _newSize) {
ethread::RecursiveLock lock(m_mutex);
_newSize.setValue( nextP2(_newSize.x()), nextP2(_newSize.y()) );
m_data.resize(_newSize);
}
void ewol::resource::Texture::set(egami::Image _image) {
EWOL_DEBUG("Set a new image in a texture:");
ethread::RecursiveLock lock(m_mutex);
if (_image.exist() == false) {
EWOL_ERROR("ERROR when loading the image : [raw data]");
return;
}
EWOL_DEBUG(" size=" << _image.getSize());
etk::swap(m_data, _image);
ivec2 tmp = m_data.getSize();
m_realImageSize = vec2(tmp.x(), tmp.y());
vec2 compatibilityHWSize = vec2(nextP2(tmp.x()), nextP2(tmp.y()));
if (m_realImageSize != compatibilityHWSize) {
EWOL_VERBOSE("RESIZE Image for HArwareCompatibility:" << m_realImageSize << " => " << compatibilityHWSize);
m_data.resize(ivec2(compatibilityHWSize.x(),compatibilityHWSize.y()));
}
flush();
}

View File

@ -0,0 +1,91 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <egami/Image.hpp>
#include <gale/resource/Texture.hpp>
//#define EWOL_USE_FBO 1
namespace ewol {
namespace resource {
enum class TextureFilter {
nearest,
linear
};
class Texture : public gale::Resource {
protected:
uint32_t m_texId; //!< openGl textureID.
#ifdef EWOL_USE_FBO
uint32_t m_texPboId; //!< openGl textureID.
#endif
// openGl Context propoerties :
egami::Image m_data;
//! Last loaded size in the system openGL
vec2 m_lastSize;
//! some image are not square == > we need to sqared it to prevent some openGl api error the the displayable size is not all the time 0.0 -> 1.0
vec2 m_realImageSize;
// internal state of the openGl system :
bool m_loaded;
int32_t m_lastTypeObject;
int32_t m_lastSizeObject;
protected:
bool m_repeat; //!< repeate mode of the image (repeat the image if out of range [0..1]
public:
/**
* @brief Set the repeate mode of the images if UV range is out of [0..1]
* @param[in] _value Value of the new repeate mode
*/
void setRepeat(bool _value);
protected:
enum ewol::resource::TextureFilter m_filter; //!< Filter apply at the image when rendering it
public:
/**
* @brief Set the Filter mode to apply at the image when display with a scale (not 1:1 ratio)
* @param[in] _value Value of the new filter mode
*/
void setFilterMode(enum ewol::resource::TextureFilter _filter);
// Public API:
protected:
void init(const etk::String& _filename);
void init();
Texture();
public:
DECLARE_RESOURCE_FACTORY(Texture);
virtual ~Texture();
public:
// You must set the size here, because it will be set in multiple of pow(2)
void setImageSize(ivec2 _newSize);
// Get the reference on this image to draw nomething on it ...
inline egami::Image& get() {
return m_data;
};
/**
* @brief Set the image in the texture system
* @note It will reize in square2 if needed by the system.
* @param[in] _image Image to set. (use @code set(etk::move(xxx)); @endcode )
*/
void set(egami::Image _image);
// Flush the data to send it at the openGl system
void flush();
bool updateContext();
void removeContext();
void removeContextToLate();
const ivec2& getOpenGlSize() const {
return m_data.getSize();
};
const vec2& getUsableSize() const {
return m_realImageSize;
};
uint32_t getRendererId() const {
return m_texId;
};
};
}
}

View File

@ -0,0 +1,119 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <egami/egami.hpp>
#include <gale/resource/Manager.hpp>
#include <ewol/resource/TextureFile.hpp>
#include <ewol/resource/Texture.hpp>
#include <ethread/Thread.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::resource::TextureFile);
const ivec2 ewol::resource::TextureFile::sizeAuto(-1,-1);
const ivec2 ewol::resource::TextureFile::sizeDefault(0,0);
/**
* @brief get the next power 2 if the input
* @param[in] _value Value that we want the next power of 2
* @return result value
*/
static int32_t nextP2(int32_t _value) {
int32_t val=1;
for (int32_t iii=1; iii<31; iii++) {
if (_value <= val) {
return val;
}
val *=2;
}
EWOL_CRITICAL("impossible CASE.... request P2 of " << _value);
return val;
}
ewol::resource::TextureFile::TextureFile() {
addResourceType("ewol::resource::Image");
}
void ewol::resource::TextureFile::init() {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::Texture::init();
}
void ewol::resource::TextureFile::init(etk::String _genName, const etk::Uri& _uri, const ivec2& _size) {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::Texture::init(_genName);
EWOL_DEBUG("create a new resource::Image : _genName=" << _genName << " _uri=" << _uri << " size=" << _size);
egami::Image tmp = egami::load(_uri, _size);
set(etk::move(tmp));
//m_lastSize = m_realImageSize;
#ifdef GENERATE_DISTANCE_FIELD_MODE
//egami::generateDistanceFieldFile(_uri, etk::String(_uri, 0, _uri.size()-4) + ".bmp");
egami::generateDistanceFieldFile(_uri, etk::String(_uri, 0, _uri.size()-4) + ".edf");
#endif
}
ememory::SharedPtr<ewol::resource::TextureFile> ewol::resource::TextureFile::create(const etk::Uri& _uri, ivec2 _size, ivec2 _sizeRegister) {
EWOL_VERBOSE("KEEP: TextureFile: '" << _uri << "' size=" << _size << " sizeRegister=" << _sizeRegister);
if (_uri.isEmpty() == true) {
ememory::SharedPtr<ewol::resource::TextureFile> object(ETK_NEW(ewol::resource::TextureFile));
if (object == null) {
EWOL_ERROR("allocation error of a resource : ??TEX??");
return null;
}
object->init();
getManager().localAdd(object);
return object;
}
if (_size.x() == 0) {
_size.setX(-1);
//EWOL_ERROR("Error Request the image size.x() =0 ???");
}
if (_size.y() == 0) {
_size.setY(-1);
//EWOL_ERROR("Error Request the image size.y() =0 ???");
}
etk::Uri tmpFilename = _uri;
if (etk::toLower(_uri.getPath().getExtention()) != "svg") {
_size = ewol::resource::TextureFile::sizeAuto;
}
if (_size.x()>0 && _size.y()>0) {
EWOL_VERBOSE(" == > specific size : " << _size);
_size.setValue(nextP2(_size.x()), nextP2(_size.y()));
if (_sizeRegister != ewol::resource::TextureFile::sizeAuto) {
if (_sizeRegister != ewol::resource::TextureFile::sizeDefault) {
tmpFilename.getQuery().set("x", etk::toString(_size.x()));
tmpFilename.getQuery().set("y", etk::toString(_size.y()));
}
}
}
EWOL_VERBOSE("KEEP: TextureFile: '" << tmpFilename << "' new size=" << _size);
ememory::SharedPtr<ewol::resource::TextureFile> object = null;
ememory::SharedPtr<gale::Resource> object2 = getManager().localKeep(tmpFilename.getString());
if (object2 != null) {
object = ememory::dynamicPointerCast<ewol::resource::TextureFile>(object2);
if (object == null) {
EWOL_CRITICAL("Request resource file : '" << tmpFilename << "' With the wrong type (dynamic cast error)");
return null;
}
}
if (object != null) {
return object;
}
EWOL_DEBUG("CREATE: TextureFile: '" << tmpFilename << "' size=" << _size);
// need to crate a new one ...
object = ememory::SharedPtr<ewol::resource::TextureFile>(ETK_NEW(ewol::resource::TextureFile));
if (object == null) {
EWOL_ERROR("allocation error of a resource : " << _uri);
return null;
}
object->init(tmpFilename.getString(), _uri, _size);
getManager().localAdd(object);
return object;
}

View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
// TODO : Change tis file name ...
#pragma once
#include <etk/types.hpp>
#include <etk/types.hpp>
#include <egami/Image.hpp>
#include <ewol/resource/Texture.hpp>
namespace ewol {
namespace resource {
class TextureFile : public ewol::resource::Texture {
public:
static const ivec2 sizeAuto;
static const ivec2 sizeDefault;
protected:
TextureFile();
void init();
void init(etk::String _genName, const etk::Uri& _uri, const ivec2& _size);
public:
virtual ~TextureFile() { };
public:
const vec2& getRealSize() {
return m_realImageSize;
};
public:
/**
* @brief keep the resource pointer.
* @note Never free this pointer by your own...
* @param[in] _filename Name of the image file.
* @param[in] _requested size of the image (usefull when loading .svg to automatic rescale)
* @param[in] _sizeRegister size register in named (When you preaload the images the size write here will be )
* @return pointer on the resource or null if an error occured.
*/
static ememory::SharedPtr<ewol::resource::TextureFile> create(const etk::Uri& _filename,
ivec2 _size=ewol::resource::TextureFile::sizeAuto,
ivec2 _sizeRegister=ewol::resource::TextureFile::sizeAuto);
};
};
};

View File

@ -0,0 +1,369 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <egami/egami.hpp>
#include <gale/resource/Manager.hpp>
#include <ewol/resource/font/FontBase.hpp>
#include <ewol/resource/TexturedFont.hpp>
#include <ewol/resource/FontFreeType.hpp>
#include <ewol/context/Context.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::font::mode);
ETK_DECLARE_TYPE(ewol::resource::TexturedFont);
etk::Stream& ewol::operator <<(etk::Stream& _os, enum ewol::font::mode _obj) {
switch(_obj) {
default :
_os << "error";
break;
case ewol::font::Regular:
_os << "Regular";
break;
case ewol::font::Italic:
_os << "Italic";
break;
case ewol::font::Bold:
_os << "Bold";
break;
case ewol::font::BoldItalic:
_os << "BoldItalic";
break;
}
return _os;
}
ewol::resource::TexturedFont::TexturedFont():
m_size(10) {
addResourceType("ewol::resource::TexturedFont");
}
/**
* @brief Get all the Path contain in the specidy path:
* @param[in] _path Generic path to parse ...
* @return The list of path found
* @example[start]
* auto out = explodeMultiplePath("DATA:///font?lib=ewol");
* // out contain: {"DATA:///font", "DATA:///font?lib=ewol"}
* @example[stop]
*/
static etk::Vector<etk::Uri> explodeMultiplePath(const etk::Uri& _uri) {
etk::Vector<etk::Uri> out;
out.pushBack(_uri);
if (_uri.getQuery().exist("lib") == true) {
etk::Uri tmp = _uri;
tmp.getQuery().erase("lib");
out.pushBack(tmp);
}
return out;
}
void ewol::resource::TexturedFont::init(const etk::String& _fontName) {
ethread::RecursiveLock lock(m_mutex);
ewol::resource::Texture::init(_fontName);
EWOL_DEBUG("Load font : '" << _fontName << "'" );
m_font[0] = null;
m_font[1] = null;
m_font[2] = null;
m_font[3] = null;
m_modeWraping[0] = ewol::font::Regular;
m_modeWraping[1] = ewol::font::Regular;
m_modeWraping[2] = ewol::font::Regular;
m_modeWraping[3] = ewol::font::Regular;
m_lastGlyphPos[0].setValue(1,1);
m_lastGlyphPos[1].setValue(1,1);
m_lastGlyphPos[2].setValue(1,1);
m_lastGlyphPos[3].setValue(1,1);
m_lastRawHeigh[0] = 0;
m_lastRawHeigh[1] = 0;
m_lastRawHeigh[2] = 0;
m_lastRawHeigh[3] = 0;
int32_t tmpSize = 0;
// extarct name and size :
const char * tmpData = _fontName.c_str();
const char * tmpPos = strchr(tmpData, ':');
if (tmpPos == null) {
m_size = 1;
EWOL_CRITICAL("Can not parse the font name: '" << _fontName << "' ??? ':' " );
return;
} else {
if (sscanf(tmpPos+1, "%d", &tmpSize)!=1) {
m_size = 1;
EWOL_CRITICAL("Can not parse the font name: '" << _fontName << "' == > size ???");
return;
}
}
etk::String localName(_fontName, 0, (tmpPos - tmpData));
if (tmpSize>400) {
EWOL_ERROR("Font size too big ==> limit at 400 when exxeed ==> error: " << tmpSize << "==>30");
tmpSize = 30;
}
m_size = tmpSize;
etk::Vector<etk::Uri> folderList;
if (ewol::getContext().getFontDefault().getUseExternal() == true) {
#if defined(__TARGET_OS__Android)
folderList.pushBack(etk::Path("/system/fonts"));
#elif defined(__TARGET_OS__Linux)
folderList.pushBack(etk::Path("/usr/share/fonts"));
#endif
}
etk::Uri applicationBaseFont = ewol::getContext().getFontDefault().getFolder();
for (auto &it : explodeMultiplePath(applicationBaseFont)) {
folderList.pushBack(it);
}
for (size_t folderID = 0; folderID < folderList.size() ; folderID++) {
etk::Vector<etk::Uri> output = etk::uri::listRecursive(folderList[folderID]);
etk::Vector<etk::String> split = etk::split(localName, ';');
EWOL_DEBUG("try to find font named : " << split << " in: " << output);
//EWOL_CRITICAL("parse string : " << split);
bool hasFindAFont = false;
for (size_t jjj=0; jjj<split.size(); jjj++) {
EWOL_DEBUG(" try with : '" << split[jjj] << "'");
for (size_t iii=0; iii<output.size(); iii++) {
etk::String nameFolder = output[iii].getPath().getString();
//EWOL_DEBUG(" file : " << output[iii]);
if( etk::end_with(nameFolder, split[jjj]+"-"+"bold"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"b"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"bd"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"bold"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"bd"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"b"+".ttf", false) == true) {
EWOL_DEBUG(" find Font [Bold] : " << output[iii]);
m_fileName[ewol::font::Bold] = output[iii];
hasFindAFont = true;
} else if( etk::end_with(nameFolder, split[jjj]+"-"+"oblique"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"italic"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"Light"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"i"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"oblique"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"italic"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"light"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"i"+".ttf", false) == true) {
EWOL_DEBUG(" find Font [Italic] : " << output[iii]);
m_fileName[ewol::font::Italic] = output[iii];
hasFindAFont = true;
} else if( etk::end_with(nameFolder, split[jjj]+"-"+"bolditalic"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"boldoblique"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"bi"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"z"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"bolditalic"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"boldoblique"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"bi"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"z"+".ttf", false) == true) {
EWOL_DEBUG(" find Font [Bold-Italic] : " << output[iii]);
m_fileName[ewol::font::BoldItalic] = output[iii];
hasFindAFont = true;
} else if( etk::end_with(nameFolder, split[jjj]+"-"+"regular"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"-"+"r"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"regular"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+"r"+".ttf", false) == true
|| etk::end_with(nameFolder, split[jjj]+".ttf", false) == true) {
EWOL_DEBUG(" find Font [Regular] : " << output[iii]);
m_fileName[ewol::font::Regular] = output[iii];
hasFindAFont = true;
}
}
if (hasFindAFont == true) {
EWOL_DEBUG(" find this font : '" << split[jjj] << "'");
break;
} else if (jjj == split.size()-1) {
EWOL_DEBUG("Find NO font in the LIST ... " << split);
}
}
if (hasFindAFont == true) {
EWOL_DEBUG(" find this font : '" << folderList[folderID] << "'");
break;
} else if (folderID == folderList.size()-1) {
EWOL_ERROR("Find NO font in the LIST ... " << folderList);
}
}
// try to find the reference mode :
enum ewol::font::mode refMode = ewol::font::Regular;
for(int32_t iii=3; iii >= 0; iii--) {
if (m_fileName[iii].isEmpty() == false) {
refMode = (enum ewol::font::mode)iii;
}
}
EWOL_DEBUG(" set reference mode : " << refMode);
// generate the wrapping on the preventing error
for(int32_t iii=3; iii >= 0; iii--) {
if (m_fileName[iii].isEmpty() == false) {
m_modeWraping[iii] = (enum ewol::font::mode)iii;
} else {
m_modeWraping[iii] = refMode;
}
}
for (int32_t iiiFontId=0; iiiFontId<4 ; iiiFontId++) {
if (m_fileName[iiiFontId].isEmpty() == true) {
EWOL_DEBUG("can not load FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" == > size=" << m_size );
m_font[iiiFontId] = null;
continue;
}
EWOL_DEBUG("Load FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" == > size=" << m_size);
m_font[iiiFontId] = ewol::resource::FontFreeType::create(m_fileName[iiiFontId]);
if (m_font[iiiFontId] == null) {
EWOL_DEBUG("error in loading FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" == > size=" << m_size );
}
}
for (int32_t iiiFontId=0; iiiFontId<4 ; iiiFontId++) {
// set the bassic charset:
m_listElement[iiiFontId].clear();
if (m_font[iiiFontId] == null) {
continue;
}
m_height[iiiFontId] = m_font[iiiFontId]->getHeight(m_size);
// TODO : basic font use 512 is better ... == > maybe estimate it with the dpi ???
setImageSize(ivec2(256,32));
// now we can acces directly on the image
m_data.clear(etk::Color<>(0x00000000));
}
// add error glyph
addGlyph(0);
// by default we set only the first AINSI char availlable
for (int32_t iii=0x20; iii<0x7F; iii++) {
EWOL_VERBOSE("Add clyph :" << iii);
addGlyph(iii);
}
flush();
EWOL_DEBUG("Wrapping properties : ");
EWOL_DEBUG(" " << ewol::font::Regular << " == >" << getWrappingMode(ewol::font::Regular));
EWOL_DEBUG(" " << ewol::font::Italic << " == >" << getWrappingMode(ewol::font::Italic));
EWOL_DEBUG(" " << ewol::font::Bold << " == >" << getWrappingMode(ewol::font::Bold));
EWOL_DEBUG(" " << ewol::font::BoldItalic << " == >" << getWrappingMode(ewol::font::BoldItalic));
}
ewol::resource::TexturedFont::~TexturedFont() {
}
bool ewol::resource::TexturedFont::addGlyph(const char32_t& _val) {
ethread::RecursiveLock lock(m_mutex);
bool hasChange = false;
// for each font :
for (int32_t iii=0; iii<4 ; iii++) {
if (m_font[iii] == null) {
continue;
}
// add the curent "char"
GlyphProperty tmpchar;
tmpchar.m_UVal = _val;
if (m_font[iii]->getGlyphProperty(m_size, tmpchar) == true) {
//EWOL_DEBUG("load char : '" << _val << "'=" << _val.get());
hasChange = true;
// change line if needed ...
if (m_lastGlyphPos[iii].x()+tmpchar.m_sizeTexture.x()+3 > m_data.getSize().x()) {
m_lastGlyphPos[iii].setX(1);
m_lastGlyphPos[iii] += ivec2(0, m_lastRawHeigh[iii]);
m_lastRawHeigh[iii] = 0;
}
while(m_lastGlyphPos[iii].y()+tmpchar.m_sizeTexture.y()+3 > m_data.getSize().y()) {
ivec2 size = m_data.getSize();
size.setY(size.y()*2);
m_data.resize(size, etk::Color<>(0));
// note : need to rework all the lyer due to the fact that the texture is used by the faur type...
for (size_t kkk=0; kkk<4 ; kkk++) {
// change the coordonate on the element in the texture
for (size_t jjj=0 ; jjj<m_listElement[kkk].size() ; ++jjj) {
m_listElement[kkk][jjj].m_texturePosStart *= vec2(1.0f, 0.5f);
m_listElement[kkk][jjj].m_texturePosSize *= vec2(1.0f, 0.5f);
}
}
}
// draw the glyph
m_font[iii]->drawGlyph(m_data, m_size, m_lastGlyphPos[iii], tmpchar, iii);
// set video position
tmpchar.m_texturePosStart.setValue( (float)m_lastGlyphPos[iii].x() / (float)m_data.getSize().x(),
(float)m_lastGlyphPos[iii].y() / (float)m_data.getSize().y() );
tmpchar.m_texturePosSize.setValue( (float)tmpchar.m_sizeTexture.x() / (float)m_data.getSize().x(),
(float)tmpchar.m_sizeTexture.y() / (float)m_data.getSize().y() );
// update the maximum of the line hight :
if (m_lastRawHeigh[iii]<tmpchar.m_sizeTexture.y()) {
// note : +1 is for the overlapping of the glyph (Part 2)
m_lastRawHeigh[iii] = tmpchar.m_sizeTexture.y()+1;
}
// note : +1 is for the overlapping of the glyph (Part 3)
// update the Bitmap position drawing :
m_lastGlyphPos[iii] += ivec2(tmpchar.m_sizeTexture.x()+1, 0);
} else {
EWOL_WARNING("Did not find char : '" << _val << "'=" << _val);
tmpchar.setNotExist();
}
m_listElement[iii].pushBack(tmpchar);
//m_font[iii]->display();
// generate the kerning for all the characters :
if (tmpchar.exist() == true) {
// TODO : set the kerning back ...
//m_font[iii]->generateKerning(m_size, m_listElement[iii]);
}
}
if (hasChange == true) {
flush();
ewol::getContext().forceRedrawAll();
//egami::store(m_data, "fileFont.bmp"); // ==> for debug test only ...
}
return hasChange;
}
int32_t ewol::resource::TexturedFont::getIndex(char32_t _charcode, const enum ewol::font::mode _displayMode) {
ethread::RecursiveLock lock(m_mutex);
if (_charcode < 0x20) {
return 0;
} else if (_charcode < 0x80) {
return _charcode - 0x1F;
} else {
for (size_t iii=0x80-0x20; iii < m_listElement[_displayMode].size(); iii++) {
//EWOL_DEBUG("search : '" << charcode << "' =?= '" << (m_listElement[displayMode])[iii].m_UVal << "'");
if (_charcode == (m_listElement[_displayMode])[iii].m_UVal) {
//EWOL_DEBUG("search : '" << charcode << "'");
if ((m_listElement[_displayMode])[iii].exist()) {
//EWOL_DEBUG("return " << iii);
return iii;
} else {
return 0;
}
}
}
}
if (addGlyph(_charcode) == true) {
// TODO : This does not work due to the fact that the update of open GL is not done in the context main cycle !!!
ewol::getContext().forceRedrawAll();
}
return 0;
}
ewol::GlyphProperty* ewol::resource::TexturedFont::getGlyphPointer(const char32_t& _charcode, const enum ewol::font::mode _displayMode) {
ethread::RecursiveLock lock(m_mutex);
//EWOL_DEBUG("Get glyph property for mode: " << _displayMode << " == > wrapping index : " << m_modeWraping[_displayMode]);
int32_t index = getIndex(_charcode, _displayMode);
if( index < 0
|| (size_t)index >= m_listElement[_displayMode].size() ) {
EWOL_ERROR(" Try to get glyph index inexistant ... == > return the index 0 ... id=" << index);
if (m_listElement[_displayMode].size() > 0) {
return &((m_listElement[_displayMode])[0]);
}
return &m_emptyGlyph;
}
//EWOL_ERROR(" index=" << index);
//EWOL_ERROR(" m_UVal=" << m_listElement[_displayMode][index].m_UVal);
//EWOL_ERROR(" m_glyphIndex=" << m_listElement[_displayMode][index].m_glyphIndex);
//EWOL_ERROR(" m_advance=" << m_listElement[_displayMode][index].m_advance);
//EWOL_ERROR(" m_bearing=" << m_listElement[_displayMode][index].m_bearing);
return &((m_listElement[_displayMode])[index]);
}

View File

@ -0,0 +1,98 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/resource/font/FontBase.hpp>
#include <ewol/resource/Texture.hpp>
namespace ewol {
namespace font {
/**
* @not_in_doc
*/
enum mode {
Regular=0,
Italic,
Bold,
BoldItalic,
};
}
etk::Stream& operator <<(etk::Stream& _os, enum ewol::font::mode _obj);
namespace resource {
class TexturedFont : public ewol::resource::Texture {
private:
etk::Uri m_fileName[4];
int32_t m_size;
int32_t m_height[4];
// specific element to have the the know if the specify element is known...
// == > otherwise I can just generate italic ...
// == > Bold is a little more complicated (maybe with the bordersize)
ememory::SharedPtr<ewol::resource::FontBase> m_font[4];
enum ewol::font::mode m_modeWraping[4]; //!< This is a wrapping mode to prevent the fact that no font is define for a specific mode
public:
GlyphProperty m_emptyGlyph;
etk::Vector<GlyphProperty> m_listElement[4];
private:
// for the texture generation :
ivec2 m_lastGlyphPos[4];
int32_t m_lastRawHeigh[4];
protected:
TexturedFont();
void init(const etk::String& _fontName);
public:
DECLARE_RESOURCE_NAMED_FACTORY(TexturedFont);
virtual ~TexturedFont();
public:
/**
* @brief get the display height of this font
* @param[in] _displayMode Mode to display the currrent font
* @return Dimention of the font need between 2 lines
*/
int32_t getHeight(const enum ewol::font::mode _displayMode = ewol::font::Regular) {
return m_height[_displayMode];
};
/**
* @brief get the font height (user friendly)
* @return Dimention of the font the user requested
*/
int32_t getFontSize() {
return m_size;
};
/**
* @brief get the ID of a unicode charcode
* @param[in] _charcode The unicodeValue
* @param[in] _displayMode Mode to display the currrent font
* @return The ID in the table (if it does not exist : return 0)
*/
int32_t getIndex(char32_t _charcode, const enum ewol::font::mode _displayMode);
/**
* @brief get the pointer on the coresponding glyph
* @param[in] _charcode The unicodeValue
* @param[in] _displayMode Mode to display the currrent font
* @return The pointer on the glyph == > never null
*/
ewol::GlyphProperty* getGlyphPointer(const char32_t& _charcode, const enum ewol::font::mode _displayMode);
/**
* @brief The wrapping mode is used to prevent the non existance of a specific mode.
* For exemple when a blod mode does not exist, this resend a regular mode.
* @param[in] _source The requested mode.
* @return the best mode we have in stock.
*/
enum ewol::font::mode getWrappingMode(const enum ewol::font::mode _source) {
return m_modeWraping[_source];
};
private:
/**
* @brief add a glyph in a texture font.
* @param[in] _val Char value to add.
* @return true if the image size have change, false otherwise
*/
bool addGlyph(const char32_t& _val);
};
}
}

View File

@ -0,0 +1,55 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <egami/Image.hpp>
#include <egami/ImageMono.hpp>
#include <ewol/resource/Texture.hpp>
#include <gale/resource/Resource.hpp>
#include <ewol/resource/font/GlyphProperty.hpp>
namespace ewol {
namespace resource {
class FontBase : public gale::Resource {
public:
FontBase() {
addResourceType("ewol::FontFreeType");
}
void init(const etk::Uri& _uri) {
gale::Resource::init(_uri);
};
virtual ~FontBase() { };
virtual bool getGlyphProperty(int32_t _fontSize,
ewol::GlyphProperty& _property) = 0;
virtual bool drawGlyph(egami::Image& _imageOut,
int32_t _fontSize,
ivec2 _glyphPosition,
ewol::GlyphProperty& _property,
int8_t _posInImage) = 0;
virtual bool drawGlyph(egami::ImageMono& _imageOut,
int32_t _fontSize,
ewol::GlyphProperty& _property,
int32_t _borderSize = 0) = 0;
virtual vec2 getSize(int32_t _fontSize, const etk::String& _unicodeString) = 0;
virtual float getSizeWithHeight(float _fontHeight) = 0;
virtual int32_t getHeight(int32_t _fontSize) = 0;
virtual void generateKerning(int32_t _fontSize, etk::Vector<ewol::GlyphProperty>& _listGlyph) { };
virtual void display() {};
};
};
};

View File

@ -0,0 +1,103 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/resource/font/Kerning.hpp>
namespace ewol {
/*
| | | |
| | | |
| | | |
Y | | | |
^ |------------| |------------|
|
m_advance.y:/-> |
| |
| |
m_sizeTex.x/-> | | |------------| |------------|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | A | | G |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
\-> | | |------------| |------------|
/--> | |
\--> \-> |
m_bearing.y |
|____*________________________*____________>> X
<------------------------> : m_advance.x
<------------> : m_sizeTexture.x
<---> : m_bearing.x
*/
/**
* @not_in_doc
*/
class GlyphProperty {
public:
char32_t m_UVal; //!< Unicode value
public:
bool m_exist;
public:
int32_t m_glyphIndex; //!< Glyph index in the system
ivec2 m_sizeTexture; //!< size of the element to display
ivec2 m_bearing; //!< offset to display the data (can be negatif id the texture sise is bigger than the theoric places in the string)
ivec2 m_advance; //!< space use in the display for this specific char
vec2 m_texturePosStart; //!< Texture normalized position (START)
vec2 m_texturePosSize; //!< Texture normalized position (SIZE)
private:
etk::Vector<ewol::Kerning> m_kerning; //!< kerning values of link of all elements
public:
GlyphProperty() :
m_UVal(0),
m_exist(true),
m_glyphIndex(0),
m_sizeTexture(10,10),
m_bearing(2,2),
m_advance(10,10),
m_texturePosStart(0,0),
m_texturePosSize(0,0) {
};
float kerningGet(const char32_t _charcode) {
for(size_t iii=0; iii<m_kerning.size(); iii++ ) {
if (m_kerning[iii].m_UVal == _charcode) {
return m_kerning[iii].m_value;
}
}
return 0;
};
void kerningAdd(const char32_t _charcode, float _value) {
m_kerning.pushBack(ewol::Kerning(_charcode, _value));
};
void kerningClear() {
m_kerning.clear();
};
/**
* @brief get the status of the char, if it exist or not in the FONT
* @return true if the char is availlable, false otherwise
*/
bool exist() const {
return m_exist;
};
/**
* @brief set the element doen not exist !!!
*/
void setNotExist() {
m_exist = false;
};
};
};

View File

@ -0,0 +1,69 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
namespace ewol {
/**
* @not_in_doc
* @brief Kerning properties of one specific Glyph with an other
*
* Without Kerning :
* [pre]
*
* \ / /\
* \ / / \
* \ / / \
* \ / /______\
* \ / / \
* \/ / \
* v v a a
* [/pre]
*
* With Kerning :
* [pre]
*
* \ / /\
* \ / / \
* \ / / \
* \ / /______\
* \ / / \
* \/ / \
* v a v a
* [/pre]
*
* @note The "Kerning" is the methode to provide a better display for some string like
* the "VA" has 2 letter that overlap themself. This name Kerning
*/
class Kerning {
public:
char32_t m_UVal; //!< unicode value (the previous character that must be before)
float m_value; //!< kerning real offset
public:
/**
* @brief Simple constructor that allow to allocate the etk::Vector element
*/
Kerning() :
m_UVal(0),
m_value(0) {
};
/**
* @brief Normal constructor
* @param[in] _charcode The Unicode value of the coresponding character that might be before
* @param[in] _value The Kerning value of the offset (nb pixel number)
*/
Kerning(const char32_t _charcode, const float _value) :
m_UVal(_charcode),
m_value(_value) {
};
/**
* @brief normal destructor
*/
~Kerning() { };
};
};

View File

@ -0,0 +1,65 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/ewol.hpp>
#include <ewol/tools/message.hpp>
#include <ewol/context/Context.hpp>
#include <ewol/widget/Widget.hpp>
#include <ewol/widget/Windows.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/widget/meta/StdPopUp.hpp>
void ewol::tools::message::create(enum ewol::tools::message::type _type, const etk::String& _message) {
ewol::widget::StdPopUpShared tmpPopUp = widget::StdPopUp::create();
if (tmpPopUp == null) {
EWOL_ERROR("Can not create a simple pop-up");
return;
}
switch(_type) {
case ewol::tools::message::type::info:
tmpPopUp->propertyTitle.set("<bold>_T{Info}</bold>");
break;
case ewol::tools::message::type::warning:
tmpPopUp->propertyTitle.set("<bold><font color='orange'>_T{Warning}</font></bold>");
break;
case ewol::tools::message::type::error:
tmpPopUp->propertyTitle.set("<bold><font color='red'>_T{Error}</font></bold>");
break;
case ewol::tools::message::type::critical:
tmpPopUp->propertyTitle.set("<bold><font colorBg='red'>_T{Critical}</font></bold>");
break;
}
tmpPopUp->propertyComment.set(_message);
tmpPopUp->addButton("_T{close}", true);
tmpPopUp->propertyCloseOutEvent.set(true);
// get windows:
ewol::Context& context = ewol::getContext();
ewol::widget::WindowsShared windows = context.getWindows();
if (windows == null) {
EWOL_ERROR("can not get the current windows ... ==> can not display message : " << _message);
return;
}
windows->popUpWidgetPush(tmpPopUp);
}
void ewol::tools::message::displayInfo(const etk::String& _message) {
ewol::tools::message::create(ewol::tools::message::type::info, _message);
}
void ewol::tools::message::displayWarning(const etk::String& _message) {
ewol::tools::message::create(ewol::tools::message::type::warning, _message);
}
void ewol::tools::message::displayError(const etk::String& _message) {
ewol::tools::message::create(ewol::tools::message::type::error, _message);
}
void ewol::tools::message::displayCritical(const etk::String& _message) {
ewol::tools::message::create(ewol::tools::message::type::critical, _message);
}

View File

@ -0,0 +1,52 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Widget.hpp>
#include <etk/Color.hpp>
#include <ewol/resource/ColorFile.hpp>
namespace ewol {
namespace tools {
namespace message {
enum class type {
info, //!< information message pop-up
warning, //!< warning message pop-up
error, //!< Error message pop-up
critical //!< Critical message pop-up
};
/**
* @brief Create a simple pop-up message on the screen for application error.
* @param[in] _type Type of the error.
* @param[in] _message message to display (decorated text)
*/
void create(enum ewol::tools::message::type _type, const etk::String& _message);
/**
* @brief Create a simple information message
* @param[in] _message message to display (decorated text)
*/
void displayInfo(const etk::String& _message);
/**
* @brief Create a simple warning message
* @param[in] _message message to display (decorated text)
*/
void displayWarning(const etk::String& _message);
/**
* @brief Create a simple error message
* @param[in] _message message to display (decorated text)
*/
void displayError(const etk::String& _message);
/**
* @brief Create a simple critical message
* @param[in] _message message to display (decorated text)
*/
void displayCritical(const etk::String& _message);
}
}
}

View File

@ -0,0 +1,288 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/Button.hpp>
#include <ewol/object/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::Button);
ETK_DECLARE_TYPE(ewol::widget::Button::buttonLock);
// DEFINE for the shader display system:
const static int32_t STATUS_UP(0);
const static int32_t STATUS_HOVER(2);
const static int32_t STATUS_PRESSED(1);
const static int32_t STATUS_DOWN(3);
ewol::widget::Button::Button() :
signalPressed(this, "pressed", "Button is pressed"),
signalDown(this, "down", "Button is DOWN"),
signalUp(this, "up", "Button is UP"),
signalEnter(this, "enter", "The cursor enter inside the button"),
signalLeave(this, "leave", "the cursor leave the button"),
signalValue(this, "value", "button value change"),
propertyShape(this, "shape", etk::Uri("THEME_GUI:///Button.json?lib=ewol"), "The display name for config file", &ewol::widget::Button::onChangePropertyShape),
propertyValue(this, "value", false, "Value of the Button", &ewol::widget::Button::onChangePropertyValue),
propertyLock(this, "lock", lockNone, "Lock the button in a special state to permit changing state only by the coder", &ewol::widget::Button::onChangePropertyLock),
propertyToggleMode(this, "toggle", false, "The Button can toogle", &ewol::widget::Button::onChangePropertyToggleMode),
propertyEnableSingle(this, "enable-single", false, "If one element set in the Button ==> display only set", &ewol::widget::Button::onChangePropertyEnableSingle),
m_mouseHover(false),
m_buttonPressed(false),
m_selectableAreaPos(0,0),
m_selectableAreaSize(0,0) {
addObjectType("ewol::widget::Button");
// set property list:
propertyLock.add(lockNone, "none");
propertyLock.add(lockWhenPressed, "pressed");
propertyLock.add(lockWhenReleased, "released");
propertyLock.add(lockAccess, "access");
propertyCanFocus.setDirectCheck(true);
// shaper satatus update:
CheckStatus();
// Limit event at 1:
setMouseLimit(1);
}
void ewol::widget::Button::init() {
ewol::widget::Container2::init();
propertyShape.notifyChange();
}
ewol::widget::Button::~Button() {
}
void ewol::widget::Button::onChangeSize() {
ewol::Padding padding = m_shaper.getPadding();
ewol::Padding ret = onChangeSizePadded(padding);
//EWOL_DEBUG(" configuring : origin=" << origin << " size=" << subElementSize << "");
m_selectableAreaPos = vec2(ret.xLeft(), ret.yButtom());
m_selectableAreaSize = m_size - (m_selectableAreaPos + vec2(ret.xRight(), ret.yTop()));
}
void ewol::widget::Button::calculateMinMaxSize() {
ewol::Padding padding = m_shaper.getPadding();
calculateMinMaxSizePadded(padding);
}
void ewol::widget::Button::onDraw() {
// draw the shaaper (if needed indeed)
m_shaper.draw();
}
void ewol::widget::Button::onRegenerateDisplay() {
ewol::widget::Container2::onRegenerateDisplay();
if (needRedraw() == false) {
return;
}
ewol::Padding padding = m_shaper.getPadding();
m_shaper.setShape(vec2(0,0),
m_size,
vec2ClipInt32(m_selectableAreaPos+vec2(padding.xLeft(),padding.yButtom()) ),
vec2ClipInt32(m_selectableAreaSize-vec2(padding.x(),padding.y()) ) );
//EWOL_ERROR("pos=" << m_origin << " size=" << m_size);
}
bool ewol::widget::Button::onEventInput(const ewol::event::Input& _event) {
EWOL_VERBOSE("Event on BT : " << _event);
// disable event in the lock access mode :
if(ewol::widget::Button::lockAccess == *propertyLock) {
return false;
}
if( _event.getStatus() == gale::key::status::leave
|| _event.getStatus() == gale::key::status::abort) {
m_mouseHover = false;
m_buttonPressed = false;
} else {
vec2 relativePos = relativePosition(_event.getPos());
// prevent error from ouside the button
if( relativePos.x() < m_selectableAreaPos.x()
|| relativePos.y() < m_selectableAreaPos.y()
|| relativePos.x() > m_selectableAreaPos.x() + m_selectableAreaSize.x()
|| relativePos.y() > m_selectableAreaPos.y() + m_selectableAreaSize.y() ) {
m_mouseHover = false;
m_buttonPressed = false;
} else {
m_mouseHover = true;
}
}
EWOL_VERBOSE("Event on BT ... mouse hover : " << m_mouseHover);
if (m_mouseHover == true) {
if (_event.getId() == 1) {
if(_event.getStatus() == gale::key::status::down) {
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalDown);
signalDown.emit();
m_buttonPressed = true;
markToRedraw();
}
if(_event.getStatus() == gale::key::status::up) {
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalUp);
signalUp.emit();
m_buttonPressed = false;
markToRedraw();
}
if(_event.getStatus() == gale::key::status::pressSingle) {
if ( ( *propertyValue == true
&& *propertyLock == ewol::widget::Button::lockWhenPressed)
|| ( *propertyValue == false
&& *propertyLock == ewol::widget::Button::lockWhenReleased) ) {
// nothing to do : Lock mode ...
// user might set himself the new correct value with @ref setValue(xxx)
} else {
// inverse value :
propertyValue.set((*propertyValue)?false:true);
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalPressed);
signalPressed.emit();
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalValue << " val=" << *propertyValue );
signalValue.emit(*propertyValue);
if( *propertyToggleMode == false
&& *propertyValue == true) {
propertyValue.set(false);
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalValue << " val=" << *propertyValue);
signalValue.emit(*propertyValue);
}
}
markToRedraw();
}
}
}
CheckStatus();
return m_mouseHover;
}
bool ewol::widget::Button::onEventEntry(const ewol::event::Entry& _event) {
//EWOL_DEBUG("BT PRESSED : \"" << UTF8_data << "\" size=" << strlen(UTF8_data));
if( _event.getType() == gale::key::keyboard::character
&& _event.getStatus() == gale::key::status::down
&& _event.getChar() == '\r') {
signalEnter.emit();
return true;
}
return false;
}
void ewol::widget::Button::onLostFocus() {
m_buttonPressed = false;
EWOL_VERBOSE(propertyName.get() << " : Remove Focus ...");
CheckStatus();
}
void ewol::widget::Button::CheckStatus() {
if (m_buttonPressed == true) {
changeStatusIn(STATUS_PRESSED);
return;
}
if (m_mouseHover == true) {
changeStatusIn(STATUS_HOVER);
return;
}
if (*propertyValue == true) {
changeStatusIn(STATUS_DOWN);
}
changeStatusIn(STATUS_UP);
}
void ewol::widget::Button::changeStatusIn(int32_t _newStatusId) {
if (m_shaper.changeStatusIn(_newStatusId) == true) {
m_PCH = getObjectManager().periodicCall.connect(this, &ewol::widget::Button::periodicCall);
markToRedraw();
}
}
void ewol::widget::Button::periodicCall(const ewol::event::Time& _event) {
if (m_shaper.periodicCall(_event) == false) {
m_PCH.disconnect();
}
markToRedraw();
}
void ewol::widget::Button::onChangePropertyShape() {
m_shaper.setSource(*propertyShape);
markToRedraw();
}
void ewol::widget::Button::onChangePropertyValue() {
if (*propertyToggleMode == true) {
if (*propertyValue == false) {
m_idWidgetDisplayed = 0;
} else {
m_idWidgetDisplayed = 1;
}
}
if (*propertyEnableSingle == true) {
if ( m_idWidgetDisplayed == 0
&& m_subWidget[0] == null
&& m_subWidget[1] != null) {
m_idWidgetDisplayed = 1;
} else if ( m_idWidgetDisplayed == 1
&& m_subWidget[1] == null
&& m_subWidget[0] != null) {
m_idWidgetDisplayed = 0;
}
}
CheckStatus();
markToRedraw();
}
void ewol::widget::Button::onChangePropertyLock() {
if(ewol::widget::Button::lockAccess == *propertyLock) {
m_buttonPressed = false;
m_mouseHover = false;
}
CheckStatus();
markToRedraw();
}
void ewol::widget::Button::onChangePropertyToggleMode() {
if (*propertyValue == true) {
propertyValue.setDirect(false);
// TODO : change display and send event ...
}
if (*propertyToggleMode == false) {
m_idWidgetDisplayed = 0;
} else {
if (*propertyValue == false) {
m_idWidgetDisplayed = 0;
} else {
m_idWidgetDisplayed = 1;
}
}
if (*propertyEnableSingle == true) {
if ( m_idWidgetDisplayed == 0
&& m_subWidget[0] == null
&& m_subWidget[1] != null) {
m_idWidgetDisplayed = 1;
} else if ( m_idWidgetDisplayed == 1
&& m_subWidget[1] == null
&& m_subWidget[0] != null) {
m_idWidgetDisplayed = 0;
}
}
CheckStatus();
markToRedraw();
}
void ewol::widget::Button::onChangePropertyEnableSingle() {
if (*propertyEnableSingle == true) {
if ( m_idWidgetDisplayed == 0
&& m_subWidget[0] == null
&& m_subWidget[1] != null) {
m_idWidgetDisplayed = 1;
} else if ( m_idWidgetDisplayed == 1
&& m_subWidget[1] == null
&& m_subWidget[0] != null) {
m_idWidgetDisplayed = 0;
} else if ( m_subWidget[0] == null
&& m_subWidget[1] == null) {
m_idWidgetDisplayed = 0;
}
}
}

View File

@ -0,0 +1,107 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Text.hpp>
#include <ewol/compositing/Image.hpp>
#include <ewol/compositing/Shaper.hpp>
#include <ewol/widget/Container2.hpp>
#include <ewol/widget/Manager.hpp>
#include <esignal/Signal.hpp>
namespace ewol {
namespace widget {
class Button;
using ButtonShared = ememory::SharedPtr<ewol::widget::Button>;
using ButtonWeak = ememory::WeakPtr<ewol::widget::Button>;
/**
* @brief a composed button is a button with an inside composed with the specify XML element
* ==> this permit to generate standard element simple
*/
class Button : public ewol::widget::Container2 {
public:
enum buttonLock{
lockNone, //!< normal status of the button
lockWhenPressed, //!< When the state is set in pressed, the status stay in this one
lockWhenReleased, //!< When the state is set in not pressed, the status stay in this one
lockAccess, //!< all event are trashed == > acctivity of the button is disable
};
public: // Event list
esignal::Signal<> signalPressed;
esignal::Signal<> signalDown;
esignal::Signal<> signalUp;
esignal::Signal<> signalEnter;
esignal::Signal<> signalLeave;
esignal::Signal<bool> signalValue;
public: // propertie list
eproperty::Value<etk::Uri> propertyShape; //!< shaper name property
eproperty::Value<bool> propertyValue; //!< Current state of the button.
eproperty::List<enum buttonLock> propertyLock; //!< Current lock state of the button.
eproperty::Value<bool> propertyToggleMode; //!< The button is able to toggle.
eproperty::Value<bool> propertyEnableSingle; //!< When a single subwidget is set display all time it.
private:
ewol::compositing::Shaper m_shaper; //!< Compositing theme.
protected:
/**
* @brief Constructor
* @param[in] _shaperName Shaper file properties
*/
Button();
void init() override;
public:
DECLARE_WIDGET_FACTORY(Button, "Button");
/**
* @brief Destructor
*/
virtual ~Button();
private:
bool m_mouseHover; //!< Flag to know where the mouse is (inside the displayed widget (if not fill)).
bool m_buttonPressed; //!< Flag to know if the button is curently pressed.
// hover area :
vec2 m_selectableAreaPos; //!< Start position of the events
vec2 m_selectableAreaSize; //!< size of the event positions
private:
/**
* @brief internal system to change the property of the current status
* @param[in] _newStatusId new state
*/
void changeStatusIn(int32_t _newStatusId);
/**
* @brief update the status with the internal satte of the button ...
*/
void CheckStatus();
protected: // Derived function
virtual void onDraw() override;
public:
void calculateMinMaxSize() override;
void onChangeSize() override;
void onRegenerateDisplay() override;
bool onEventInput(const ewol::event::Input& _event) override;
bool onEventEntry(const ewol::event::Entry& _event) override;
void onDetectPresenceToggleWidget() override {
propertyToggleMode.set(true);
}
protected:
esignal::Connection m_PCH; //!< Periodic Call Handle to remove it when needed
/**
* @brief Periodic call to update grapgic display
* @param[in] _event Time generic event
*/
void periodicCall(const ewol::event::Time& _event);
void onLostFocus() override;
protected:
virtual void onChangePropertyShape();
virtual void onChangePropertyValue();
virtual void onChangePropertyLock();
virtual void onChangePropertyToggleMode();
virtual void onChangePropertyEnableSingle();
};
};
};

View File

@ -0,0 +1,228 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/widget/ButtonColor.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/widget/meta/ColorChooser.hpp>
#include <ewol/widget/Windows.hpp>
#include <ewol/ewol.hpp>
#include <ewol/object/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::ButtonColor);
// DEFINE for the shader display system :
#define STATUS_UP (0)
#define STATUS_HOVER (2)
#define STATUS_PRESSED (1)
#define STATUS_DOWN (3)
ewol::widget::ButtonColor::ButtonColor() :
signalChange(this, "change", "Button color change value"),
propertyValue(this, "color", etk::color::black, "Current color", &ewol::widget::ButtonColor::onChangePropertyValue),
propertyShape(this, "shape", etk::Uri("THEME_GUI:///Button.json?lib=ewol"), "shape of the widget", &ewol::widget::ButtonColor::onChangePropertyShape),
m_widgetContextMenu(null) {
addObjectType("ewol::widget::ButtonColor");
changeStatusIn(STATUS_UP);
// Limit event at 1:
setMouseLimit(1);
propertyCanFocus.setDirectCheck(true);
}
void ewol::widget::ButtonColor::init() {
ewol::Widget::init();
propertyShape.notifyChange();
propertyValue.notifyChange();
}
ewol::widget::ButtonColor::~ButtonColor() {
}
void ewol::widget::ButtonColor::calculateMinMaxSize() {
ewol::Padding padding = m_shaper.getPadding();
etk::String label = propertyValue.getString();
vec3 minSize = m_text.calculateSize(label);
m_minSize.setX(padding.x()*2 + minSize.x() + 7);
m_minSize.setY(padding.y()*2 + minSize.y() );
markToRedraw();
}
void ewol::widget::ButtonColor::onDraw() {
m_shaper.draw();
m_text.draw();
}
void ewol::widget::ButtonColor::onRegenerateDisplay() {
if (needRedraw() == false) {
return;
}
EWOL_DEBUG("redraw");
m_text.clear();
m_shaper.clear();
ewol::Padding padding = m_shaper.getPadding();
etk::String label = propertyValue.getString();
ivec2 localSize = m_minSize;
vec3 tmpOrigin((m_size.x() - m_minSize.x()) / 2.0,
(m_size.y() - m_minSize.y()) / 2.0,
0);
// no change for the text orogin :
vec3 tmpTextOrigin((m_size.x() - m_minSize.x()) / 2.0,
(m_size.y() - m_minSize.y()) / 2.0,
0);
if (propertyFill->x() == true) {
localSize.setX(m_size.x());
tmpOrigin.setX(0);
tmpTextOrigin.setX(0);
}
if (propertyFill->y() == true) {
localSize.setY(m_size.y());
}
tmpOrigin += vec3(padding.xLeft(), padding.yButtom(), 0);
tmpTextOrigin += vec3(padding.xLeft(), padding.yButtom(), 0);
localSize -= ivec2(padding.x(), padding.y());
// clean the element
m_text.reset();
if( propertyValue.get().r() < 100
|| propertyValue.get().g() < 100
|| propertyValue.get().b() < 100) {
m_text.setColor(etk::color::white);
} else {
m_text.setColor(etk::color::black);
}
m_text.setPos(tmpTextOrigin);
m_text.setColorBg(propertyValue.get());
m_text.setTextAlignement(tmpTextOrigin.x(), tmpTextOrigin.x()+localSize.x(), ewol::compositing::alignCenter);
m_text.print(label);
if (propertyFill->y() == true) {
tmpOrigin.setY(padding.yButtom());
}
// selection area :
m_selectableAreaPos = vec2(tmpOrigin.x()-padding.xLeft(), tmpOrigin.y()-padding.yButtom());
m_selectableAreaSize = localSize + vec2(padding.x(),padding.y());
vec3 tmpp = m_text.calculateSize(label);
m_shaper.setShape(m_selectableAreaPos,
m_selectableAreaSize,
vec2(tmpTextOrigin.x(), tmpTextOrigin.y()),
vec2(tmpp.x(), tmpp.y()));
}
bool ewol::widget::ButtonColor::onEventInput(const ewol::event::Input& _event) {
bool previousHoverState = m_mouseHover;
if(gale::key::status::leave == _event.getStatus()) {
m_mouseHover = false;
m_buttonPressed = false;
} else {
vec2 relativePos = relativePosition(_event.getPos());
// prevent error from ouside the button
if( relativePos.x() < m_selectableAreaPos.x()
|| relativePos.y() < m_selectableAreaPos.y()
|| relativePos.x() > m_selectableAreaPos.x() + m_selectableAreaSize.x()
|| relativePos.y() > m_selectableAreaPos.y() + m_selectableAreaSize.y() ) {
m_mouseHover = false;
m_buttonPressed = false;
} else {
m_mouseHover = true;
}
}
bool previousPressed = m_buttonPressed;
//EWOL_DEBUG("Event on BT ... mouse position : " << m_mouseHover);
if (true == m_mouseHover) {
if (1 == _event.getId()) {
if(gale::key::status::down == _event.getStatus()) {
m_buttonPressed = true;
markToRedraw();
}
if(gale::key::status::up == _event.getStatus()) {
m_buttonPressed = false;
markToRedraw();
}
if(gale::key::status::pressSingle == _event.getStatus()) {
m_buttonPressed = false;
m_mouseHover = false;
// create a context menu :
m_widgetContextMenu = ewol::widget::ContextMenu::create();
if (m_widgetContextMenu == null) {
EWOL_ERROR("Allocation Error");
return true;
}
vec2 tmpPos = m_origin + m_selectableAreaPos + m_selectableAreaSize;
tmpPos.setX( tmpPos.x() - m_minSize.x()/2.0);
m_widgetContextMenu->setPositionMark(ewol::widget::ContextMenu::markButtom, tmpPos );
ewol::widget::ColorChooserShared myColorChooser = widget::ColorChooser::create();
myColorChooser->propertyValue.set(propertyValue.get());
// set it in the pop-up-system :
m_widgetContextMenu->setSubWidget(myColorChooser);
myColorChooser->signalChange.connect(sharedFromThis(), &ewol::widget::ButtonColor::onCallbackColorChange);
ewol::widget::WindowsShared currentWindows = getWindows();
if (currentWindows == null) {
EWOL_ERROR("Can not get the curent Windows...");
m_widgetContextMenu.reset();
} else {
currentWindows->popUpWidgetPush(m_widgetContextMenu);
}
markToRedraw();
}
}
}
if( m_mouseHover != previousHoverState
|| m_buttonPressed != previousPressed) {
if (m_buttonPressed == true) {
changeStatusIn(STATUS_PRESSED);
} else {
if (m_mouseHover == true) {
changeStatusIn(STATUS_HOVER);
} else {
changeStatusIn(STATUS_UP);
}
}
}
return m_mouseHover;
}
void ewol::widget::ButtonColor::onCallbackColorChange(const etk::Color<>& _color) {
propertyValue.set(_color);
}
void ewol::widget::ButtonColor::changeStatusIn(int32_t _newStatusId) {
if (m_shaper.changeStatusIn(_newStatusId) == true) {
m_PCH = getObjectManager().periodicCall.connect(this, &ewol::widget::ButtonColor::periodicCall);
markToRedraw();
}
}
void ewol::widget::ButtonColor::periodicCall(const ewol::event::Time& _event) {
if (m_shaper.periodicCall(_event) == false) {
m_PCH.disconnect();
}
markToRedraw();
}
void ewol::widget::ButtonColor::onChangePropertyValue() {
signalChange.emit(propertyValue);
}
void ewol::widget::ButtonColor::onChangePropertyShape() {
m_shaper.setSource(propertyShape.get());
markToRedraw();
}

View File

@ -0,0 +1,78 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Button.hpp>
#include <ewol/widget/ContextMenu.hpp>
#include <ewol/compositing/Text.hpp>
#include <ewol/compositing/Shaper.hpp>
#include <ewol/widget/Widget.hpp>
#include <ewol/widget/Manager.hpp>
#include <esignal/Signal.hpp>
namespace ewol {
namespace widget {
class ButtonColor;
using ButtonColorShared = ememory::SharedPtr<ewol::widget::ButtonColor>;
using ButtonColorWeak = ememory::WeakPtr<ewol::widget::ButtonColor>;
class ButtonColor : public ewol::Widget {
public: // signals
esignal::Signal<etk::Color<>> signalChange;
public: // properties
eproperty::Value<etk::Color<>> propertyValue; //!< Current color.
eproperty::Value<etk::Uri> propertyShape; //!< Current color.
private:
ewol::compositing::Shaper m_shaper; //!< Compositing theme.
ewol::compositing::Text m_text; //!< Compositing Test display.
ewol::widget::ContextMenuShared m_widgetContextMenu; //!< Specific context menu.
bool m_mouseHover; //!< Flag to know where the mouse is (inside the displayed widget (if not fill)).
bool m_buttonPressed; //!< Flag to know if the button is curently pressed.
// hover area :
vec2 m_selectableAreaPos; //!< Start position of the events
vec2 m_selectableAreaSize; //!< size of the event positions
protected:
/**
* @brief Main constructor.
* @param[in] _baseColor basic displayed color.
* @param[in] _shaperName The new shaper filename.
*/
ButtonColor();
void init() override;
public:
DECLARE_WIDGET_FACTORY(ButtonColor, "ButtonColor");
/**
* @brief Main destructor.
*/
virtual ~ButtonColor();
protected:
void onDraw() override;
public:
void calculateMinMaxSize() override;
void onRegenerateDisplay() override;
bool onEventInput(const ewol::event::Input& _event) override;
private:
/**
* @brief internal system to change the property of the current status
* @param[in] _newStatusId new state
*/
void changeStatusIn(int32_t _newStatusId);
esignal::Connection m_PCH; //!< Periodic call handle to remove it when needed
/**
* @brief Periodic call to update grapgic display
* @param[in] _event Time generic event
*/
void periodicCall(const ewol::event::Time& _event);
// Callback function:
void onCallbackColorChange(const etk::Color<>& _color);
protected:
virtual void onChangePropertyValue();
virtual void onChangePropertyShape();
};
};
};

View File

@ -0,0 +1,216 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/widget/CheckBox.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/object/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::CheckBox);
// DEFINE for the shader display system :
#define STATUS_UP (0)
#define STATUS_HOVER (2)
#define STATUS_PRESSED (1)
#define STATUS_SELECTED (2)
ewol::widget::CheckBox::CheckBox() :
signalPressed(this, "pressed", "CheckBox is pressed"),
signalDown(this, "down", "CheckBox is DOWN"),
signalUp(this, "up", "CheckBox is UP"),
signalEnter(this, "enter", "The cursor enter inside the CheckBox"),
signalValue(this, "value", "CheckBox value change"),
propertyValue(this, "value",
false,
"Basic value of the widget",
&ewol::widget::CheckBox::onChangePropertyValue),
propertyShape(this, "shape",
etk::Uri("THEME_GUI:///CheckBox.json?lib=ewol"),
"The display name for config file",
&ewol::widget::CheckBox::onChangePropertyShape),
m_mouseHover(false),
m_buttonPressed(false),
m_selectableAreaPos(0,0),
m_selectableAreaSize(0,0),
m_shaperIdSize(-1),
m_shaperIdSizeInsize(-1) {
addObjectType("ewol::widget::CheckBox");
// shaper satatus update:
CheckStatus();
propertyCanFocus.setDirectCheck(true);
// Limit event at 1:
setMouseLimit(1);
}
void ewol::widget::CheckBox::init() {
ewol::widget::Container2::init();
propertyShape.notifyChange();
}
ewol::widget::CheckBox::~CheckBox() {
}
void ewol::widget::CheckBox::onChangeSize() {
ewol::Padding padding = m_shaper.getPadding();
float boxSize = m_shaper.getConfigNumber(m_shaperIdSize);
padding.setXLeft(padding.xLeft()*2.0f + boxSize);
ewol::Padding ret = onChangeSizePadded(padding);
EWOL_DEBUG(" configuring : padding=" << padding << " boxSize=" << boxSize << "");
m_selectableAreaPos = vec2(ret.xLeft()/*-boxSize*/, ret.yButtom());
m_selectableAreaSize = m_size - (m_selectableAreaPos + vec2(ret.xRight(), ret.yTop()));
}
void ewol::widget::CheckBox::calculateMinMaxSize() {
ewol::Padding padding = m_shaper.getPadding();
float boxSize = m_shaper.getConfigNumber(m_shaperIdSize);
padding.setXLeft(padding.xLeft()*2.0f + boxSize);
calculateMinMaxSizePadded(padding);
if (m_minSize.y() < padding.y()+boxSize) {
m_minSize.setY(padding.y()+boxSize);
}
}
void ewol::widget::CheckBox::onDraw() {
// draw the shaaper (if needed indeed)
m_shaper.draw();
}
void ewol::widget::CheckBox::onRegenerateDisplay() {
ewol::widget::Container2::onRegenerateDisplay();
if (needRedraw() == false) {
return;
}
ewol::Padding padding = m_shaper.getPadding();
float boxSize = m_shaper.getConfigNumber(m_shaperIdSize);
float boxInside = m_shaper.getConfigNumber(m_shaperIdSizeInsize);
m_shaper.clear();
EWOL_DEBUG(" configuring : boxSize=" << boxSize << " boxInside=" << boxInside << "");
vec2 origin(m_selectableAreaPos + vec2(0, (m_selectableAreaSize.y() - (boxSize+padding.y()))*0.5f));
vec2 size = vec2(boxSize+padding.x(), boxSize+padding.y());
vec2 origin2 = m_selectableAreaPos + vec2((boxSize-boxInside)*0.5f, (m_selectableAreaSize.y() - (boxInside+padding.y()))*0.5f);
vec2 size2 = vec2(boxInside+padding.x(), boxInside+padding.y());
m_shaper.setShape(vec2ClipInt32(origin),
vec2ClipInt32(size),
vec2ClipInt32(origin2+vec2(padding.xLeft(),padding.yButtom()) ),
vec2ClipInt32(size2-vec2(padding.x(),padding.y()) ));
}
bool ewol::widget::CheckBox::onEventInput(const ewol::event::Input& _event) {
EWOL_VERBOSE("Event on BT : " << _event);
bool previousHoverState = m_mouseHover;
if( gale::key::status::leave == _event.getStatus()
|| gale::key::status::abort == _event.getStatus()) {
m_mouseHover = false;
m_buttonPressed = false;
} else {
vec2 relativePos = relativePosition(_event.getPos());
// prevent error from ouside the button
if( relativePos.x() < m_selectableAreaPos.x()
|| relativePos.y() < m_selectableAreaPos.y()
|| relativePos.x() > m_selectableAreaPos.x() + m_selectableAreaSize.x()
|| relativePos.y() > m_selectableAreaPos.y() + m_selectableAreaSize.y() ) {
m_mouseHover = false;
m_buttonPressed = false;
} else {
m_mouseHover = true;
}
}
bool previousPressed = m_buttonPressed;
EWOL_VERBOSE("Event on BT ... mouse hover : " << m_mouseHover);
if (m_mouseHover == true) {
if (_event.getId() == 1) {
if(gale::key::status::down == _event.getStatus()) {
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalDown);
signalDown.emit();
m_buttonPressed = true;
markToRedraw();
}
if(gale::key::status::up == _event.getStatus()) {
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalUp);
signalUp.emit();
m_buttonPressed = false;
markToRedraw();
}
if(gale::key::status::pressSingle == _event.getStatus()) {
// inverse value :
propertyValue.set((*propertyValue)?false:true);
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalPressed);
signalPressed.emit();
EWOL_VERBOSE(*propertyName << " : Generate event : " << signalValue << " val=" << propertyValue );
signalValue.emit(*propertyValue);
markToRedraw();
}
}
}
if( m_mouseHover != previousHoverState
|| m_buttonPressed != previousPressed) {
CheckStatus();
}
return m_mouseHover;
}
bool ewol::widget::CheckBox::onEventEntry(const ewol::event::Entry& _event) {
//EWOL_DEBUG("BT PRESSED : \"" << UTF8_data << "\" size=" << strlen(UTF8_data));
if( _event.getType() == gale::key::keyboard::character
&& _event.getStatus() == gale::key::status::down
&& _event.getChar() == '\r') {
signalEnter.emit();
return true;
}
return false;
}
void ewol::widget::CheckBox::CheckStatus() {
if (m_shaper.setState(*propertyValue==true?1:0) == true) {
markToRedraw();
}
if (m_buttonPressed == true) {
changeStatusIn(STATUS_PRESSED);
return;
}
if (m_mouseHover == true) {
changeStatusIn(STATUS_HOVER);
return;
}
changeStatusIn(STATUS_UP);
}
void ewol::widget::CheckBox::changeStatusIn(int32_t _newStatusId) {
if (m_shaper.changeStatusIn(_newStatusId) == true) {
m_PCH = getObjectManager().periodicCall.connect(this, &ewol::widget::CheckBox::periodicCall);
markToRedraw();
}
}
void ewol::widget::CheckBox::periodicCall(const ewol::event::Time& _event) {
if (m_shaper.periodicCall(_event) == false) {
m_PCH.disconnect();
}
markToRedraw();
}
void ewol::widget::CheckBox::onChangePropertyShape() {
m_shaper.setSource(*propertyShape);
m_shaperIdSize = m_shaper.requestConfig("box-size");
m_shaperIdSizeInsize = m_shaper.requestConfig("box-inside");
markToRedraw();
}
void ewol::widget::CheckBox::onChangePropertyValue() {
if (*propertyValue == false) {
m_idWidgetDisplayed = convertId(0);
} else {
m_idWidgetDisplayed = convertId(1);
}
CheckStatus();
markToRedraw();
m_shaper.setActivateState(*propertyValue==true?1:0);
}

View File

@ -0,0 +1,85 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Shaper.hpp>
#include <ewol/widget/Container2.hpp>
#include <ewol/widget/Manager.hpp>
#include <esignal/Signal.hpp>
namespace ewol {
namespace widget {
class CheckBox;
using CheckBoxShared = ememory::SharedPtr<ewol::widget::CheckBox>;
using CheckBoxWeak = ememory::WeakPtr<ewol::widget::CheckBox>;
class CheckBox : public ewol::widget::Container2 {
public: // Event list
esignal::Signal<> signalPressed;
esignal::Signal<> signalDown;
esignal::Signal<> signalUp;
esignal::Signal<> signalEnter;
esignal::Signal<bool> signalValue;
public: // propertie list
eproperty::Value<bool> propertyValue; //!< Current state of the checkbox.
eproperty::Value<etk::Uri> propertyShape; //!< shape of the widget
private:
ewol::compositing::Shaper m_shaper; //!< Compositing theme.
bool m_mouseHover; //!< Flag to know where the mouse is (inside the displayed widget (if not fill)).
bool m_buttonPressed; //!< Flag to know if the button is curently pressed.
// hover area :
vec2 m_selectableAreaPos; //!< Start position of the events
vec2 m_selectableAreaSize; //!< size of the event positions
// shaper ids:
int32_t m_shaperIdSize;
int32_t m_shaperIdSizeInsize;
protected:
/**
* @brief Main checkbox constructor
* @param[in] _shaperName Shaper file properties
*/
CheckBox();
void init() override;
public:
DECLARE_WIDGET_FACTORY(CheckBox, "CheckBox");
/**
* @brief main destructor.
*/
virtual ~CheckBox();
protected:
/**
* @brief internal system to change the property of the current status
* @param[in] _newStatusId new state
*/
void changeStatusIn(int32_t _newStatusId);
/**
* @brief update the status with the internal satte of the button ...
*/
void CheckStatus();
protected:
void onDraw() override;
public:
void calculateMinMaxSize() override;
void onChangeSize() override;
void onRegenerateDisplay() override;
bool onEventInput(const ewol::event::Input& _event) override;
bool onEventEntry(const ewol::event::Entry& _event) override;
protected:
esignal::Connection m_PCH; //!< Periodic call handle to remove it when needed
/**
* @brief Periodic call to update grapgic display
* @param[in] _event Time generic event
*/
void periodicCall(const ewol::event::Time& _event);
protected:
virtual void onChangePropertyShape();
virtual void onChangePropertyValue();
};
};
};

View File

@ -0,0 +1,223 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/widget/ColorBar.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/widget/Manager.hpp>
#include <etk/Color.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::ColorBar);
ewol::widget::ColorBar::ColorBar() :
signalChange(this, "change", "Color value change"),
propertyValue(this, "color",
etk::color::black,
"Current color",
&ewol::widget::ColorBar::onChangePropertyValue) {
addObjectType("ewol::widget::ColorBar");
m_currentUserPos.setValue(0,0);
propertyCanFocus.setDirectCheck(true);
setMouseLimit(1);
}
ewol::widget::ColorBar::~ColorBar() {
}
void ewol::widget::ColorBar::calculateMinMaxSize() {
m_minSize.setValue(160, 80);
markToRedraw();
}
static etk::Color<> s_listColorWhite(0xFF, 0xFF, 0xFF, 0xFF);
static etk::Color<> s_listColorBlack(0x00, 0x00, 0x00, 0xFF);
#define NB_BAND_COLOR (6)
static etk::Color<> s_listColor[NB_BAND_COLOR+1] = {
etk::Color<>(0xFF, 0x00, 0x00, 0xFF),
etk::Color<>(0xFF, 0xFF, 0x00, 0xFF),
etk::Color<>(0x00, 0xFF, 0x00, 0xFF),
etk::Color<>(0x00, 0xFF, 0xFF, 0xFF),
etk::Color<>(0x00, 0x00, 0xFF, 0xFF),
etk::Color<>(0xFF, 0x00, 0xFF, 0xFF),
etk::Color<>(0xFF, 0x00, 0x00, 0xFF)};
void ewol::widget::ColorBar::onChangePropertyValue() {
propertyValue.getDirect().setA(0xFF);
// estimate the cursor position:
EWOL_TODO("Later when really needed ...");
}
void ewol::widget::ColorBar::onDraw() {
m_draw.draw();
}
void ewol::widget::ColorBar::onRegenerateDisplay() {
if (needRedraw() == true) {
return;
}
// clean the object list ...
m_draw.clear();
int32_t tmpSizeX = m_minSize.x();
int32_t tmpSizeY = m_minSize.y();
int32_t tmpOriginX = (m_size.x() - m_minSize.x()) / 2;
int32_t tmpOriginY = (m_size.y() - m_minSize.y()) / 2;
if (propertyFill->x() == true) {
tmpSizeX = m_size.x();
tmpOriginX = 0;
}
if (propertyFill->y() == true) {
tmpSizeY = m_size.y();
tmpOriginY = 0;
}
for(int32_t iii=0; iii<NB_BAND_COLOR ; iii++) {
/* Step 1 :
*
* **
* ****
* ******
* ********
*/
m_draw.setColor(s_listColorWhite);
m_draw.setPos(vec3(tmpOriginX + (iii)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY, 0) );
m_draw.addVertex();
m_draw.setColor(s_listColor[iii+1]);
m_draw.setPos(vec3(tmpOriginX + (iii+1)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY/2, 0) );
m_draw.addVertex();
m_draw.setColor(s_listColor[iii]);
m_draw.setPos(vec3(tmpOriginX + iii*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY/2, 0) );
m_draw.addVertex();
/* Step 2 :
* ********
* ******
* ****
* **
*
*/
m_draw.setColor(s_listColorWhite);
m_draw.setPos(vec3(tmpOriginX + iii*(tmpSizeX/NB_BAND_COLOR), tmpOriginY, 0) );
m_draw.addVertex();
m_draw.setColor(s_listColorWhite);
m_draw.setPos(vec3(tmpOriginX + (iii+1)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY, 0) );
m_draw.addVertex();
m_draw.setColor(s_listColor[iii+1]);
m_draw.setPos(vec3(tmpOriginX + (iii+1)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY/2, 0) );
m_draw.addVertex();
/* Step 3 :
*
* **
* ****
* ******
* ********
*/
m_draw.setColor(s_listColor[iii]);
m_draw.setPos(vec3(tmpOriginX + iii*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY/2, 0));
m_draw.addVertex();
m_draw.setColor(s_listColorBlack);
m_draw.setPos(vec3(tmpOriginX + (iii+1)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY, 0));
m_draw.addVertex();
m_draw.setColor(s_listColorBlack);
m_draw.setPos(vec3(tmpOriginX + iii*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY, 0));
m_draw.addVertex();
/* Step 4 :
* ********
* ******
* ****
* **
*
*/
m_draw.setColor(s_listColor[iii]);
m_draw.setPos(vec3(tmpOriginX + iii*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY/2, 0));
m_draw.addVertex();
m_draw.setColor(s_listColor[iii+1]);
m_draw.setPos(vec3(tmpOriginX + (iii+1)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY/2, 0));
m_draw.addVertex();
m_draw.setColor(s_listColorBlack);
m_draw.setPos(vec3(tmpOriginX + (iii+1)*(tmpSizeX/NB_BAND_COLOR), tmpOriginY+tmpSizeY, 0));
m_draw.addVertex();
}
if (m_currentUserPos.y() > 0.5) {
m_draw.setColor(etk::color::white);
} else {
m_draw.setColor(etk::color::black);
}
m_draw.setPos(vec3(m_currentUserPos.x()*m_size.x(), m_currentUserPos.y()*m_size.y(), 0) );
m_draw.setThickness(1);
m_draw.circle(3.0);
}
bool ewol::widget::ColorBar::onEventInput(const ewol::event::Input& _event) {
vec2 relativePos = relativePosition(_event.getPos());
//EWOL_DEBUG("Event on BT ...");
if (1 == _event.getId()) {
relativePos.setValue( etk::avg(0.0f, m_size.x(),relativePos.x()),
etk::avg(0.0f, m_size.y(),relativePos.y()) );
if( gale::key::status::pressSingle == _event.getStatus()
|| gale::key::status::move == _event.getStatus()) {
// nothing to do ...
m_currentUserPos.setValue( relativePos.x()/m_size.x(),
relativePos.y()/m_size.y() );
markToRedraw();
// == > try to estimate color
EWOL_VERBOSE("event on (" << relativePos.x() << "," << relativePos.y() << ")");
int32_t bandID = (int32_t)(relativePos.x()/(m_size.x()/6));
float localPos = relativePos.x() - (m_size.x()/6) * bandID;
float poroportionnalPos = localPos/(m_size.x()/6);
EWOL_VERBOSE("bandId=" << bandID << " relative pos=" << localPos);
etk::Color<> estimateColor = etk::color::white;
if (s_listColor[bandID].r() == s_listColor[bandID+1].r()) {
estimateColor.setR(s_listColor[bandID].r());
} else if (s_listColor[bandID].r() < s_listColor[bandID+1].r()) {
estimateColor.setR(s_listColor[bandID].r() + (s_listColor[bandID+1].r()-s_listColor[bandID].r())*poroportionnalPos);
} else {
estimateColor.setR(s_listColor[bandID+1].r() + (s_listColor[bandID].r()-s_listColor[bandID+1].r())*(1-poroportionnalPos));
}
if (s_listColor[bandID].g() == s_listColor[bandID+1].g()) {
estimateColor.setG(s_listColor[bandID].g());
} else if (s_listColor[bandID].g() < s_listColor[bandID+1].g()) {
estimateColor.setG(s_listColor[bandID].g() + (s_listColor[bandID+1].g()-s_listColor[bandID].g())*poroportionnalPos);
} else {
estimateColor.setG(s_listColor[bandID+1].g() + (s_listColor[bandID].g()-s_listColor[bandID+1].g())*(1-poroportionnalPos));
}
if (s_listColor[bandID].b() == s_listColor[bandID+1].b()) {
estimateColor.setB(s_listColor[bandID].b());
} else if (s_listColor[bandID].b() < s_listColor[bandID+1].b()) {
estimateColor.setB(s_listColor[bandID].b() + (s_listColor[bandID+1].b()-s_listColor[bandID].b())*poroportionnalPos);
} else {
estimateColor.setB(s_listColor[bandID+1].b() + (s_listColor[bandID].b()-s_listColor[bandID+1].b())*(1-poroportionnalPos));
}
// step 2 generate the white and black ...
if (m_currentUserPos.y() == 0.5) {
// nothing to do ... just get the current color ...
} else if (m_currentUserPos.y() < 0.5) {
float poroportionnalWhite = (0.5-m_currentUserPos.y())*2.0;
estimateColor.setR(estimateColor.r() + (0xFF-estimateColor.r())*poroportionnalWhite);
estimateColor.setG(estimateColor.g() + (0xFF-estimateColor.g())*poroportionnalWhite);
estimateColor.setB(estimateColor.b() + (0xFF-estimateColor.b())*poroportionnalWhite);
} else {
float poroportionnalBlack = (m_currentUserPos.y()-0.5)*2.0;
estimateColor.setR(estimateColor.r() - estimateColor.r()*poroportionnalBlack);
estimateColor.setG(estimateColor.g() - estimateColor.g()*poroportionnalBlack);
estimateColor.setB(estimateColor.b() - estimateColor.b()*poroportionnalBlack);
}
if(*propertyValue != estimateColor) {
propertyValue.set(estimateColor);
signalChange.emit(*propertyValue);
}
return true;
}
}
return false;
}

View File

@ -0,0 +1,44 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <etk/Color.hpp>
#include <ewol/widget/Widget.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <esignal/Signal.hpp>
namespace ewol {
namespace widget {
class ColorBar;
using ColorBarShared = ememory::SharedPtr<ewol::widget::ColorBar>;
using ColorBarWeak = ememory::WeakPtr<ewol::widget::ColorBar>;
class ColorBar : public ewol::Widget {
public: // signals
esignal::Signal<etk::Color<>> signalChange;
public:
eproperty::Value<etk::Color<>> propertyValue;
protected:
ColorBar();
public:
DECLARE_WIDGET_FACTORY(ColorBar, "ColorBar");
virtual ~ColorBar();
private:
ewol::compositing::Drawing m_draw; //!< Compositing drawing element
vec2 m_currentUserPos;
protected:
void onDraw() override;
public:
void calculateMinMaxSize() override;
void onRegenerateDisplay() override;
bool onEventInput(const ewol::event::Input& _event) override;
protected:
virtual void onChangePropertyValue();
};
};
};

View File

@ -0,0 +1,162 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/Composer.hpp>
#include <etk/uri/uri.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::Composer);
ewol::widget::Composer::Composer() :
propertyRemoveIfUnderRemove(this, "remove-if-under-remove", true, "Demand the remove iof the widget if the subObject demand a remove"),
propertySubFile(this, "sub-file", "", "compose with a subXML file", &ewol::widget::Composer::onChangePropertySubFile) {
addObjectType("ewol::widget::Composer");
// nothing to do ...
}
ewol::WidgetShared ewol::widget::composerGenerateFile(const etk::Uri& _uri, uint64_t _id) {
etk::String tmpData;
if (etk::uri::readAll(_uri, tmpData) == false) {
EWOL_ERROR("Can not read the file: " << _uri);
return null;
}
return ewol::widget::composerGenerateString(tmpData, _id);
}
ewol::WidgetShared ewol::widget::composerGenerateString(const etk::String& _data, uint64_t _id) {
ewol::widget::Manager& widgetManager = ewol::getContext().getWidgetManager();
if (_data == "") {
return null;
}
exml::Document doc;
etk::String tmpData = _data;
// replace all elements:
if (_id != 0) {
tmpData.replace("{ID}", etk::toString(_id));
}
if (doc.parse(tmpData) == false) {
EWOL_ERROR(" can not load file XML string...");
return null;
}
exml::Element root = doc.toElement();
if (root.nodes.size() == 0) {
EWOL_ERROR(" (l ?) No node in the XML file/string.");
return null;
}
if (root.nodes.size() > 1) {
EWOL_WARNING(" (l ?) More than 1 node in the XML file/string. (JUST parse the first)");
}
exml::Element pNode = root.nodes[0].toElement();
if (pNode.exist() == false) {
EWOL_ERROR(" (l ?) No node in the XML file/string. {2}");
return null;
}
etk::String widgetName = pNode.getValue();
if (widgetManager.exist(widgetName) == false) {
EWOL_ERROR("(l " << pNode.getPos() << ") Unknown basic node='" << widgetName << "' not in : [" << widgetManager.list() << "]" );
return null;
}
EWOL_DEBUG("try to create subwidget : '" << widgetName << "'");
ewol::WidgetShared tmpWidget = widgetManager.create(widgetName);
if (tmpWidget == null) {
EWOL_ERROR ("(l " << pNode.getPos() << ") Can not create the widget : '" << widgetName << "'");
return null;
}
if (tmpWidget->loadXML(pNode) == false) {
EWOL_ERROR ("(l " << pNode.getPos() << ") can not load widget properties : '" << widgetName << "'");
}
return tmpWidget;
}
ewol::widget::Composer::~Composer() {
}
bool ewol::widget::Composer::loadFromFile(const etk::Uri& _uri, uint64_t _id) {
etk::String tmpData;
if (etk::uri::readAll(_uri, tmpData) == false) {
EWOL_ERROR("Can not read the file: " << _uri);
return false;
}
return loadFromString(tmpData, _id);
}
bool ewol::widget::Composer::loadFromString(const etk::String& _composerXmlString, uint64_t _id) {
exml::Document doc;
etk::String tmpData = _composerXmlString;
// replace all elements:
if (_id != 0) {
tmpData.replace("{ID}", etk::toString(_id));
}
if (doc.parse(tmpData) == false) {
EWOL_ERROR(" can not load file XML string...");
return false;
}
exml::Element root = doc.nodes["composer"];
if (root.exist() == false) {
// Maybe a multiple node XML for internal config:
root = doc.toElement();
if (root.exist() == false) {
EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} (l ?) main node not find: 'composer' ...");
return false;
}
if (root.nodes.size() == 0) {
EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} (l ?) no node in the Container XML element.");
return false;
}
}
// call upper class to parse his elements ...
ewol::widget::Container::loadXML(root);
if (m_subWidget == null) {
EWOL_WARNING("Load data from composer and have no under Widget after loading");
if (_composerXmlString.size() != 0) {
EWOL_ERROR("Error Loading XML data : " << _composerXmlString);
return false;
}
}
requestUpdateSize();
return true;
}
void ewol::widget::Composer::requestDestroyFromChild(const ewol::ObjectShared& _child) {
ewol::widget::Container::requestDestroyFromChild(_child);
if (*propertyRemoveIfUnderRemove == true) {
EWOL_DEBUG("Child widget remove ==> auto-remove");
autoDestroy();
}
}
void ewol::widget::Composer::onChangePropertySubFile() {
EWOL_INFO("Load compositing form external file : " << propertySubFile);
if (*propertySubFile == "") {
// remove all elements:
subWidgetRemove();
return;
}
if (loadFromFile(*propertySubFile, getId()) == false) {
EWOL_ERROR("Can not load Player GUI from file ... " << propertySubFile);
return;
}
}
bool ewol::widget::Composer::loadXML(const exml::Element& _node) {
//EWOL_VERBOSE("[" << getId() << "] t=" << getObjectType() << " Load XML (start)");
if (_node.exist() == false) {
return false;
}
// parse generic properties:
ewol::Widget::loadXML(_node);
// parse all the elements:
if (_node.nodes.size() != 0) {
EWOL_ERROR("a composer Node Can not have Sub-element in XML ==> must be done in an external file and load it with attribute: 'sub-file'");
}
//drawWidgetTree();
//EWOL_VERBOSE("[" << getId() << "] t=" << getObjectType() << " Load XML (stop)");
return true;
}

View File

@ -0,0 +1,63 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Container.hpp>
#include <etk/uri/uri.hpp>
namespace ewol {
namespace widget {
class Composer;
using ComposerShared = ememory::SharedPtr<ewol::widget::Composer>;
using ComposerWeak = ememory::WeakPtr<ewol::widget::Composer>;
/**
* @ingroup ewolWidgetGroup
* @brief the composer widget is a widget that create a link on a string.file to parse the data and generate some widget tree
*/
class Composer : public ewol::widget::Container {
public:
eproperty::Value<bool> propertyRemoveIfUnderRemove; //!< Remove the composer if sub element request a remove
eproperty::Value<etk::Uri> propertySubFile; //!< If loading a sub-file, we must do it here ==> permit to configure it in the xml and not have wrong display
protected:
/**
* @brief Constructor
*/
Composer();
public:
DECLARE_WIDGET_FACTORY(Composer, "Composer");
/**
* @brief Destructor
*/
virtual ~Composer();
/**
* @brief load a composition with a file
* @param[in] _uri Name of the file
* @param[in] _id Unique ID that is used in replacing the balise "{ID}" inside the File (do nothing if == 0)
* @return true == > all done OK
* @return false == > some error occured
*/
bool loadFromFile(const etk::Uri& _uri, uint64_t _id=0);
/**
* @brief load a composition with a file
* @param[in] _composerXmlString xml to parse directly
* @param[in] _id Unique ID that is used in replacing the balise "{ID}" inside the String (do nothing if == 0)
* @return true == > all done OK
* @return false == > some error occured
*/
bool loadFromString(const etk::String& _composerXmlString, uint64_t _id=0);
private:
void requestDestroyFromChild(const ewol::ObjectShared& _child) override;
public:
bool loadXML(const exml::Element& _node) override;
protected:
virtual void onChangePropertySubFile();
};
ewol::WidgetShared composerGenerateString(const etk::String& _data = "", uint64_t _id=0);
ewol::WidgetShared composerGenerateFile(const etk::Uri& _uri = "", uint64_t _id=0);
};
};

View File

@ -0,0 +1,215 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/Container.hpp>
#include <ewol/widget/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::Container);
ewol::widget::Container::Container() {
addObjectType("ewol::widget::Container");
// nothing to do ...
}
ewol::widget::Container::~Container() {
subWidgetRemove();
}
ewol::WidgetShared ewol::widget::Container::getSubWidget() {
return m_subWidget;
}
void ewol::widget::Container::setSubWidget(ewol::WidgetShared _newWidget) {
if (_newWidget == null) {
return;
}
subWidgetRemove();
m_subWidget = _newWidget;
if (m_subWidget != null) {
m_subWidget->setParent(sharedFromThis());
}
markToRedraw();
requestUpdateSize();
}
void ewol::widget::Container::subWidgetReplace(const ewol::WidgetShared& _oldWidget,
const ewol::WidgetShared& _newWidget) {
if (m_subWidget != _oldWidget) {
EWOL_WARNING("Request replace with a wrong old widget");
return;
}
m_subWidget->removeParent();
m_subWidget.reset();
m_subWidget = _newWidget;
if (m_subWidget != null) {
m_subWidget->setParent(sharedFromThis());
}
markToRedraw();
requestUpdateSize();
}
void ewol::widget::Container::subWidgetRemove() {
if (m_subWidget != null) {
m_subWidget->removeParent();
m_subWidget.reset();
markToRedraw();
requestUpdateSize();
}
}
void ewol::widget::Container::subWidgetUnLink() {
if (m_subWidget != null) {
m_subWidget->removeParent();
}
m_subWidget.reset();
}
ewol::ObjectShared ewol::widget::Container::getSubObjectNamed(const etk::String& _objectName) {
ewol::ObjectShared tmpObject = ewol::Widget::getSubObjectNamed(_objectName);
if (tmpObject != null) {
return tmpObject;
}
if (m_subWidget != null) {
return m_subWidget->getSubObjectNamed(_objectName);
}
return null;
}
void ewol::widget::Container::systemDraw(const ewol::DrawProperty& _displayProp) {
if (propertyHide.get() == true){
// widget is hidden ...
return;
}
ewol::Widget::systemDraw(_displayProp);
if (m_subWidget != null) {
ewol::DrawProperty prop = _displayProp;
prop.limit(m_origin, m_size);
//EWOL_INFO("Draw : [" << propertyName << "] t=" << getObjectType() << " o=" << m_origin << " s=" << m_size);
m_subWidget->systemDraw(prop);
} else {
EWOL_INFO("[" << getId() << "] ++++++ : [null]");
}
}
void ewol::widget::Container::onChangeSize() {
ewol::Widget::onChangeSize();
if (*propertyHide == true) {
return;
}
if (m_subWidget == null) {
return;
}
vec2 origin = m_origin+m_offset;
vec2 minSize = m_subWidget->getCalculateMinSize();
bvec2 expand = m_subWidget->propertyExpand.get();
origin += ewol::gravityGenerateDelta(propertyGravity.get(), minSize - m_size);
m_subWidget->setOrigin(origin);
m_subWidget->setSize(m_size);
m_subWidget->onChangeSize();
}
void ewol::widget::Container::calculateMinMaxSize() {
// call main class
ewol::Widget::calculateMinMaxSize();
// call sub classes
if (m_subWidget != null) {
m_subWidget->calculateMinMaxSize();
vec2 min = m_subWidget->getCalculateMinSize();
m_minSize.setMax(min);
}
//EWOL_ERROR("[" << getId() << "] Result min size : " << m_minSize);
}
void ewol::widget::Container::onRegenerateDisplay() {
if (m_subWidget != null) {
m_subWidget->onRegenerateDisplay();
}
}
ewol::WidgetShared ewol::widget::Container::getWidgetAtPos(const vec2& _pos) {
if (propertyHide.get() == false) {
if (m_subWidget != null) {
return m_subWidget->getWidgetAtPos(_pos);
}
}
return null;
};
bool ewol::widget::Container::loadXML(const exml::Element& _node) {
if (_node.exist() == false) {
return false;
}
// parse generic properties:
ewol::Widget::loadXML(_node);
// remove previous element:
subWidgetRemove();
// parse all the elements:
for (const auto it : _node.nodes) {
exml::Element pNode = it.toElement();
if (pNode.exist() == false) {
// trash here all that is not element
continue;
}
etk::String widgetName = pNode.getValue();
EWOL_VERBOSE("[" << getId() << "] t=" << getObjectType() << " Load node name : '" << widgetName << "'");
if (getWidgetManager().exist(widgetName) == false) {
EWOL_ERROR("(l " << pNode.getPos() << ") Unknown basic node='" << widgetName << "' not in : [" << getWidgetManager().list() << "]" );
continue;
}
if (getSubWidget() != null) {
EWOL_ERROR("(l " << pNode.getPos() << ") Can only have one subWidget ??? node='" << widgetName << "'" );
continue;
}
EWOL_DEBUG("try to create subwidget : '" << widgetName << "'");
ewol::WidgetShared tmpWidget = getWidgetManager().create(widgetName, pNode);
if (tmpWidget == null) {
EWOL_ERROR ("(l " << pNode.getPos() << ") Can not create the widget : '" << widgetName << "'");
continue;
}
// add widget :
setSubWidget(tmpWidget);
if (tmpWidget->loadXML(pNode) == false) {
EWOL_ERROR ("(l " << pNode.getPos() << ") can not load widget properties : '" << widgetName << "'");
return false;
}
}
if ( _node.nodes.size() != 0
&& m_subWidget == null) {
EWOL_WARNING("Load container with no data inside");
}
return true;
}
void ewol::widget::Container::setOffset(const vec2& _newVal) {
if (m_offset != _newVal) {
ewol::Widget::setOffset(_newVal);
// recalculate the new sise and position of sub widget ...
onChangeSize();
}
}
void ewol::widget::Container::requestDestroyFromChild(const ewol::ObjectShared& _child) {
if (m_subWidget != _child) {
return;
}
if (m_subWidget == null) {
return;
}
m_subWidget->removeParent();
m_subWidget.reset();
markToRedraw();
}
void ewol::widget::Container::drawWidgetTree(int32_t _level) {
ewol::Widget::drawWidgetTree(_level);
_level++;
if (m_subWidget != null) {
m_subWidget->drawWidgetTree(_level);
}
}

View File

@ -0,0 +1,73 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Widget.hpp>
namespace ewol {
namespace widget {
class Container;
using ContainerShared = ememory::SharedPtr<ewol::widget::Container>;
using ContainerWeak = ememory::WeakPtr<ewol::widget::Container>;
/**
* @ingroup ewolWidgetGroup
* @brief the Cotainer widget is a widget that have an only one subWidget
*/
class Container : public ewol::Widget {
protected:
ewol::WidgetShared m_subWidget;
protected:
/**
* @brief Constructor
*/
Container();
public:
/**
* @brief Destructor
*/
virtual ~Container();
public:
/**
* @brief get the main node widget
* @return the requested pointer on the node
*/
ewol::WidgetShared getSubWidget();
/**
* @brief set the subWidget node widget.
* @param[in] _newWidget The widget to add.
*/
void setSubWidget(ewol::WidgetShared _newWidget);
/**
* @brief Replace a old subwidget with a new one.
* @param[in] _oldWidget The widget to replace.
* @param[in] _newWidget The widget to set.
*/
virtual void subWidgetReplace(const ewol::WidgetShared& _oldWidget,
const ewol::WidgetShared& _newWidget);
/**
* @brief remove the subWidget node (async).
*/
void subWidgetRemove();
/**
* @brief Unlink the subwidget Node.
*/
void subWidgetUnLink();
public:
void systemDraw(const ewol::DrawProperty& _displayProp) override;
void onRegenerateDisplay() override;
void onChangeSize() override;
void calculateMinMaxSize() override;
ewol::WidgetShared getWidgetAtPos(const vec2& _pos) override;
ewol::ObjectShared getSubObjectNamed(const etk::String& _objectName) override;
bool loadXML(const exml::Element& _node) override;
void setOffset(const vec2& _newVal) override;
void requestDestroyFromChild(const ewol::ObjectShared& _child) override;
void drawWidgetTree(int32_t _level=0) override;
};
};
};

View File

@ -0,0 +1,261 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/Container2.hpp>
#include <ewol/widget/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::Container2);
ewol::widget::Container2::Container2() :
m_idWidgetDisplayed(0) {
addObjectType("ewol::widget::Container2");
}
ewol::widget::Container2::~Container2() {
subWidgetRemove();
subWidgetRemoveToggle();
}
void ewol::widget::Container2::setSubWidget(ewol::WidgetShared _newWidget, int32_t _idWidget) {
subWidgetRemove(_idWidget);
m_subWidget[_idWidget] = _newWidget;
if (m_subWidget[_idWidget] != null) {
EWOL_VERBOSE("Add widget : " << _idWidget);
m_subWidget[_idWidget]->setParent(sharedFromThis());
}
markToRedraw();
requestUpdateSize();
}
void ewol::widget::Container2::subWidgetReplace(const ewol::WidgetShared& _oldWidget,
const ewol::WidgetShared& _newWidget) {
bool haveChange = false;
for (size_t iii=0; iii<2; ++iii) {
if (m_subWidget[iii] != _oldWidget) {
continue;
}
m_subWidget[iii]->removeParent();
m_subWidget[iii].reset();
m_subWidget[iii] = _newWidget;
if (m_subWidget[iii] != null) {
m_subWidget[iii]->setParent(sharedFromThis());
}
haveChange = true;
}
if (haveChange == false) {
EWOL_WARNING("Request replace with a wrong old widget");
return;
}
markToRedraw();
requestUpdateSize();
}
void ewol::widget::Container2::subWidgetRemove(int32_t _idWidget) {
if (m_subWidget[_idWidget] != null) {
EWOL_VERBOSE("Remove widget : " << _idWidget);
m_subWidget[_idWidget]->removeParent();
m_subWidget[_idWidget].reset();
markToRedraw();
requestUpdateSize();
}
}
void ewol::widget::Container2::subWidgetUnLink(int32_t _idWidget) {
if (m_subWidget[_idWidget] != null) {
m_subWidget[_idWidget]->removeParent();
EWOL_VERBOSE("Unlink widget : " << _idWidget);
}
m_subWidget[_idWidget].reset();
}
ewol::ObjectShared ewol::widget::Container2::getSubObjectNamed(const etk::String& _widgetName) {
ewol::ObjectShared tmpObject = ewol::Widget::getSubObjectNamed(_widgetName);
if (tmpObject != null) {
return tmpObject;
}
if (m_subWidget[0] != null) {
tmpObject = m_subWidget[0]->getSubObjectNamed(_widgetName);
if (tmpObject != null) {
return tmpObject;
}
}
if (m_subWidget[1] != null) {
return m_subWidget[1]->getSubObjectNamed(_widgetName);
}
return null;
}
void ewol::widget::Container2::systemDraw(const ewol::DrawProperty& _displayProp) {
if (propertyHide.get() == true){
// widget is hidden ...
return;
}
ewol::Widget::systemDraw(_displayProp);
if (m_subWidget[m_idWidgetDisplayed] != null) {
//EWOL_INFO("Draw : [" << propertyName << "] t=" << getObjectType() << " o=" << m_origin << " s=" << m_size);
m_subWidget[m_idWidgetDisplayed]->systemDraw(_displayProp);
}
}
ewol::Padding ewol::widget::Container2::onChangeSizePadded(const ewol::Padding& _padding) {
ewol::Widget::onChangeSize();
vec2 localAvaillable = m_size - vec2(_padding.x(), _padding.y());
// Checkin the filling properties == > for the subElements:
vec2 subElementSize = m_minSize;
if (propertyFill->x() == true) {
subElementSize.setX(m_size.x());
}
if (propertyFill->y() == true) {
subElementSize.setY(m_size.y());
}
vec2 delta = ewol::gravityGenerateDelta(propertyGravity, m_size - subElementSize);
vec2 origin = delta + vec2(_padding.xLeft(), _padding.yButtom());
subElementSize -= vec2(_padding.x(), _padding.y());
for (size_t iii = 0; iii < 2; ++iii) {
if (m_subWidget[iii] != null) {
vec2 origin2 = origin+m_offset;
vec2 minSize = m_subWidget[iii]->getCalculateMinSize();
//bvec2 expand = m_subWidget[iii]->propertyExpand.get();
origin2 += ewol::gravityGenerateDelta(propertyGravity, minSize - localAvaillable);
m_subWidget[iii]->setOrigin(m_origin + origin);
m_subWidget[iii]->setSize(subElementSize);
m_subWidget[iii]->onChangeSize();
}
}
vec2 selectableAreaPos = origin-vec2(_padding.xLeft(), _padding.yButtom());
vec2 selectableAreaEndPos = m_size - (selectableAreaPos + subElementSize + vec2(_padding.x(), _padding.y()));
markToRedraw();
return ewol::Padding(selectableAreaPos.x(),
selectableAreaEndPos.y(),
selectableAreaEndPos.x(),
selectableAreaPos.y());
}
void ewol::widget::Container2::calculateMinMaxSizePadded(const ewol::Padding& _padding) {
// call main class
m_minSize = vec2(0,0);
// call sub classes
for (size_t iii = 0; iii < 2; ++iii) {
if (m_subWidget[iii] != null) {
m_subWidget[iii]->calculateMinMaxSize();
vec2 min = m_subWidget[iii]->getCalculateMinSize();
m_minSize.setMax(min);
}
}
// add padding :
m_minSize += vec2(_padding.x(), _padding.y());
// verify the min max of the min size ...
checkMinSize();
markToRedraw();
}
void ewol::widget::Container2::onRegenerateDisplay() {
if (m_subWidget[m_idWidgetDisplayed] != null) {
m_subWidget[m_idWidgetDisplayed]->onRegenerateDisplay();
}
}
/*
ewol::WidgetShared ewol::widget::Container2::getWidgetAtPos(const vec2& _pos) {
if (isHide() == false) {
if (m_subWidget[m_idWidgetDisplayed] != null) {
return m_subWidget[m_idWidgetDisplayed]->getWidgetAtPos(_pos);
}
}
return null;
}
*/
bool ewol::widget::Container2::loadXML(const exml::Element& _node) {
if (_node.exist() == false) {
return false;
}
// parse generic properties :
ewol::Widget::loadXML(_node);
// remove previous element :
subWidgetRemove();
EWOL_VERBOSE("Create en element 2 ... with nodes.size()=" << _node.nodes.size());
// parse all the elements:
for(const auto it : _node.nodes) {
EWOL_VERBOSE(" node: " << it);
exml::Element pNode = it.toElement();
if (pNode.exist() == false) {
// trash here all that is not element
continue;
}
etk::String widgetName = pNode.getValue();
if (getWidgetManager().exist(widgetName) == false) {
EWOL_ERROR("(l " << pNode.getPos() << ") Unknown basic node='" << widgetName << "' not in: [" << getWidgetManager().list() << "]" );
continue;
}
bool toogleMode=false;
if (getSubWidget() != null) {
toogleMode=true;
if (getSubWidgetToggle() != null) {
EWOL_ERROR("(l " << pNode.getPos() << ") Can only have one subWidget ??? node='" << widgetName << "'" );
continue;
}
}
EWOL_DEBUG("try to create subwidget : '" << widgetName << "'");
ewol::WidgetShared tmpWidget = getWidgetManager().create(widgetName, pNode);
if (tmpWidget == null) {
EWOL_ERROR ("(l " << pNode.getPos() << ") Can not create the widget: '" << widgetName << "'");
continue;
}
// add widget :
if (toogleMode == false) {
setSubWidget(tmpWidget);
} else {
setSubWidgetToggle(tmpWidget);
}
if (tmpWidget->loadXML(pNode) == false) {
EWOL_ERROR ("(l "<<pNode.getPos()<<") can not load widget properties: '" << widgetName << "'");
return false;
}
}
return true;
}
void ewol::widget::Container2::setOffset(const vec2& _newVal) {
if (m_offset != _newVal) {
ewol::Widget::setOffset(_newVal);
// recalculate the new sise and position of sub widget ...
calculateSize();
}
}
void ewol::widget::Container2::requestDestroyFromChild(const ewol::ObjectShared& _child) {
if (m_subWidget[0] == _child) {
if (m_subWidget[0] == null) {
return;
}
m_subWidget[0]->removeParent();
m_subWidget[0].reset();
markToRedraw();
}
if (m_subWidget[1] == _child) {
if (m_subWidget[1] == null) {
return;
}
m_subWidget[1]->removeParent();
m_subWidget[1].reset();
markToRedraw();
}
}
void ewol::widget::Container2::drawWidgetTree(int32_t _level) {
ewol::Widget::drawWidgetTree(_level);
_level++;
if (m_subWidget[0] != null) {
m_subWidget[0]->drawWidgetTree(_level);
}
if (m_subWidget[1] != null) {
m_subWidget[1]->drawWidgetTree(_level);
}
}

View File

@ -0,0 +1,174 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Widget.hpp>
#include <ewol/Padding.hpp>
namespace ewol {
namespace widget {
class Container2;
using Container2Shared = ememory::SharedPtr<ewol::widget::Container2>;
using Container2Weak = ememory::WeakPtr<ewol::widget::Container2>;
/**
* @ingroup ewolWidgetGroup
* @brief the Cotainer widget is a widget that have an only one subWidget
*/
class Container2 : public ewol::Widget {
protected:
ewol::WidgetShared m_subWidget[2]; //!< 2 subwidget possible
int32_t m_idWidgetDisplayed; //!< current widget displayed
protected:
/**
* @brief Constructor
* @param[in] _subElement Widget to set on the normal position
* @param[in] _subElementToggle Widget to set on the toggle position
*/
Container2();
public:
/**
* @brief Destructor
*/
virtual ~Container2();
private:
/**
* @brief Specify the current widget
* @param[in] _subWidget Widget to add normal
* @param[in] _idWidget Id of the widget to set
*/
void setSubWidget(ewol::WidgetShared _subWidget, int32_t _idWidget);
public:
/**
* @brief Specify the current widget
* @param[in] _subWidget Widget to add normal
*/
void setSubWidget(ewol::WidgetShared _subWidget) {
setSubWidget(_subWidget, 0);
}
/**
* @brief Specify the current toggle widget
* @param[in] _subWidget Widget to add Toggle
*/
void setSubWidgetToggle(ewol::WidgetShared _subWidget) {
setSubWidget(_subWidget, 1);
}
private:
/**
* @brief get the current displayed composition
* @param[in] _idWidget Id of the widget to set
* @return The base widget
*/
ewol::WidgetShared getSubWidget(int32_t _idWidget) const {
return m_subWidget[_idWidget];
};
public:
/**
* @brief get the current displayed composition
* @return The base widget
*/
ewol::WidgetShared getSubWidget() const {
return getSubWidget(0);
};
/**
* @brief get the current displayed composition
* @return The toggle widget
*/
ewol::WidgetShared getSubWidgetToggle() const {
return getSubWidget(1);
};
private:
/**
* @brief remove the subWidget node (async).
* @param[in] _idWidget Id of the widget to set
*/
void subWidgetRemove(int32_t _idWidget);
public:
/**
* @brief remove the subWidget node (async).
*/
void subWidgetRemove() {
subWidgetRemove(0);
}
/**
* @brief remove the subWidget Toggle node (async).
*/
void subWidgetRemoveToggle() {
subWidgetRemove(1);
}
private:
/**
* @brief Unlink the subwidget Node.
* @param[in] _idWidget Id of the widget to set
*/
void subWidgetUnLink(int32_t _idWidget);
public:
/**
* @brief Unlink the subwidget Node.
*/
void subWidgetUnLink() {
subWidgetUnLink(0);
}
/**
* @brief Unlink the subwidget Toggle Node.
*/
void subWidgetUnLinkToggle() {
subWidgetUnLink(1);
}
protected:
/**
* @brief Parent set the possible diplay size of the current widget whith his own possibilities
* By default this save the widget available size in the widget size
* @param[in] _padding Padding of the widget.
* @note : INTERNAL EWOL SYSTEM
*/
virtual ewol::Padding onChangeSizePadded(const ewol::Padding& _padding = ewol::Padding(0,0,0,0));
/**
* @brief calculate the minimum and maximum size (need to estimate expend properties of the widget)
* @param[in] _padding Padding of the widget.
* @note : INTERNAL EWOL SYSTEM
*/
virtual void calculateMinMaxSizePadded(const ewol::Padding& _padding = ewol::Padding(0,0,0,0));
/**
* @brief Called when parsing a XML and detect the presence of a second Widget
*/
virtual void onDetectPresenceToggleWidget() {}
/**
* @brief convert ID of the widget if not existed
* @param[in] _id Id of the widget to display.
* @return the id of the widget displayable
*/
int32_t convertId(int32_t _id) {
if (m_subWidget[_id] == null) {
return (_id+1)%2;
}
return _id;
}
/**
* @brief Replace a old subwidget with a new one.
* @param[in] _oldWidget The widget to replace.
* @param[in] _newWidget The widget to set.
*/
virtual void subWidgetReplace(const ewol::WidgetShared& _oldWidget,
const ewol::WidgetShared& _newWidget);
public:
void systemDraw(const ewol::DrawProperty& _displayProp) override;
void onRegenerateDisplay() override;
void onChangeSize() override {
onChangeSizePadded();
}
void calculateMinMaxSize() override {
calculateMinMaxSizePadded();
}
ewol::ObjectShared getSubObjectNamed(const etk::String& _objectName) override;
bool loadXML(const exml::Element& _node) override;
void setOffset(const vec2& _newVal) override;
void requestDestroyFromChild(const ewol::ObjectShared& _child) override;
void drawWidgetTree(int32_t _level=0) override;
};
};
};

View File

@ -0,0 +1,342 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/ContainerN.hpp>
#include <ewol/widget/Manager.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::ContainerN);
ewol::widget::ContainerN::ContainerN() :
propertyLockExpand(this, "lock",
vec2(false,false),
"Lock the subwidget expand",
&ewol::widget::ContainerN::onChangePropertyLockExpand),
m_subExpend(false,false) {
addObjectType("ewol::widget::ContainerN");
// nothing to do ...
}
ewol::widget::ContainerN::~ContainerN() {
subWidgetRemoveAll();
}
bvec2 ewol::widget::ContainerN::canExpand() {
bvec2 res = propertyExpand.get();
if (propertyLockExpand->x() == false) {
if (m_subExpend.x() == true) {
res.setX(true);
}
}
if (propertyLockExpand->y() == false) {
if (m_subExpend.y() == true) {
res.setY(true);
}
}
//EWOL_DEBUG("Expend check : user=" << m_userExpand << " lock=" << propertyLockExpand << " sub=" << m_subExpend << " res=" << res);
return res;
}
void ewol::widget::ContainerN::onChangePropertyLockExpand() {
markToRedraw();
requestUpdateSize();
}
void ewol::widget::ContainerN::subWidgetReplace(ewol::WidgetShared _oldWidget,
ewol::WidgetShared _newWidget) {
bool haveChange = false;
for (auto &it : m_subWidget) {
if (it != _oldWidget) {
continue;
}
it->removeParent();
it.reset();
if (_newWidget != null) {
_newWidget->setParent(sharedFromThis());
}
it = _newWidget;
haveChange = true;
}
if (haveChange == false) {
EWOL_WARNING("Request replace with a wrong old widget");
return;
}
markToRedraw();
requestUpdateSize();
}
int32_t ewol::widget::ContainerN::subWidgetAdd(ewol::WidgetShared _newWidget) {
if (_newWidget == null) {
EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} Try to add An empty Widget ... ");
return -1;
}
_newWidget->setParent(sharedFromThis());
m_subWidget.pushBack(_newWidget);
markToRedraw();
requestUpdateSize();
// added at the last eelement :
return _newWidget->getId();
}
int32_t ewol::widget::ContainerN::subWidgetAddStart(ewol::WidgetShared _newWidget) {
if (_newWidget == null) {
EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} Try to add start An empty Widget ... ");
return -1;
}
if (_newWidget != null) {
_newWidget->setParent(sharedFromThis());
}
m_subWidget.insert(m_subWidget.begin(), _newWidget);
markToRedraw();
requestUpdateSize();
return _newWidget->getId();
}
void ewol::widget::ContainerN::subWidgetRemove(ewol::WidgetShared _newWidget) {
if (_newWidget == null) {
return;
}
size_t errorControl = m_subWidget.size();
auto it(m_subWidget.begin());
while (it != m_subWidget.end()) {
if (_newWidget == *it) {
(*it)->removeParent();
m_subWidget.erase(it);
it = m_subWidget.begin();
markToRedraw();
requestUpdateSize();
} else {
++it;
}
}
}
void ewol::widget::ContainerN::subWidgetUnLink(ewol::WidgetShared _newWidget) {
if (_newWidget == null) {
return;
}
auto it(m_subWidget.begin());
while (it != m_subWidget.end()) {
if (_newWidget == *it) {
(*it)->removeParent();
(*it).reset();
m_subWidget.erase(it);
it = m_subWidget.begin();
markToRedraw();
requestUpdateSize();
} else {
++it;
}
}
}
void ewol::widget::ContainerN::subWidgetRemoveAll() {
for(auto &it : m_subWidget) {
if (it != null) {
it->removeParent();
}
it.reset();
}
m_subWidget.clear();
}
void ewol::widget::ContainerN::subWidgetRemoveAllDelayed() {
subWidgetRemoveAll();
}
ewol::ObjectShared ewol::widget::ContainerN::getSubObjectNamed(const etk::String& _objectName) {
ewol::ObjectShared tmpObject = ewol::Widget::getSubObjectNamed(_objectName);
if (tmpObject != null) {
return tmpObject;
}
for (auto &it : m_subWidget) {
if (it != null) {
tmpObject = it->getSubObjectNamed(_objectName);
if (tmpObject != null) {
return tmpObject;
}
}
}
return null;
}
void ewol::widget::ContainerN::systemDraw(const ewol::DrawProperty& _displayProp) {
if (*propertyHide == true){
// widget is hidden ...
return;
}
// local widget draw
ewol::Widget::systemDraw(_displayProp);
// subwidget draw
ewol::DrawProperty prop = _displayProp;
prop.limit(m_origin, m_size);
for (int64_t iii = m_subWidget.size()-1; iii>=0; --iii) {
if (m_subWidget[iii] != null) {
//EWOL_INFO(" ***** : [" << (*it)->propertyName << "] t=" << (*it)->getObjectType() << " o=" << (*it)->m_origin << " s=" << (*it)->m_size);
m_subWidget[iii]->systemDraw(prop);
}
}
}
void ewol::widget::ContainerN::onChangeSize() {
for (auto &it : m_subWidget) {
if (it == null) {
continue;
}
it->setOrigin(m_origin+m_offset);
it->setSize(m_size);
it->onChangeSize();
}
}
void ewol::widget::ContainerN::calculateMinMaxSize() {
m_subExpend.setValue(false, false);
m_minSize.setValue(0,0);
m_maxSize.setValue(ULTIMATE_MAX_SIZE,ULTIMATE_MAX_SIZE);
//EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} set min size : " << m_minSize);
for (auto &it : m_subWidget) {
if (it != null) {
it->calculateMinMaxSize();
bvec2 subExpendProp = it->canExpand();
if (true == subExpendProp.x()) {
m_subExpend.setX(true);
}
if (true == subExpendProp.y()) {
m_subExpend.setY(true);
}
vec2 tmpSize = it->getCalculateMinSize();
m_minSize.setValue( etk::max(tmpSize.x(), m_minSize.x()),
etk::max(tmpSize.y(), m_minSize.y()) );
}
}
//EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} Result min size : " << m_minSize);
}
void ewol::widget::ContainerN::onRegenerateDisplay() {
for (auto &it : m_subWidget) {
if (it != null) {
it->onRegenerateDisplay();
}
}
}
ewol::WidgetShared ewol::widget::ContainerN::getWidgetAtPos(const vec2& _pos) {
if (*propertyHide == true) {
return null;
}
// for all element in the sizer ...
for (auto &it : m_subWidget) {
if (it != null) {
vec2 tmpSize = it->getSize();
vec2 tmpOrigin = it->getOrigin();
if( (tmpOrigin.x() <= _pos.x() && tmpOrigin.x() + tmpSize.x() >= _pos.x())
&& (tmpOrigin.y() <= _pos.y() && tmpOrigin.y() + tmpSize.y() >= _pos.y()) )
{
ewol::WidgetShared tmpWidget = it->getWidgetAtPos(_pos);
if (tmpWidget != null) {
return tmpWidget;
}
// stop searching
break;
}
}
}
return null;
};
bool ewol::widget::ContainerN::loadXML(const exml::Element& _node) {
if (_node.exist() == false) {
return false;
}
// parse generic properties :
ewol::Widget::loadXML(_node);
// remove previous element :
subWidgetRemoveAll();
etk::String tmpAttributeValue = _node.attributes["lock"];
if (tmpAttributeValue.size()!=0) {
propertyLockExpand.set(tmpAttributeValue);
}
bool invertAdding=false;
tmpAttributeValue = _node.attributes["addmode"];
if(etk::compare_no_case(tmpAttributeValue, "invert")) {
invertAdding=true;
}
// parse all the elements :
for (const auto nodeIt : _node.nodes) {
const exml::Element pNode = nodeIt.toElement();
if (pNode.exist() == false) {
// trash here all that is not element
continue;
}
etk::String widgetName = pNode.getValue();
EWOL_VERBOSE(" t=" << getObjectType() << " Load node name : '" << widgetName << "'");
if (getWidgetManager().exist(widgetName) == false) {
EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} (l " << pNode.getPos() << ") Unknown basic node='" << widgetName << "' not in : [" << getWidgetManager().list() << "]" );
continue;
}
EWOL_DEBUG("[" << getId() << "] {" << getObjectType() << "} load new element : '" << widgetName << "'");
ewol::WidgetShared subWidget = getWidgetManager().create(widgetName, pNode);
if (subWidget == null) {
EWOL_ERROR ("[" << getId() << "] {" << getObjectType() << "} (l " << pNode.getPos() << ") Can not create the widget : '" << widgetName << "'");
continue;
}
// add sub element :
if (invertAdding == false) {
subWidgetAdd(subWidget);
} else {
subWidgetAddStart(subWidget);
}
if (subWidget->loadXML(pNode) == false) {
EWOL_ERROR("[" << getId() << "] {" << getObjectType() << "} (l " << pNode.getPos() << ") can not load widget properties : '" << widgetName << "'");
return false;
}
}
return true;
}
void ewol::widget::ContainerN::setOffset(const vec2& _newVal) {
if (m_offset != _newVal) {
ewol::Widget::setOffset(_newVal);
// recalculate the new sise and position of sub widget ...
onChangeSize();
}
}
void ewol::widget::ContainerN::requestDestroyFromChild(const ewol::ObjectShared& _child) {
auto it = m_subWidget.begin();
while (it != m_subWidget.end()) {
if (*it == _child) {
if (*it == null) {
m_subWidget.erase(it);
it = m_subWidget.begin();
continue;
}
(*it)->removeParent();
(*it).reset();
m_subWidget.erase(it);
it = m_subWidget.begin();
markToRedraw();
continue;
}
++it;
}
}
void ewol::widget::ContainerN::drawWidgetTree(int32_t _level) {
ewol::Widget::drawWidgetTree(_level);
_level++;
for (auto &it: m_subWidget) {
if (it != null) {
it->drawWidgetTree(_level);
}
}
}

View File

@ -0,0 +1,105 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Widget.hpp>
namespace ewol {
namespace widget {
class ContainerN;
using ContainerNShared = ememory::SharedPtr<ewol::widget::ContainerN>;
using ContainerNWeak = ememory::WeakPtr<ewol::widget::ContainerN>;
/**
* @ingroup ewolWidgetGroup
* @brief the Cotainer widget is a widget that have an only one subWidget
*/
class ContainerN : public ewol::Widget {
public: // properties:
eproperty::Value<bvec2> propertyLockExpand; //!< Lock the expend of the sub widget to this one == > this permit to limit bigger subWidget
protected:
etk::Vector<ewol::WidgetShared> m_subWidget;
protected:
/**
* @brief Constructor
*/
ContainerN();
public:
/**
* @brief Destructor
*/
virtual ~ContainerN();
protected:
bvec2 m_subExpend; //!< reference of the sub element expention requested.
// herited function
virtual bvec2 canExpand() override;
public:
/**
* @brief remove all sub element from the widget.
*/
virtual void subWidgetRemoveAll();
/**
* @brief remove all sub element from the widget (delayed to prevent remove in the callbback).
*/
virtual void subWidgetRemoveAllDelayed();
/**
* @brief Replace a old subwidget with a new one.
* @param[in] _oldWidget The widget to replace.
* @param[in] _newWidget The widget to set.
*/
virtual void subWidgetReplace(ewol::WidgetShared _oldWidget,
ewol::WidgetShared _newWidget);
/**
* @brief add at end position a Widget (note : This system use an inverted phylisophie (button to top, and left to right)
* @param[in] _newWidget the element pointer
* @return the ID of the set element
*/
virtual int32_t subWidgetAdd(ewol::WidgetShared _newWidget);
//! @previous
inline int32_t subWidgetAddBack(ewol::WidgetShared _newWidget) {
return subWidgetAdd(_newWidget);
};
//! @previous
inline int32_t subWidgetAddEnd(ewol::WidgetShared _newWidget) {
return subWidgetAdd(_newWidget);
};
/**
* @brief add at start position a Widget (note : This system use an inverted phylisophie (button to top, and left to right)
* @param[in] _newWidget the element pointer
* @return the ID of the set element
*/
virtual int32_t subWidgetAddStart(ewol::WidgetShared _newWidget);
//! @previous
inline int32_t subWidgetAddFront(ewol::WidgetShared _newWidget) {
return subWidgetAddStart(_newWidget);
};
/**
* @brief remove definitly a widget from the system and this layer.
* @param[in] _newWidget the element pointer.
*/
virtual void subWidgetRemove(ewol::WidgetShared _newWidget);
/**
* @brief Just unlick the specify widget, this function does not remove it from the system (if you can, do nt use it ...)
* @param[in] _newWidget the element pointer.
*/
virtual void subWidgetUnLink(ewol::WidgetShared _newWidget);
public:
void systemDraw(const ewol::DrawProperty& _displayProp) override;
void onRegenerateDisplay() override;
void onChangeSize() override;
void calculateMinMaxSize() override;
ewol::WidgetShared getWidgetAtPos(const vec2& _pos) override;
ewol::ObjectShared getSubObjectNamed(const etk::String& _objectName) override;
bool loadXML(const exml::Element& _node) override;
void setOffset(const vec2& _newVal) override;
void requestDestroyFromChild(const ewol::ObjectShared& _child) override;
void drawWidgetTree(int32_t _level=0) override;
protected:
virtual void onChangePropertyLockExpand();
};
};
};

View File

@ -0,0 +1,267 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/widget/ContextMenu.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/widget/Windows.hpp>
#include <ewol/Padding.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::ContextMenu);
ETK_DECLARE_TYPE(enum ewol::widget::ContextMenu::markPosition);
ewol::widget::ContextMenu::ContextMenu():
propertyShape(this, "shape",
etk::Uri("THEME_GUI:///ContextMenu.json?lib=ewol"),
"the display name for config file",
&ewol::widget::ContextMenu::onChangePropertyShape),
propertyArrowPos(this, "arrow-position",
vec2(0,0),
"Position of the arrow in the pop-up",
&ewol::widget::ContextMenu::onChangePropertyArrowPos),
propertyArrawBorder(this, "arrow-mode",
markTop,
"position of the arrow",
&ewol::widget::ContextMenu::onChangePropertyArrawBorder) {
addObjectType("ewol::widget::ContextMenu");
propertyArrawBorder.add(markTop, "top");
propertyArrawBorder.add(markRight, "right");
propertyArrawBorder.add(markButtom, "buttom");
propertyArrawBorder.add(markLeft, "left");
propertyArrawBorder.add(markNone, "none");
m_offset = 20;
m_colorBorder = etk::color::black;
m_colorBorder.setA(0x7F);
setMouseLimit(1);
}
void ewol::widget::ContextMenu::init() {
ewol::widget::Container::init();
propertyShape.notifyChange();
}
ewol::widget::ContextMenu::~ContextMenu() {
}
void ewol::widget::ContextMenu::onChangeSize() {
markToRedraw();
// pop-up fill all the display :
ewol::Padding padding = m_shaper.getPadding();
EWOL_VERBOSE("our origin=" << m_origin << " size=" << m_size);
if (m_subWidget == null) {
return;
}
vec2 subWidgetSize(0,0);
vec2 subWidgetOrigin(0,0);
subWidgetSize = m_subWidget->getCalculateMinSize();
if (m_subWidget->canExpand().x() == true) {
subWidgetSize.setX(m_size.x());
}
if (m_subWidget->canExpand().y() == true) {
subWidgetSize.setY(m_size.y());
}
int32_t minWidth = 100;
int32_t maxWidth = 300;
subWidgetSize.setX((int32_t)etk::max(minWidth, (int32_t)subWidgetSize.x()));
subWidgetSize.setX((int32_t)etk::min(maxWidth, (int32_t)subWidgetSize.x()));
subWidgetSize.setY((int32_t)subWidgetSize.y());
// set config to the Sub-widget
switch (propertyArrawBorder.get()) {
case markTop:
subWidgetOrigin.setX((int32_t)(propertyArrowPos->x() - subWidgetSize.x()/2));
subWidgetOrigin.setY((int32_t)(propertyArrowPos->y() - m_offset - subWidgetSize.y()));
break;
case markButtom:
subWidgetOrigin.setX((int32_t)(propertyArrowPos->x() - subWidgetSize.x()/2));
subWidgetOrigin.setY((int32_t)(propertyArrowPos->y() + m_offset));
break;
case markRight:
case markLeft:
default:
subWidgetOrigin.setX((int32_t)(m_size.x() - m_origin.x() - subWidgetSize.x())/2 + m_origin.x());
subWidgetOrigin.setY((int32_t)(m_size.y() - m_origin.y() - subWidgetSize.y())/2 + m_origin.y());
break;
}
// set the widget position at the border of the screen
subWidgetOrigin.setX( (int32_t)( etk::max(0, (int32_t)(subWidgetOrigin.x()-padding.x()))
+ padding.x()) );
subWidgetOrigin.setY( (int32_t)( etk::max(0, (int32_t)(subWidgetOrigin.y()-padding.y()))
+ padding.y()) );
switch (propertyArrawBorder.get()) {
default:
case markTop:
case markButtom:
if (propertyArrowPos->x() <= m_offset ) {
subWidgetOrigin.setX(propertyArrowPos->x()+padding.xLeft());
}
break;
case markRight:
case markLeft:
if (propertyArrowPos->y() <= m_offset ) {
subWidgetOrigin.setY(propertyArrowPos->y()+padding.yButtom());
}
break;
}
EWOL_VERBOSE(" == > sub origin=" << subWidgetOrigin << " size=" << subWidgetSize);
m_subWidget->setOrigin(subWidgetOrigin);
m_subWidget->setSize(subWidgetSize);
m_subWidget->onChangeSize();
}
void ewol::widget::ContextMenu::calculateMinMaxSize() {
// call main class to calculate the min size...
ewol::widget::Container::calculateMinMaxSize();
// add padding of the display
ewol::Padding padding = m_shaper.getPadding();
m_minSize += vec2(padding.x(), padding.y());
//EWOL_DEBUG("CalculateMinSize=>>" << m_minSize);
markToRedraw();
}
void ewol::widget::ContextMenu::onDraw() {
m_compositing.draw();
m_shaper.draw();
}
void ewol::widget::ContextMenu::onRegenerateDisplay() {
// call upper class :
ewol::widget::Container::onRegenerateDisplay();
if (needRedraw() == false) {
return;
}
m_compositing.clear();
m_shaper.clear();
ewol::Padding padding = m_shaper.getPadding();
if (m_subWidget == null) {
return;
}
vec2 tmpSize = m_subWidget->getSize();
vec2 tmpOrigin = m_subWidget->getOrigin();
// display border ...
m_compositing.setColor(m_colorBorder);
switch (propertyArrawBorder) {
case markTop:
m_compositing.setPos(vec3(propertyArrowPos->x(), propertyArrowPos->y(), 0.0f) );
m_compositing.addVertex();
if (propertyArrowPos->x() <= tmpOrigin.x() ) {
float laking = m_offset - padding.yTop();
m_compositing.setPos(vec3(propertyArrowPos->x()+laking, propertyArrowPos->y()-laking, 0.0f) );
m_compositing.addVertex();
m_compositing.setPos(vec3(propertyArrowPos->x(), propertyArrowPos->y()-laking, 0.0f) );
m_compositing.addVertex();
} else {
float laking = m_offset - padding.yTop();
m_compositing.setPos(vec3(propertyArrowPos->x()+laking, propertyArrowPos->y()-laking, 0.0f) );
m_compositing.addVertex();
m_compositing.setPos(vec3(propertyArrowPos->x()-laking, propertyArrowPos->y()-laking, 0.0f) );
m_compositing.addVertex();
}
break;
case markButtom:
m_compositing.setPos(vec3(propertyArrowPos->x(), propertyArrowPos->y(), 0) );
m_compositing.addVertex();
if (propertyArrowPos->x() <= tmpOrigin.x() ) {
int32_t laking = m_offset - padding.yTop();
m_compositing.setPos(vec3(propertyArrowPos->x()+laking, propertyArrowPos->y()+laking, 0.0f) );
m_compositing.addVertex();
m_compositing.setPos(vec3(propertyArrowPos->x(), propertyArrowPos->y()+laking, 0.0f) );
m_compositing.addVertex();
} else {
int32_t laking = m_offset - padding.yTop();
m_compositing.setPos(vec3(propertyArrowPos->x()+laking, propertyArrowPos->y()+laking, 0.0f) );
m_compositing.addVertex();
m_compositing.setPos(vec3(propertyArrowPos->x()-laking, propertyArrowPos->y()+laking, 0.0f) );
m_compositing.addVertex();
}
break;
default:
case markRight:
case markLeft:
EWOL_TODO("later");
break;
}
vec2 shaperOrigin = tmpOrigin-vec2(padding.xLeft(), padding.yButtom());
vec2 shaperSize = tmpSize+vec2(padding.x(), padding.y());
m_shaper.setShape(vec2ClipInt32(shaperOrigin),
vec2ClipInt32(shaperSize));
}
bool ewol::widget::ContextMenu::onEventInput(const ewol::event::Input& _event) {
if (_event.getId() > 0) {
if (ewol::widget::Container::getWidgetAtPos(_event.getPos()) != null) {
return false;
}
if( _event.getStatus() == gale::key::status::down
|| _event.getStatus() == gale::key::status::move
|| _event.getStatus() == gale::key::status::pressSingle
|| _event.getStatus() == gale::key::status::up
|| _event.getStatus() == gale::key::status::enter
|| _event.getStatus() == gale::key::status::leave ) {
// Auto-remove ...
autoDestroy();
return true;
}
}
return false;
}
ewol::WidgetShared ewol::widget::ContextMenu::getWidgetAtPos(const vec2& _pos) {
ewol::WidgetShared val = ewol::widget::Container::getWidgetAtPos(_pos);
if (val != null) {
return val;
}
return ememory::dynamicPointerCast<ewol::Widget>(sharedFromThis());
}
void ewol::widget::ContextMenu::onChangePropertyArrowPos() {
markToRedraw();
}
void ewol::widget::ContextMenu::onChangePropertyArrawBorder() {
markToRedraw();
}
void ewol::widget::ContextMenu::onChangePropertyShape() {
m_shaper.setSource(propertyShape.get());
markToRedraw();
}
void ewol::widget::ContextMenu::setPositionMarkAuto(const vec2& _origin, const vec2& _size) {
ewol::widget::WindowsShared windows = getWindows();
vec2 globalSize = windows->getSize();
// TODO : Support left and right
float upperSize = globalSize.y() - (_origin.y() + _size.y());
float underSize = _origin.y();
if (underSize >= upperSize) {
vec2 pos = _origin + _size - vec2(_size.x()*0.5f, 0.0f);
setPositionMark(ewol::widget::ContextMenu::markButtom, pos);
} else {
vec2 pos = _origin + vec2(_size.x()*0.5f, 0.0f);
setPositionMark(ewol::widget::ContextMenu::markTop, pos);
}
}
void ewol::widget::ContextMenu::setPositionMark(enum markPosition _position, const vec2& _arrowPos) {
propertyArrawBorder.set(_position);
propertyArrowPos.set(_arrowPos);
}

View File

@ -0,0 +1,70 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/Color.hpp>
#include <ewol/debug.hpp>
#include <ewol/widget/Container.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/compositing/Shaper.hpp>
#include <ewol/widget/Manager.hpp>
namespace ewol {
namespace widget {
class ContextMenu;
using ContextMenuShared = ememory::SharedPtr<ewol::widget::ContextMenu>;
using ContextMenuWeak = ememory::WeakPtr<ewol::widget::ContextMenu>;
/**
* @ingroup ewolWidgetGroup
*/
class ContextMenu : public ewol::widget::Container {
public:
enum markPosition {
markTop,
markRight,
markButtom,
markLeft,
markNone
};
public: // properties
eproperty::Value<etk::Uri> propertyShape; //!< shape of the widget.
eproperty::Value<vec2> propertyArrowPos;
eproperty::List<enum markPosition> propertyArrawBorder;
protected:
ContextMenu();
void init() override;
public:
DECLARE_WIDGET_FACTORY(ContextMenu, "ContextMenu");
virtual ~ContextMenu();
private:
ewol::compositing::Shaper m_shaper; //!< Compositing theme.
// TODO : Use shaper for the arraw ...
ewol::compositing::Drawing m_compositing;
etk::Color<> m_colorBorder; // use shaper ID
float m_offset;
public:
void setPositionMarkAuto(const vec2& _origin, const vec2& _size);
void setPositionMark(enum markPosition _position, const vec2& _arrowPos);
protected:
void onDraw() override;
public:
void onRegenerateDisplay() override;
bool onEventInput(const ewol::event::Input& _event) override;
void onChangeSize() override;
void calculateMinMaxSize() override;
ewol::WidgetShared getWidgetAtPos(const vec2& _pos) override;
protected:
virtual void onChangePropertyArrowPos();
virtual void onChangePropertyArrawBorder();
virtual void onChangePropertyShape();
};
};
};

View File

@ -0,0 +1,612 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/widget/Entry.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/ewol.hpp>
#include <ewol/context/Context.hpp>
#include <ewol/Padding.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(ewol::widget::Entry);
// DEFINE for the shader display system :
#define STATUS_NORMAL (0)
#define STATUS_HOVER (1)
#define STATUS_SELECTED (2)
ewol::widget::Entry::Entry() :
signalClick(this, "click", "the user Click on the Entry box"),
signalEnter(this, "enter", "The cursor enter inside the button"),
signalModify(this, "modify", "Entry box value change"),
propertyPassword(this, "password",
false,
"Not display content in password mode",
&ewol::widget::Entry::onChangePropertyPassword),
propertyShape(this, "shape",
etk::Uri("THEME_GUI:///Entry.json?lib=ewol"),
"Shaper to display the background",
&ewol::widget::Entry::onChangePropertyShaper),
propertyValue(this, "value",
"",
"Value display in the entry (decorated text)",
&ewol::widget::Entry::onChangePropertyValue),
propertyMaxCharacter(this, "max",
0x7FFFFFFF, 0, 0x7FFFFFFF,
"Maximum char that can be set on the Entry",
&ewol::widget::Entry::onChangePropertyMaxCharacter),
propertyRegex(this, "regex",
".*",
"Control what it is write with a regular expression",
&ewol::widget::Entry::onChangePropertyRegex),
propertyTextWhenNothing(this, "empty-text",
"",
"Text when nothing is written",
&ewol::widget::Entry::onChangePropertyTextWhenNothing),
m_needUpdateTextPos(true),
m_displayStartPosition(0),
m_displayCursor(false),
m_displayCursorPos(0),
m_displayCursorPosSelection(0) {
addObjectType("ewol::widget::Entry");
propertyCanFocus.setDirectCheck(true);
}
void ewol::widget::Entry::init() {
ewol::Widget::init();
propertyShape.notifyChange();
m_regex.compile(propertyRegex.get());
if (m_regex.getStatus() == false) {
EWOL_ERROR("can not parse regex for : " << propertyRegex);
}
markToRedraw();
shortCutAdd("ctrl+w", "clean");
shortCutAdd("ctrl+x", "cut");
shortCutAdd("ctrl+c", "copy");
shortCutAdd("ctrl+v", "paste");
shortCutAdd("ctrl+a", "select:all");
shortCutAdd("ctrl+shift+a", "select:none");
signalShortcut.connect(sharedFromThis(), &ewol::widget::Entry::onCallbackShortCut);
}
ewol::widget::Entry::~Entry() {
}
void ewol::widget::Entry::onCallbackShortCut(const etk::String& _value) {
if (_value == "clean") {
onCallbackEntryClean();
} else if (_value == "cut") {
onCallbackCut();
} else if (_value == "copy") {
onCallbackCopy();
} else if (_value == "paste") {
EWOL_WARNING("Request past ...");
onCallbackPaste();
} else if (_value == "select:all") {
onCallbackSelect(true);
} else if (_value == "select:none") {
onCallbackSelect(false);
} else {
EWOL_WARNING("Unknow event from ShortCut : " << _value);
}
}
void ewol::widget::Entry::calculateMinMaxSize() {
// call main class
ewol::Widget::calculateMinMaxSize();
// get generic padding
ewol::Padding padding = m_shaper.getPadding();
int32_t minHeight = m_text.calculateSize(char32_t('A')).y();
vec2 minimumSizeBase(20, minHeight);
// add padding :
minimumSizeBase += vec2(padding.x(), padding.y());
m_minSize.setMax(minimumSizeBase);
// verify the min max of the min size ...
checkMinSize();
}
void ewol::widget::Entry::onDraw() {
m_shaper.draw();
m_text.draw();
}
void ewol::widget::Entry::onRegenerateDisplay() {
if (needRedraw() == true) {
m_shaper.clear();
m_text.clear();
if (m_colorIdTextFg >= 0) {
m_text.setDefaultColorFg(m_shaper.getColor(m_colorIdTextFg));
m_text.setDefaultColorBg(m_shaper.getColor(m_colorIdTextBg));
m_text.setCursorColor(m_shaper.getColor(m_colorIdCursor));
m_text.setSelectionColor(m_shaper.getColor(m_colorIdSelection));
}
updateTextPosition();
ewol::Padding padding = m_shaper.getPadding();
vec2 tmpSizeShaper = m_minSize;
if (propertyFill->x() == true) {
tmpSizeShaper.setX(m_size.x());
}
if (propertyFill->y() == true) {
tmpSizeShaper.setY(m_size.y());
}
vec2 tmpOriginShaper = (m_size - tmpSizeShaper) / 2.0f;
vec2 tmpSizeText = tmpSizeShaper - vec2(padding.x(), padding.y());
vec2 tmpOriginText = (m_size - tmpSizeText) / 2.0f;
// sometimes, the user define an height bigger than the real size needed == > in this case we need to center the text in the shaper ...
int32_t minHeight = m_text.calculateSize(char32_t('A')).y();
if (tmpSizeText.y() > minHeight) {
tmpOriginText += vec2(0,(tmpSizeText.y()-minHeight)/2.0f);
}
// fix all the position in the int32_t class:
tmpSizeShaper = vec2ClipInt32(tmpSizeShaper);
tmpOriginShaper = vec2ClipInt32(tmpOriginShaper);
tmpSizeText = vec2ClipInt32(tmpSizeText);
tmpOriginText = vec2ClipInt32(tmpOriginText);
m_text.reset();
m_text.setClippingWidth(tmpOriginText, tmpSizeText);
m_text.setPos(tmpOriginText+vec2(m_displayStartPosition,0));
if (m_displayCursorPosSelection != m_displayCursorPos) {
m_text.setCursorSelection(m_displayCursorPos, m_displayCursorPosSelection);
} else {
m_text.setCursorPos(m_displayCursorPos);
}
etk::UString valueToDisplay = etk::toUString(*propertyValue);
if (*propertyPassword == true) {
for (auto &it: valueToDisplay) {
it = '*';
}
}
if (valueToDisplay.size() != 0) {
m_text.print(valueToDisplay);
} else {
if (propertyTextWhenNothing->size() != 0) {
m_text.printDecorated(propertyTextWhenNothing);
}
}
m_text.setClippingMode(false);
m_shaper.setShape(tmpOriginShaper, tmpSizeShaper, tmpOriginText, tmpSizeText);
}
}
void ewol::widget::Entry::updateCursorPosition(const vec2& _pos, bool _selection) {
ewol::Padding padding = m_shaper.getPadding();
vec2 relPos = relativePosition(_pos);
relPos.setX(relPos.x()-m_displayStartPosition - padding.xLeft());
// try to find the new cursor position :
etk::String tmpDisplay = etk::String(propertyValue, 0, m_displayStartPosition);
int32_t displayHidenSize = m_text.calculateSize(tmpDisplay).x();
//EWOL_DEBUG("hidenSize : " << displayHidenSize);
int32_t newCursorPosition = -1;
int32_t tmpTextOriginX = padding.xLeft();
for (size_t iii=0; iii<propertyValue->size(); iii++) {
tmpDisplay = etk::String(propertyValue, 0, iii);
int32_t tmpWidth = m_text.calculateSize(tmpDisplay).x() - displayHidenSize;
if (tmpWidth >= relPos.x()-tmpTextOriginX) {
newCursorPosition = iii;
break;
}
}
if (newCursorPosition == -1) {
newCursorPosition = propertyValue->size();
}
if (_selection == false) {
m_displayCursorPos = newCursorPosition;
m_displayCursorPosSelection = m_displayCursorPos;
markToRedraw();
} else {
if (m_displayCursorPos == m_displayCursorPosSelection) {
m_displayCursorPosSelection = m_displayCursorPos;
}
m_displayCursorPos = newCursorPosition;
markToRedraw();
}
markToUpdateTextPosition();
}
void ewol::widget::Entry::removeSelected() {
if (m_displayCursorPosSelection == m_displayCursorPos) {
// nothing to cut ...
return;
}
int32_t pos1 = m_displayCursorPosSelection;
int32_t pos2 = m_displayCursorPos;
if(m_displayCursorPosSelection>m_displayCursorPos) {
pos2 = m_displayCursorPosSelection;
pos1 = m_displayCursorPos;
}
// remove data ...
m_displayCursorPos = pos1;
m_displayCursorPosSelection = pos1;
propertyValue.getDirect().erase(pos1, pos2-pos1);
markToRedraw();
}
void ewol::widget::Entry::copySelectionToClipBoard(enum gale::context::clipBoard::clipboardListe _clipboardID) {
if (m_displayCursorPosSelection == m_displayCursorPos) {
// nothing to cut ...
return;
}
int32_t pos1 = m_displayCursorPosSelection;
int32_t pos2 = m_displayCursorPos;
if(m_displayCursorPosSelection>m_displayCursorPos) {
pos2 = m_displayCursorPosSelection;
pos1 = m_displayCursorPos;
}
// Copy
etk::String tmpData = etk::String(propertyValue, pos1, pos2);
gale::context::clipBoard::set(_clipboardID, tmpData);
}
bool ewol::widget::Entry::onEventInput(const ewol::event::Input& _event) {
EWOL_WARNING("Event on Input ... " << _event);
if (_event.getId() == 1) {
if (gale::key::status::pressSingle == _event.getStatus()) {
keepFocus();
signalClick.emit();
//nothing to do ...
return true;
} else if (gale::key::status::pressDouble == _event.getStatus()) {
keepFocus();
// select word
m_displayCursorPosSelection = m_displayCursorPos-1;
// search forward
for (size_t iii=m_displayCursorPos; iii <= propertyValue->size(); iii++) {
if(iii == propertyValue->size()) {
m_displayCursorPos = iii;
break;
}
if(!( ( propertyValue.get()[iii] >= 'a'
&& propertyValue.get()[iii] <= 'z')
|| ( propertyValue.get()[iii] >= 'A'
&& propertyValue.get()[iii] <= 'Z')
|| ( propertyValue.get()[iii] >= '0'
&& propertyValue.get()[iii] <= '9')
|| propertyValue.get()[iii] == '_'
|| propertyValue.get()[iii] == '-'
) ) {
m_displayCursorPos = iii;
break;
}
}
// search backward
for (int64_t iii=m_displayCursorPosSelection; iii >= -1; iii--) {
if(iii == -1) {
m_displayCursorPosSelection = 0;
break;
}
if(!( ( propertyValue.get()[iii] >= 'a'
&& propertyValue.get()[iii] <= 'z')
|| ( propertyValue.get()[iii] >= 'A'
&& propertyValue.get()[iii] <= 'Z')
|| ( propertyValue.get()[iii] >= '0'
&& propertyValue.get()[iii] <= '9')
|| propertyValue.get()[iii] == '_'
|| propertyValue.get()[iii] == '-'
) ) {
m_displayCursorPosSelection = iii+1;
break;
}
}
// Copy to clipboard Middle ...
copySelectionToClipBoard(gale::context::clipBoard::clipboardSelection);
markToRedraw();
} else if (gale::key::status::pressTriple == _event.getStatus()) {
keepFocus();
m_displayCursorPosSelection = 0;
m_displayCursorPos = propertyValue->size();
} else if (gale::key::status::down == _event.getStatus()) {
keepFocus();
updateCursorPosition(_event.getPos());
markToRedraw();
} else if (gale::key::status::move == _event.getStatus()) {
keepFocus();
updateCursorPosition(_event.getPos(), true);
markToRedraw();
} else if (gale::key::status::up == _event.getStatus()) {
keepFocus();
updateCursorPosition(_event.getPos(), true);
// Copy to clipboard Middle ...
copySelectionToClipBoard(gale::context::clipBoard::clipboardSelection);
markToRedraw();
}
}
else if( gale::key::type::mouse == _event.getType()
&& _event.getId() == 2) {
if( _event.getStatus() == gale::key::status::down
|| _event.getStatus() == gale::key::status::move
|| _event.getStatus() == gale::key::status::up) {
keepFocus();
// updatethe cursor position :
updateCursorPosition(_event.getPos());
}
// Paste current selection only when up button
if (_event.getStatus() == gale::key::status::up) {
keepFocus();
// middle button => past data...
gale::context::clipBoard::request(gale::context::clipBoard::clipboardSelection);
}
}
return false;
}
bool ewol::widget::Entry::onEventEntry(const ewol::event::Entry& _event) {
EWOL_WARNING("Event on Entry ... " << _event);
if (_event.getType() == gale::key::keyboard::character) {
if(_event.getStatus() == gale::key::status::down) {
// remove curent selected data ...
removeSelected();
if( _event.getChar() == '\n'
|| _event.getChar() == '\r') {
signalEnter.emit(propertyValue);
return true;
} else if (_event.getChar() == 0x7F) {
// SUPPR :
if (propertyValue->size() > 0 && m_displayCursorPos < (int64_t)propertyValue->size()) {
propertyValue.getDirect().erase(m_displayCursorPos, 1);
m_displayCursorPos = etk::max(m_displayCursorPos, 0);
m_displayCursorPosSelection = m_displayCursorPos;
}
} else if (_event.getChar() == 0x08) {
// DEL :
if (propertyValue->size() > 0 && m_displayCursorPos != 0) {
propertyValue.getDirect().erase(m_displayCursorPos-1, 1);
m_displayCursorPos--;
m_displayCursorPos = etk::max(m_displayCursorPos, 0);
m_displayCursorPosSelection = m_displayCursorPos;
}
} else if(_event.getChar() >= 20) {
EWOL_ERROR("get data: '" << _event.getChar() << "' = '" << u32char::convertToUtf8(_event.getChar()) << "'");
if ((int64_t)propertyValue->size() > propertyMaxCharacter) {
EWOL_INFO("Reject data for entry : '" << _event.getChar() << "'");
} else {
etk::String newData = propertyValue;
etk::String inputData = u32char::convertToUtf8(_event.getChar());
newData.insert(newData.begin()+m_displayCursorPos, inputData);
setInternalValue(newData);
if (propertyValue.get() == newData) {
m_displayCursorPos += inputData.size();
m_displayCursorPosSelection = m_displayCursorPos;
}
}
}
signalModify.emit(propertyValue);
markToRedraw();
return true;
}
return false;
} else {
if(_event.getStatus() == gale::key::status::down) {
switch (_event.getType()) {
case gale::key::keyboard::left:
m_displayCursorPos--;
break;
case gale::key::keyboard::right:
m_displayCursorPos++;
break;
case gale::key::keyboard::start:
m_displayCursorPos = 0;
break;
case gale::key::keyboard::end:
m_displayCursorPos = propertyValue->size();
break;
default:
return false;
}
m_displayCursorPos = etk::avg(0, m_displayCursorPos, (int32_t)propertyValue->size());
m_displayCursorPosSelection = m_displayCursorPos;
markToRedraw();
return true;
}
}
return false;
}
void ewol::widget::Entry::setInternalValue(const etk::String& _newData) {
etk::String previous = propertyValue;
// check the RegExp :
if (_newData.size()>0) {
/*
if (m_regex.parse(_newData, 0, _newData.size()) == false) {
EWOL_INFO("The input data does not match with the regExp '" << _newData << "' Regex='" << propertyRegex << "'" );
return;
}
if (m_regex.start() != 0) {
EWOL_INFO("The input data does not match with the regExp '" << _newData << "' Regex='" << propertyRegex << "' (start position error)" );
return;
}
if (m_regex.stop() != _newData.size()) {
EWOL_INFO("The input data does not match with the regExp '" << _newData << "' Regex='" << propertyRegex << "' (stop position error)" );
return;
}
*/
}
propertyValue.setDirect(_newData);
markToRedraw();
}
void ewol::widget::Entry::onEventClipboard(enum gale::context::clipBoard::clipboardListe _clipboardID) {
// remove curent selected data ...
removeSelected();
// get current selection / Copy :
etk::String tmpData = get(_clipboardID);
// add it on the current display :
if (tmpData.size() != 0) {
etk::String newData = propertyValue;
newData.insert(m_displayCursorPos, &tmpData[0]);
setInternalValue(newData);
if (propertyValue.get() == newData) {
if (propertyValue->size() == tmpData.size()) {
m_displayCursorPos = tmpData.size();
} else {
m_displayCursorPos += tmpData.size();
}
m_displayCursorPosSelection = m_displayCursorPos;
markToRedraw();
}
}
signalModify.emit(propertyValue);
}
void ewol::widget::Entry::onCallbackEntryClean() {
propertyValue.setDirect("");
m_displayStartPosition = 0;
m_displayCursorPos = 0;
m_displayCursorPosSelection = m_displayCursorPos;
markToRedraw();
}
void ewol::widget::Entry::onCallbackCut() {
copySelectionToClipBoard(gale::context::clipBoard::clipboardStd);
removeSelected();
signalModify.emit(propertyValue);
}
void ewol::widget::Entry::onCallbackCopy() {
copySelectionToClipBoard(gale::context::clipBoard::clipboardStd);
}
void ewol::widget::Entry::onCallbackPaste() {
gale::context::clipBoard::request(gale::context::clipBoard::clipboardStd);
}
void ewol::widget::Entry::onCallbackSelect(bool _all) {
if(_all == true) {
m_displayCursorPosSelection = 0;
m_displayCursorPos = propertyValue->size();
} else {
m_displayCursorPosSelection = m_displayCursorPos;
}
markToRedraw();
}
void ewol::widget::Entry::markToUpdateTextPosition() {
m_needUpdateTextPos = true;
}
void ewol::widget::Entry::updateTextPosition() {
if (m_needUpdateTextPos == false) {
return;
}
ewol::Padding padding = m_shaper.getPadding();
int32_t tmpSizeX = m_minSize.x();
if (propertyFill->x() == true) {
tmpSizeX = m_size.x();
}
int32_t tmpUserSize = tmpSizeX - padding.x();
int32_t totalWidth = m_text.calculateSize(propertyValue).x();
// Check if the data inside the display can be contain in the entry box
if (totalWidth < tmpUserSize) {
// all can be display :
m_displayStartPosition = 0;
} else {
// all can not be set :
etk::String tmpDisplay = etk::String(propertyValue, 0, m_displayCursorPos);
int32_t pixelCursorPos = m_text.calculateSize(tmpDisplay).x();
// check if the Cussor is visible at 10px nearest the border :
int32_t tmp1 = pixelCursorPos+m_displayStartPosition;
EWOL_DEBUG("cursorPos=" << pixelCursorPos << "px maxSize=" << tmpUserSize << "px tmp1=" << tmp1);
if (tmp1<10) {
// set the cursor on le left
m_displayStartPosition = etk::min(-pixelCursorPos+10, 0);
} else if (tmp1>tmpUserSize-10) {
// set the cursor of the Right
m_displayStartPosition = etk::min(-pixelCursorPos + tmpUserSize - 10, 0);
}
// else : the cursor is inside the display
//m_displayStartPosition = -totalWidth + tmpUserSize;
}
}
void ewol::widget::Entry::onGetFocus() {
m_displayCursor = true;
changeStatusIn(STATUS_SELECTED);
showKeyboard();
markToRedraw();
}
void ewol::widget::Entry::onLostFocus() {
m_displayCursor = false;
changeStatusIn(STATUS_NORMAL);
hideKeyboard();
markToRedraw();
}
void ewol::widget::Entry::changeStatusIn(int32_t _newStatusId) {
if (m_shaper.changeStatusIn(_newStatusId) == true) {
m_PCH = getObjectManager().periodicCall.connect(this, &ewol::widget::Entry::periodicCall);
markToRedraw();
}
}
void ewol::widget::Entry::periodicCall(const ewol::event::Time& _event) {
if (m_shaper.periodicCall(_event) == false) {
m_PCH.disconnect();
}
markToRedraw();
}
void ewol::widget::Entry::onChangePropertyPassword() {
markToRedraw();
}
void ewol::widget::Entry::onChangePropertyShaper() {
m_shaper.setSource(propertyShape.get());
m_colorIdTextFg = m_shaper.requestColor("text-foreground");
m_colorIdTextBg = m_shaper.requestColor("text-background");
m_colorIdCursor = m_shaper.requestColor("text-cursor");
m_colorIdSelection = m_shaper.requestColor("text-selection");
}
void ewol::widget::Entry::onChangePropertyValue() {
etk::String newData = propertyValue.get();
if ((int64_t)newData.size() > propertyMaxCharacter) {
newData = etk::String(newData, 0, propertyMaxCharacter);
EWOL_DEBUG("Limit entry set of data... " << etk::String(newData, propertyMaxCharacter));
}
// set the value with the check of the RegExp ...
setInternalValue(newData);
if (newData == propertyValue.get()) {
m_displayCursorPos = propertyValue->size();
m_displayCursorPosSelection = m_displayCursorPos;
EWOL_VERBOSE("Set : '" << newData << "'");
}
markToRedraw();
}
void ewol::widget::Entry::onChangePropertyMaxCharacter() {
// TODO : check nomber of char in the data
}
void ewol::widget::Entry::onChangePropertyRegex() {
m_regex.compile(propertyRegex.get());
if (m_regex.getStatus() == false) {
EWOL_ERROR("can not parse regex for : " << propertyRegex);
}
markToRedraw();
}
void ewol::widget::Entry::onChangePropertyTextWhenNothing() {
markToRedraw();
}

View File

@ -0,0 +1,141 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/RegEx.hpp>
#include <ewol/debug.hpp>
#include <ewol/compositing/Text.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <ewol/compositing/Shaper.hpp>
#include <ewol/widget/Widget.hpp>
#include <etk/Color.hpp>
#include <ewol/widget/Manager.hpp>
#include <esignal/Signal.hpp>
namespace ewol {
namespace widget {
class Entry;
using EntryShared = ememory::SharedPtr<ewol::widget::Entry>;
using EntryWeak = ememory::WeakPtr<ewol::widget::Entry>;
/**
* @ingroup ewolWidgetGroup
* @brief Entry box display :
*
* ~~~~~~~~~~~~~~~~~~~~~~
* ----------------------------------------------
* | Editable Text |
* ----------------------------------------------
* ~~~~~~~~~~~~~~~~~~~~~~
*/
class Entry : public ewol::Widget {
public: // Event list
esignal::Signal<> signalClick; //!< bang on click the entry box
esignal::Signal<etk::String> signalEnter; //!< Enter key is pressed
esignal::Signal<etk::String> signalModify; //!< data change
public: // propertie list
eproperty::Value<bool> propertyPassword; //!< Disable display of the content of the entry
eproperty::Value<etk::Uri> propertyShape;
eproperty::Value<etk::String> propertyValue; //!< string that must be displayed
eproperty::Range<int32_t> propertyMaxCharacter; //!< number max of xharacter in the list
eproperty::Value<etk::String> propertyRegex; //!< regular expression value
eproperty::Value<etk::String> propertyTextWhenNothing; //!< Text to display when nothing in in the entry (decorated text...)
private:
ewol::compositing::Shaper m_shaper;
int32_t m_colorIdTextFg; //!< color property of the text foreground
int32_t m_colorIdTextBg; //!< color property of the text background
int32_t m_colorIdCursor; //!< color property of the text cursor
int32_t m_colorIdSelection; //!< color property of the text selection
ewol::compositing::Text m_text; //!< text display m_text
protected:
/**
* @brief Contuctor
* @param[in] _newData The USting that might be set in the Entry box (no event generation!!)
*/
Entry();
void init() override;
public:
DECLARE_WIDGET_FACTORY(Entry, "Entry");
/**
* @brief Destuctor
*/
virtual ~Entry();
protected:
/**
* @brief internal check the value with RegExp checking
* @param[in] _newData The new string to display
*/
void setInternalValue(const etk::String& _newData);
private:
etk::RegEx<etk::String> m_regex; //!< regular expression to check content
private:
bool m_needUpdateTextPos; //!< text position can have change
int32_t m_displayStartPosition; //!< ofset in pixel of the display of the UString
bool m_displayCursor; //!< Cursor must be display only when the widget has the focus
int32_t m_displayCursorPos; //!< Cursor position in number of Char
int32_t m_displayCursorPosSelection; //!< Selection position end (can be befor or after cursor and == m_displayCursorPos chan no selection availlable
protected:
/**
* @brief informe the system thet the text change and the start position change
*/
virtual void markToUpdateTextPosition();
/**
* @brief update the display position start == > depending of the position of the Cursor and the size of the Data inside
* @change m_displayStartPosition < == updated
*/
virtual void updateTextPosition();
/**
* @brief change the cursor position with the curent position requested on the display
* @param[in] _pos Absolute position of the event
* @note The display is automaticly requested when change apear.
*/
virtual void updateCursorPosition(const vec2& _pos, bool _Selection=false);
public:
/**
* @brief Copy the selected data on the specify clipboard
* @param[in] _clipboardID Selected clipboard
*/
virtual void copySelectionToClipBoard(enum gale::context::clipBoard::clipboardListe _clipboardID);
/**
* @brief remove the selected area
* @note This request a regeneration of the display
*/
virtual void removeSelected();
public:
void onRegenerateDisplay() override;
bool onEventInput(const ewol::event::Input& _event) override;
bool onEventEntry(const ewol::event::Entry& _event) override;
void onEventClipboard(enum gale::context::clipBoard::clipboardListe _clipboardID) override;
void calculateMinMaxSize() override;
protected:
void onDraw() override;
void onGetFocus() override;
void onLostFocus() override;
virtual void changeStatusIn(int32_t _newStatusId);
protected:
esignal::Connection m_PCH; //!< Periodic call handle to remove it when needed
/**
* @brief Periodic call to update grapgic display
* @param[in] _event Time generic event
*/
void periodicCall(const ewol::event::Time& _event);
private: // callback functions
void onCallbackShortCut(const etk::String& _value);
void onCallbackEntryClean();
void onCallbackCut();
void onCallbackCopy();
void onCallbackPaste();
void onCallbackSelect(bool _all);
protected:
virtual void onChangePropertyPassword();
virtual void onChangePropertyShaper();
virtual void onChangePropertyValue();
virtual void onChangePropertyMaxCharacter();
virtual void onChangePropertyRegex();
virtual void onChangePropertyTextWhenNothing();
};
};
};

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