mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-13 13:01:55 +03:00
Importing Processing rev. 5503 (1.0.3).
This commit is contained in:
10
.classpath
Normal file
10
.classpath
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="processing/app/tools/format/|processing/app/tools/format/src/|processing/app/Trace.java|processing/app/RunnerClassLoader.java" kind="src" path="app/src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
|
||||
<classpathentry kind="lib" path="build/shared/lib/antlr.jar"/>
|
||||
<classpathentry kind="lib" path="build/shared/lib/registry.jar"/>
|
||||
<classpathentry kind="lib" path="build/shared/lib/apple.jar"/>
|
||||
<classpathentry kind="output" path="app/bin"/>
|
||||
</classpath>
|
17
.project
Normal file
17
.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>processing-head</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
263
.settings/org.eclipse.jdt.core.prefs
Normal file
263
.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,263 @@
|
||||
#Thu Jan 10 10:50:38 PST 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
|
||||
org.eclipse.jdt.core.compiler.compliance=1.4
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.3
|
||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
|
||||
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_header=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_html=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_source_code=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.comment.line_length=80
|
||||
org.eclipse.jdt.core.formatter.compact_else_if=true
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation=2
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
|
||||
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_empty_lines=false
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.jdt.core.formatter.indentation.size=2
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.lineSplit=80
|
||||
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
|
||||
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.jdt.core.formatter.tabulation.char=space
|
||||
org.eclipse.jdt.core.formatter.tabulation.size=2
|
||||
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
|
4
.settings/org.eclipse.jdt.ui.prefs
Normal file
4
.settings/org.eclipse.jdt.ui.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
#Thu Jan 10 10:50:38 PST 2008
|
||||
eclipse.preferences.version=1
|
||||
formatter_settings_version=11
|
||||
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
|
20
app/.classpath
Normal file
20
app/.classpath
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="processing/app/tools/format/" kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/dxf"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/net"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/opengl">
|
||||
<attributes>
|
||||
<attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="opengl/library"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/pdf"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/serial"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/video"/>
|
||||
<classpathentry kind="lib" path="lib/antlr.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jna.jar"/>
|
||||
<classpathentry kind="lib" path="lib/ecj.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
20
app/.classpath_macosx
Normal file
20
app/.classpath_macosx
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="processing/app/tools/format/" kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/dxf"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/net"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/opengl">
|
||||
<attributes>
|
||||
<attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="opengl/library"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/pdf"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/serial"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/video"/>
|
||||
<classpathentry kind="lib" path="lib/antlr.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jna.jar"/>
|
||||
<classpathentry kind="lib" path="lib/ecj.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
21
app/.classpath_vista
Executable file
21
app/.classpath_vista
Executable file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="processing/app/tools/format/|processing/app/macosx/" kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/dxf"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/net"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/opengl">
|
||||
<attributes>
|
||||
<attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="opengl/library"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/pdf"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/serial"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/video"/>
|
||||
<classpathentry kind="lib" path="lib/antlr.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jna.jar"/>
|
||||
<classpathentry kind="lib" path="lib/ecj.jar"/>
|
||||
<classpathentry kind="lib" path="C:/Users/fry/processing/build/windows/work/java/lib/tools.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
17
app/.project
Normal file
17
app/.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>processing</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
320
app/.settings/org.eclipse.jdt.core.prefs
Normal file
320
app/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,320 @@
|
||||
#Wed Jun 04 15:47:46 EDT 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
|
||||
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18
|
||||
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=82
|
||||
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18
|
||||
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_header=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_html=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_source_code=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.comment.line_length=80
|
||||
org.eclipse.jdt.core.formatter.compact_else_if=true
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation=2
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
|
||||
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_empty_lines=false
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.jdt.core.formatter.indentation.size=2
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.lineSplit=80
|
||||
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
|
||||
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.jdt.core.formatter.tabulation.char=space
|
||||
org.eclipse.jdt.core.formatter.tabulation.size=2
|
||||
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
|
4
app/.settings/org.eclipse.jdt.ui.prefs
Normal file
4
app/.settings/org.eclipse.jdt.ui.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
#Tue Jun 03 17:00:03 EDT 2008
|
||||
eclipse.preferences.version=1
|
||||
formatter_profile=_two spaces no tabs
|
||||
formatter_settings_version=11
|
BIN
app/lib/antlr.jar
Normal file
BIN
app/lib/antlr.jar
Normal file
Binary file not shown.
BIN
app/lib/apple.jar
Executable file
BIN
app/lib/apple.jar
Executable file
Binary file not shown.
BIN
app/lib/ecj.jar
Normal file
BIN
app/lib/ecj.jar
Normal file
Binary file not shown.
BIN
app/lib/jna.jar
Normal file
BIN
app/lib/jna.jar
Normal file
Binary file not shown.
132
app/src/antlr/ExtendedCommonASTWithHiddenTokens.java
Normal file
132
app/src/antlr/ExtendedCommonASTWithHiddenTokens.java
Normal file
@ -0,0 +1,132 @@
|
||||
package antlr;
|
||||
|
||||
/* ANTLR Translator Generator
|
||||
* Project led by Terence Parr at http://www.jGuru.com
|
||||
* Software rights: http://www.antlr.org/RIGHTS.html
|
||||
*
|
||||
* $Id: ExtendedCommonASTWithHiddenTokens.java 3419 2007-07-16 14:02:05Z fry $
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
//import antlr.*;
|
||||
import antlr.collections.*;
|
||||
//import antlr.collections.impl.*;
|
||||
|
||||
/** A CommonAST whose initialization copies hidden token
|
||||
* information from the Token used to create a node.
|
||||
*/
|
||||
public class ExtendedCommonASTWithHiddenTokens
|
||||
extends CommonASTWithHiddenTokens {
|
||||
|
||||
public ExtendedCommonASTWithHiddenTokens() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ExtendedCommonASTWithHiddenTokens(Token tok) {
|
||||
super(tok);
|
||||
}
|
||||
|
||||
public void initialize(AST ast) {
|
||||
ExtendedCommonASTWithHiddenTokens a =
|
||||
(ExtendedCommonASTWithHiddenTokens)ast;
|
||||
super.initialize(a);
|
||||
hiddenBefore = a.getHiddenBefore();
|
||||
hiddenAfter = a.getHiddenAfter();
|
||||
}
|
||||
|
||||
public String getHiddenAfterString() {
|
||||
|
||||
CommonHiddenStreamToken t;
|
||||
StringBuffer hiddenAfterString = new StringBuffer(100);
|
||||
|
||||
for ( t = hiddenAfter ; t != null ; t = t.getHiddenAfter() ) {
|
||||
hiddenAfterString.append(t.getText());
|
||||
}
|
||||
|
||||
return hiddenAfterString.toString();
|
||||
}
|
||||
|
||||
public String getHiddenBeforeString() {
|
||||
|
||||
antlr.CommonHiddenStreamToken
|
||||
child = null,
|
||||
parent = hiddenBefore;
|
||||
|
||||
// if there aren't any hidden tokens here, quietly return
|
||||
//
|
||||
if (parent == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// traverse back to the head of the list of tokens before this node
|
||||
do {
|
||||
child = parent;
|
||||
parent = child.getHiddenBefore();
|
||||
} while (parent != null);
|
||||
|
||||
// dump that list
|
||||
|
||||
StringBuffer hiddenBeforeString = new StringBuffer(100);
|
||||
|
||||
for ( CommonHiddenStreamToken t = child; t != null ;
|
||||
t = t.getHiddenAfter() ) {
|
||||
hiddenBeforeString.append(t.getText());
|
||||
}
|
||||
|
||||
return hiddenBeforeString.toString();
|
||||
}
|
||||
|
||||
public void xmlSerializeNode(Writer out)
|
||||
throws IOException {
|
||||
StringBuffer buf = new StringBuffer(100);
|
||||
buf.append("<");
|
||||
buf.append(getClass().getName() + " ");
|
||||
|
||||
buf.append("hiddenBeforeString=\"" +
|
||||
encode(getHiddenBeforeString()) +
|
||||
"\" text=\"" + encode(getText()) + "\" type=\"" +
|
||||
getType() + "\" hiddenAfterString=\"" +
|
||||
encode(getHiddenAfterString()) + "\"/>");
|
||||
out.write(buf.toString());
|
||||
}
|
||||
|
||||
public void xmlSerializeRootOpen(Writer out)
|
||||
throws IOException {
|
||||
StringBuffer buf = new StringBuffer(100);
|
||||
buf.append("<");
|
||||
buf.append(getClass().getName() + " ");
|
||||
buf.append("hiddenBeforeString=\"" +
|
||||
encode(getHiddenBeforeString()) +
|
||||
"\" text=\"" + encode(getText()) + "\" type=\"" +
|
||||
getType() + "\" hiddenAfterString=\"" +
|
||||
encode(getHiddenAfterString()) + "\">\n");
|
||||
out.write(buf.toString());
|
||||
}
|
||||
|
||||
public void xmlSerializeRootClose(Writer out)
|
||||
throws IOException {
|
||||
out.write("</" + getClass().getName() + ">\n");
|
||||
}
|
||||
|
||||
public void xmlSerialize(Writer out) throws IOException {
|
||||
// print out this node and all siblings
|
||||
for (AST node = this;
|
||||
node != null;
|
||||
node = node.getNextSibling()) {
|
||||
if (node.getFirstChild() == null) {
|
||||
// print guts (class name, attributes)
|
||||
((BaseAST)node).xmlSerializeNode(out);
|
||||
}
|
||||
else {
|
||||
((BaseAST)node).xmlSerializeRootOpen(out);
|
||||
|
||||
// print children
|
||||
((BaseAST)node.getFirstChild()).xmlSerialize(out);
|
||||
|
||||
// print end tag
|
||||
((BaseAST)node).xmlSerializeRootClose(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
221
app/src/antlr/TokenStreamCopyingHiddenTokenFilter.java
Normal file
221
app/src/antlr/TokenStreamCopyingHiddenTokenFilter.java
Normal file
@ -0,0 +1,221 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
package antlr;
|
||||
//package processing.app.preproc;
|
||||
|
||||
|
||||
//import antlr.*;
|
||||
import antlr.collections.impl.BitSet;
|
||||
|
||||
/**
|
||||
* This class provides TokenStreamHiddenTokenFilters with the concept of
|
||||
* tokens which can be copied so that they are seen by both the hidden token
|
||||
* stream as well as the parser itself. This is useful when one wants to use
|
||||
* an existing parser (like the Java parser included with ANTLR) that throws
|
||||
* away some tokens to create a parse tree which can be used to spit out
|
||||
* a copy of the code with only minor modifications.
|
||||
*
|
||||
* This code is partially derived from the public domain ANLTR TokenStream
|
||||
*/
|
||||
public class TokenStreamCopyingHiddenTokenFilter
|
||||
extends TokenStreamHiddenTokenFilter
|
||||
implements TokenStream {
|
||||
|
||||
protected BitSet copyMask;
|
||||
CommonHiddenStreamToken hiddenCopy = null;
|
||||
|
||||
public TokenStreamCopyingHiddenTokenFilter(TokenStream input) {
|
||||
super(input);
|
||||
copyMask = new BitSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that all tokens of type tokenType should be copied. The copy
|
||||
* is put in the stream of hidden tokens, and the original is returned in the
|
||||
* stream of normal tokens.
|
||||
*
|
||||
* @param tokenType integer representing the token type to copied
|
||||
*/
|
||||
public void copy(int tokenType) {
|
||||
copyMask.add(tokenType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a clone of the important parts of the given token. Note that this
|
||||
* does NOT copy the hiddenBefore and hiddenAfter fields.
|
||||
*
|
||||
* @param t token to partially clone
|
||||
* @return newly created partial clone
|
||||
*/
|
||||
public CommonHiddenStreamToken partialCloneToken(CommonHiddenStreamToken t) {
|
||||
|
||||
CommonHiddenStreamToken u = new CommonHiddenStreamToken(t.getType(),
|
||||
t.getText());
|
||||
u.setColumn(t.getColumn());
|
||||
u.setLine(t.getLine());
|
||||
u.setFilename(t.getFilename());
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
public void linkAndCopyToken(CommonHiddenStreamToken prev,
|
||||
CommonHiddenStreamToken monitored) {
|
||||
// create a copy of the token in the lookahead for use as hidden token
|
||||
hiddenCopy = partialCloneToken(LA(1));
|
||||
|
||||
// attach copy to the previous token, whether hidden or monitored
|
||||
prev.setHiddenAfter(hiddenCopy);
|
||||
|
||||
// if previous token was hidden, set the hiddenBefore pointer of the
|
||||
// copy to point back to it
|
||||
if (prev != monitored) {
|
||||
hiddenCopy.setHiddenBefore(prev);
|
||||
}
|
||||
|
||||
// we don't want the non-hidden copy to link back to the hidden
|
||||
// copy on the next pass through this function, so we leave
|
||||
// lastHiddenToken alone
|
||||
|
||||
//System.err.println("hidden copy: " + hiddenCopy.toString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private void consumeFirst() throws TokenStreamException {
|
||||
consume(); // get first token of input stream
|
||||
|
||||
// Handle situation where hidden or discarded tokens
|
||||
// appear first in input stream
|
||||
CommonHiddenStreamToken p=null;
|
||||
|
||||
// while hidden, copied, or discarded scarf tokens
|
||||
while ( hideMask.member(LA(1).getType()) ||
|
||||
discardMask.member(LA(1).getType()) ||
|
||||
copyMask.member(LA(1).getType()) ) {
|
||||
|
||||
// if we've hit one of the tokens that needs to be copied, we copy it
|
||||
// and then break out of the loop, because the parser needs to see it
|
||||
// too
|
||||
//
|
||||
if (copyMask.member(LA(1).getType())) {
|
||||
|
||||
// copy the token in the lookahead
|
||||
hiddenCopy = partialCloneToken(LA(1));
|
||||
|
||||
// if there's an existing token before this, link that and the
|
||||
// copy together
|
||||
if (p != null) {
|
||||
p.setHiddenAfter(hiddenCopy);
|
||||
hiddenCopy.setHiddenBefore(p); // double-link
|
||||
}
|
||||
|
||||
lastHiddenToken = hiddenCopy;
|
||||
if (firstHidden == null) {
|
||||
firstHidden = hiddenCopy;
|
||||
}
|
||||
|
||||
// we don't want to consume this token, because it also needs to
|
||||
// be passed through to the parser, so break out of the while look
|
||||
// entirely
|
||||
//
|
||||
break;
|
||||
} else if (hideMask.member(LA(1).getType())) {
|
||||
if (p != null) {
|
||||
p.setHiddenAfter(LA(1));
|
||||
LA(1).setHiddenBefore(p); // double-link
|
||||
}
|
||||
p = LA(1);
|
||||
|
||||
lastHiddenToken = p;
|
||||
if (firstHidden == null) {
|
||||
firstHidden = p; // record hidden token if first
|
||||
}
|
||||
}
|
||||
consume();
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the next monitored token.
|
||||
* Test the token following the monitored token.
|
||||
* If following is another monitored token, save it
|
||||
* for the next invocation of nextToken (like a single
|
||||
* lookahead token) and return it then.
|
||||
* If following is unmonitored, nondiscarded (hidden)
|
||||
* channel token, add it to the monitored token.
|
||||
*
|
||||
* Note: EOF must be a monitored Token.
|
||||
*/
|
||||
public Token nextToken() throws TokenStreamException {
|
||||
// handle an initial condition; don't want to get lookahead
|
||||
// token of this splitter until first call to nextToken
|
||||
if (LA(1) == null) {
|
||||
consumeFirst();
|
||||
}
|
||||
|
||||
//System.err.println();
|
||||
|
||||
// we always consume hidden tokens after monitored, thus,
|
||||
// upon entry LA(1) is a monitored token.
|
||||
CommonHiddenStreamToken monitored = LA(1);
|
||||
|
||||
// point to hidden tokens found during last invocation
|
||||
monitored.setHiddenBefore(lastHiddenToken);
|
||||
lastHiddenToken = null;
|
||||
|
||||
// Look for hidden tokens, hook them into list emanating
|
||||
// from the monitored tokens.
|
||||
consume();
|
||||
CommonHiddenStreamToken prev = monitored;
|
||||
|
||||
// deal with as many not-purely-monitored tokens as possible
|
||||
while ( hideMask.member(LA(1).getType()) ||
|
||||
discardMask.member(LA(1).getType()) ||
|
||||
copyMask.member(LA(1).getType()) ) {
|
||||
|
||||
if (copyMask.member(LA(1).getType())) {
|
||||
|
||||
// copy the token and link it backwards
|
||||
if (hiddenCopy != null) {
|
||||
linkAndCopyToken(hiddenCopy, monitored);
|
||||
} else {
|
||||
linkAndCopyToken(prev, monitored);
|
||||
}
|
||||
|
||||
// we now need to parse it as a monitored token, so we return, which
|
||||
// avoids the consume() call at the end of this loop. the next call
|
||||
// will parse it as a monitored token.
|
||||
//System.err.println("returned: " + monitored.toString());
|
||||
return monitored;
|
||||
|
||||
} else if (hideMask.member(LA(1).getType())) {
|
||||
|
||||
// attach the hidden token to the monitored in a chain
|
||||
// link forwards
|
||||
prev.setHiddenAfter(LA(1));
|
||||
|
||||
// link backwards
|
||||
if (prev != monitored) { //hidden cannot point to monitored tokens
|
||||
LA(1).setHiddenBefore(prev);
|
||||
} else if (hiddenCopy != null) {
|
||||
hiddenCopy.setHiddenAfter(LA(1));
|
||||
LA(1).setHiddenBefore(hiddenCopy);
|
||||
hiddenCopy = null;
|
||||
}
|
||||
|
||||
//System.err.println("hidden: " + prev.getHiddenAfter().toString() + "\" after: " + prev.toString());
|
||||
prev = lastHiddenToken = LA(1);
|
||||
}
|
||||
|
||||
consume();
|
||||
}
|
||||
|
||||
// remember the last hidden token for next time around
|
||||
if (hiddenCopy != null) {
|
||||
lastHiddenToken = hiddenCopy;
|
||||
hiddenCopy = null;
|
||||
}
|
||||
|
||||
//System.err.println("returned: " + monitored.toString());
|
||||
return monitored;
|
||||
}
|
||||
}
|
1277
app/src/antlr/java/java.g
Normal file
1277
app/src/antlr/java/java.g
Normal file
File diff suppressed because it is too large
Load Diff
2002
app/src/antlr/java/java.g.java15
Normal file
2002
app/src/antlr/java/java.g.java15
Normal file
File diff suppressed because it is too large
Load Diff
326
app/src/antlr/java/java.tree.g
Normal file
326
app/src/antlr/java/java.tree.g
Normal file
@ -0,0 +1,326 @@
|
||||
package antlr;
|
||||
|
||||
|
||||
/** Java 1.3 AST Recognizer Grammar
|
||||
*
|
||||
* Author: (see java.g preamble)
|
||||
*
|
||||
* This grammar is in the PUBLIC DOMAIN
|
||||
*/
|
||||
class JavaTreeParser extends TreeParser;
|
||||
|
||||
options {
|
||||
importVocab = Java;
|
||||
}
|
||||
|
||||
compilationUnit
|
||||
: (packageDefinition)?
|
||||
(importDefinition)*
|
||||
(typeDefinition)*
|
||||
;
|
||||
|
||||
packageDefinition
|
||||
: #( PACKAGE_DEF identifier )
|
||||
;
|
||||
|
||||
importDefinition
|
||||
: #( IMPORT identifierStar )
|
||||
;
|
||||
|
||||
typeDefinition
|
||||
: #(CLASS_DEF modifiers IDENT extendsClause implementsClause objBlock )
|
||||
| #(INTERFACE_DEF modifiers IDENT extendsClause interfaceBlock )
|
||||
;
|
||||
|
||||
typeSpec
|
||||
: #(TYPE typeSpecArray)
|
||||
;
|
||||
|
||||
typeSpecArray
|
||||
: #( ARRAY_DECLARATOR typeSpecArray )
|
||||
| type
|
||||
;
|
||||
|
||||
type: identifier
|
||||
| builtInType
|
||||
;
|
||||
|
||||
builtInType
|
||||
: "void"
|
||||
| "boolean"
|
||||
| "byte"
|
||||
| "char"
|
||||
| "short"
|
||||
| "int"
|
||||
| "float"
|
||||
| "long"
|
||||
| "double"
|
||||
;
|
||||
|
||||
modifiers
|
||||
: #( MODIFIERS (modifier)* )
|
||||
;
|
||||
|
||||
modifier
|
||||
: "private"
|
||||
| "public"
|
||||
| "protected"
|
||||
| "static"
|
||||
| "transient"
|
||||
| "final"
|
||||
| "abstract"
|
||||
| "native"
|
||||
| "threadsafe"
|
||||
| "synchronized"
|
||||
| "const"
|
||||
| "volatile"
|
||||
| "strictfp"
|
||||
;
|
||||
|
||||
extendsClause
|
||||
: #(EXTENDS_CLAUSE (identifier)* )
|
||||
;
|
||||
|
||||
implementsClause
|
||||
: #(IMPLEMENTS_CLAUSE (identifier)* )
|
||||
;
|
||||
|
||||
|
||||
interfaceBlock
|
||||
: #( OBJBLOCK
|
||||
( methodDecl
|
||||
| variableDef
|
||||
)*
|
||||
)
|
||||
;
|
||||
|
||||
objBlock
|
||||
: #( OBJBLOCK
|
||||
( ctorDef
|
||||
| methodDef
|
||||
| variableDef
|
||||
| typeDefinition
|
||||
| #(STATIC_INIT slist)
|
||||
| #(INSTANCE_INIT slist)
|
||||
)*
|
||||
)
|
||||
;
|
||||
|
||||
ctorDef
|
||||
: #(CTOR_DEF modifiers methodHead (slist)?)
|
||||
;
|
||||
|
||||
methodDecl
|
||||
: #(METHOD_DEF modifiers typeSpec methodHead)
|
||||
;
|
||||
|
||||
methodDef
|
||||
: #(METHOD_DEF modifiers typeSpec methodHead (slist)?)
|
||||
;
|
||||
|
||||
variableDef
|
||||
: #(VARIABLE_DEF modifiers typeSpec variableDeclarator varInitializer)
|
||||
;
|
||||
|
||||
parameterDef
|
||||
: #(PARAMETER_DEF modifiers typeSpec IDENT )
|
||||
;
|
||||
|
||||
objectinitializer
|
||||
: #(INSTANCE_INIT slist)
|
||||
;
|
||||
|
||||
variableDeclarator
|
||||
: IDENT
|
||||
| LBRACK variableDeclarator
|
||||
;
|
||||
|
||||
varInitializer
|
||||
: #(ASSIGN initializer)
|
||||
|
|
||||
;
|
||||
|
||||
initializer
|
||||
: expression
|
||||
| arrayInitializer
|
||||
;
|
||||
|
||||
arrayInitializer
|
||||
: #(ARRAY_INIT (initializer)*)
|
||||
;
|
||||
|
||||
methodHead
|
||||
: IDENT #( PARAMETERS (parameterDef)* ) (throwsClause)?
|
||||
;
|
||||
|
||||
throwsClause
|
||||
: #( "throws" (identifier)* )
|
||||
;
|
||||
|
||||
identifier
|
||||
: IDENT
|
||||
| #( DOT identifier IDENT )
|
||||
;
|
||||
|
||||
identifierStar
|
||||
: IDENT
|
||||
| #( DOT identifier (STAR|IDENT) )
|
||||
;
|
||||
|
||||
slist
|
||||
: #( SLIST (stat)* )
|
||||
;
|
||||
|
||||
stat: typeDefinition
|
||||
| variableDef
|
||||
| expression
|
||||
| #(LABELED_STAT IDENT stat)
|
||||
| #("if" expression stat (stat)? )
|
||||
| #( "for"
|
||||
#(FOR_INIT (variableDef | elist)?)
|
||||
#(FOR_CONDITION (expression)?)
|
||||
#(FOR_ITERATOR (elist)?)
|
||||
stat
|
||||
)
|
||||
| #("while" expression stat)
|
||||
| #("do" stat expression)
|
||||
| #("break" (IDENT)? )
|
||||
| #("continue" (IDENT)? )
|
||||
| #("return" (expression)? )
|
||||
| #("switch" expression (caseGroup)*)
|
||||
| #("throw" expression)
|
||||
| #("synchronized" expression stat)
|
||||
| tryBlock
|
||||
| slist // nested SLIST
|
||||
// uncomment to make assert JDK 1.4 stuff work
|
||||
| #("assert" expression (expression)?)
|
||||
| EMPTY_STAT
|
||||
;
|
||||
|
||||
caseGroup
|
||||
: #(CASE_GROUP (#("case" expression) | "default")+ slist)
|
||||
;
|
||||
|
||||
tryBlock
|
||||
: #( "try" slist (handler)* (#("finally" slist))? )
|
||||
;
|
||||
|
||||
handler
|
||||
: #( "catch" parameterDef slist )
|
||||
;
|
||||
|
||||
elist
|
||||
: #( ELIST (expression)* )
|
||||
;
|
||||
|
||||
expression
|
||||
: #(EXPR expr)
|
||||
;
|
||||
|
||||
expr: #(QUESTION expr expr expr) // trinary operator
|
||||
| #(ASSIGN expr expr) // binary operators...
|
||||
| #(PLUS_ASSIGN expr expr)
|
||||
| #(MINUS_ASSIGN expr expr)
|
||||
| #(STAR_ASSIGN expr expr)
|
||||
| #(DIV_ASSIGN expr expr)
|
||||
| #(MOD_ASSIGN expr expr)
|
||||
| #(SR_ASSIGN expr expr)
|
||||
| #(BSR_ASSIGN expr expr)
|
||||
| #(SL_ASSIGN expr expr)
|
||||
| #(BAND_ASSIGN expr expr)
|
||||
| #(BXOR_ASSIGN expr expr)
|
||||
| #(BOR_ASSIGN expr expr)
|
||||
| #(LOR expr expr)
|
||||
| #(LAND expr expr)
|
||||
| #(BOR expr expr)
|
||||
| #(BXOR expr expr)
|
||||
| #(BAND expr expr)
|
||||
| #(NOT_EQUAL expr expr)
|
||||
| #(EQUAL expr expr)
|
||||
| #(LT expr expr)
|
||||
| #(GT expr expr)
|
||||
| #(LE expr expr)
|
||||
| #(GE expr expr)
|
||||
| #(SL expr expr)
|
||||
| #(SR expr expr)
|
||||
| #(BSR expr expr)
|
||||
| #(PLUS expr expr)
|
||||
| #(MINUS expr expr)
|
||||
| #(DIV expr expr)
|
||||
| #(MOD expr expr)
|
||||
| #(STAR expr expr)
|
||||
| #(INC expr)
|
||||
| #(DEC expr)
|
||||
| #(POST_INC expr)
|
||||
| #(POST_DEC expr)
|
||||
| #(BNOT expr)
|
||||
| #(LNOT expr)
|
||||
| #("instanceof" expr expr)
|
||||
| #(UNARY_MINUS expr)
|
||||
| #(UNARY_PLUS expr)
|
||||
| primaryExpression
|
||||
;
|
||||
|
||||
primaryExpression
|
||||
: IDENT
|
||||
| #( DOT
|
||||
( expr
|
||||
( IDENT
|
||||
| arrayIndex
|
||||
| "this"
|
||||
| "class"
|
||||
| #( "new" IDENT elist )
|
||||
| "super"
|
||||
)
|
||||
| #(ARRAY_DECLARATOR typeSpecArray)
|
||||
| builtInType ("class")?
|
||||
)
|
||||
)
|
||||
| arrayIndex
|
||||
| #(METHOD_CALL primaryExpression elist)
|
||||
| ctorCall
|
||||
| #(TYPECAST typeSpec expr)
|
||||
| newExpression
|
||||
| constant
|
||||
| "super"
|
||||
| "true"
|
||||
| "false"
|
||||
| "this"
|
||||
| "null"
|
||||
| typeSpec // type name used with instanceof
|
||||
;
|
||||
|
||||
ctorCall
|
||||
: #( CTOR_CALL elist )
|
||||
| #( SUPER_CTOR_CALL
|
||||
( elist
|
||||
| primaryExpression elist
|
||||
)
|
||||
)
|
||||
;
|
||||
|
||||
arrayIndex
|
||||
: #(INDEX_OP expr expression)
|
||||
;
|
||||
|
||||
constant
|
||||
: NUM_INT
|
||||
| CHAR_LITERAL
|
||||
| STRING_LITERAL
|
||||
| NUM_FLOAT
|
||||
| NUM_DOUBLE
|
||||
| NUM_LONG
|
||||
;
|
||||
|
||||
newExpression
|
||||
: #( "new" type
|
||||
( newArrayDeclarator (arrayInitializer)?
|
||||
| elist (objBlock)?
|
||||
)
|
||||
)
|
||||
|
||||
;
|
||||
|
||||
newArrayDeclarator
|
||||
: #( ARRAY_DECLARATOR (newArrayDeclarator)? (expression)? )
|
||||
;
|
2021
app/src/processing/app/Base.java
Normal file
2021
app/src/processing/app/Base.java
Normal file
File diff suppressed because it is too large
Load Diff
297
app/src/processing/app/Commander.java
Normal file
297
app/src/processing/app/Commander.java
Normal file
@ -0,0 +1,297 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
import processing.app.debug.*;
|
||||
|
||||
|
||||
/**
|
||||
* Class to handle running Processing from the command line.
|
||||
* <PRE>
|
||||
* --help Show the help text.
|
||||
*
|
||||
* --sketch=<name&rt; Specify the sketch folder (required)
|
||||
* --output=<name&rt; Specify the output folder (required and
|
||||
* cannot be the same as the sketch folder.)
|
||||
*
|
||||
* --preprocess Preprocess a sketch into .java files.
|
||||
* --build Preprocess and compile a sketch into .class files.
|
||||
* --run Preprocess, compile, and run a sketch.
|
||||
* --present Preprocess, compile, and run a sketch full screen.
|
||||
*
|
||||
* --export-applet Export an applet.
|
||||
* --export-application Export an application.
|
||||
* --platform Specify the platform (export to application only).
|
||||
* Should be one of 'windows', 'macosx', or 'linux'.
|
||||
*
|
||||
* --preferences=<file&rt; Specify a preferences file to use (optional).
|
||||
* </PRE>
|
||||
*
|
||||
* To build the command line version, first build for your platform,
|
||||
* then cd to processing/build/cmd and type 'dist.sh'. This will create a
|
||||
* usable installation plus a zip file of the same.
|
||||
*
|
||||
* @author fry
|
||||
*/
|
||||
public class Commander implements RunnerListener {
|
||||
static final String helpArg = "--help";
|
||||
static final String preprocArg = "--preprocess";
|
||||
static final String buildArg = "--build";
|
||||
static final String runArg = "--run";
|
||||
static final String presentArg = "--present";
|
||||
static final String sketchArg = "--sketch=";
|
||||
static final String outputArg = "--output=";
|
||||
static final String exportAppletArg = "--export-applet";
|
||||
static final String exportApplicationArg = "--export-application";
|
||||
static final String platformArg = "--platform=";
|
||||
static final String preferencesArg = "--preferences=";
|
||||
|
||||
static final int HELP = -1;
|
||||
static final int PREPROCESS = 0;
|
||||
static final int BUILD = 1;
|
||||
static final int RUN = 2;
|
||||
static final int PRESENT = 3;
|
||||
static final int EXPORT_APPLET = 4;
|
||||
static final int EXPORT_APPLICATION = 5;
|
||||
|
||||
Sketch sketch;
|
||||
|
||||
|
||||
static public void main(String[] args) {
|
||||
// init the platform so that prefs and other native code is ready to go
|
||||
Base.initPlatform();
|
||||
// make sure a full JDK is installed
|
||||
Base.initRequirements();
|
||||
// run static initialization that grabs all the prefs
|
||||
//Preferences.init(null);
|
||||
// launch command line handler
|
||||
new Commander(args);
|
||||
}
|
||||
|
||||
|
||||
public Commander(String[] args) {
|
||||
String sketchFolder = null;
|
||||
String pdePath = null; // path to the .pde file
|
||||
String outputPath = null;
|
||||
String preferencesPath = null;
|
||||
int platformIndex = PApplet.platform; // default to this platform
|
||||
int mode = HELP;
|
||||
|
||||
for (String arg : args) {
|
||||
if (arg.length() == 0) {
|
||||
// ignore it, just the crappy shell script
|
||||
|
||||
} else if (arg.equals(helpArg)) {
|
||||
// mode already set to HELP
|
||||
|
||||
} else if (arg.equals(buildArg)) {
|
||||
mode = BUILD;
|
||||
|
||||
} else if (arg.equals(runArg)) {
|
||||
mode = RUN;
|
||||
|
||||
} else if (arg.equals(presentArg)) {
|
||||
mode = PRESENT;
|
||||
|
||||
} else if (arg.equals(preprocArg)) {
|
||||
mode = PREPROCESS;
|
||||
|
||||
} else if (arg.equals(exportAppletArg)) {
|
||||
mode = EXPORT_APPLET;
|
||||
|
||||
} else if (arg.equals(exportApplicationArg)) {
|
||||
mode = EXPORT_APPLICATION;
|
||||
|
||||
} else if (arg.startsWith(platformArg)) {
|
||||
String platformStr = arg.substring(platformArg.length());
|
||||
platformIndex = Base.getPlatformIndex(platformStr);
|
||||
if (platformIndex == -1) {
|
||||
complainAndQuit(platformStr + " should instead be " +
|
||||
"'windows', 'macosx', or 'linux'.");
|
||||
}
|
||||
} else if (arg.startsWith(sketchArg)) {
|
||||
sketchFolder = arg.substring(sketchArg.length());
|
||||
File sketchy = new File(sketchFolder);
|
||||
File pdeFile = new File(sketchy, sketchy.getName() + ".pde");
|
||||
pdePath = pdeFile.getAbsolutePath();
|
||||
|
||||
} else if (arg.startsWith(outputArg)) {
|
||||
outputPath = arg.substring(outputArg.length());
|
||||
|
||||
} else {
|
||||
complainAndQuit("I don't know anything about " + arg + ".");
|
||||
}
|
||||
}
|
||||
|
||||
if ((outputPath == null) &&
|
||||
(mode == PREPROCESS || mode == BUILD ||
|
||||
mode == RUN || mode == PRESENT)) {
|
||||
complainAndQuit("An output path must be specified when using " +
|
||||
preprocArg + ", " + buildArg + ", " +
|
||||
runArg + ", or " + presentArg + ".");
|
||||
}
|
||||
|
||||
if (mode == HELP) {
|
||||
printCommandLine(System.out);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// --present --platform=windows "--sketch=/Applications/Processing 0148/examples/Basics/Arrays/Array" --output=test-build
|
||||
|
||||
File outputFolder = new File(outputPath);
|
||||
if (!outputFolder.exists()) {
|
||||
if (!outputFolder.mkdirs()) {
|
||||
complainAndQuit("Could not create the output folder.");
|
||||
}
|
||||
}
|
||||
|
||||
// run static initialization that grabs all the prefs
|
||||
// (also pass in a prefs path if that was specified)
|
||||
Preferences.init(preferencesPath);
|
||||
|
||||
if (sketchFolder == null) {
|
||||
complainAndQuit("No sketch path specified.");
|
||||
|
||||
} else if (outputPath.equals(pdePath)) {
|
||||
complainAndQuit("The sketch path and output path cannot be identical.");
|
||||
|
||||
} else if (!pdePath.toLowerCase().endsWith(".pde")) {
|
||||
complainAndQuit("Sketch path must point to the main .pde file.");
|
||||
|
||||
} else {
|
||||
//Sketch sketch = null;
|
||||
boolean success = false;
|
||||
|
||||
try {
|
||||
sketch = new Sketch(null, pdePath);
|
||||
if (mode == PREPROCESS) {
|
||||
success = sketch.preprocess(outputPath) != null;
|
||||
|
||||
} else if (mode == BUILD) {
|
||||
success = sketch.build(outputPath) != null;
|
||||
|
||||
} else if (mode == RUN || mode == PRESENT) {
|
||||
String className = sketch.build(outputPath);
|
||||
if (className != null) {
|
||||
success = true;
|
||||
Runner runner =
|
||||
new Runner(sketch, className, mode == PRESENT, this);
|
||||
runner.launch();
|
||||
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
} else if (mode == EXPORT_APPLET) {
|
||||
if (outputPath != null) {
|
||||
success = sketch.exportApplet(outputPath);
|
||||
} else {
|
||||
String target = sketchFolder + File.separatorChar + "applet";
|
||||
success = sketch.exportApplet(target);
|
||||
}
|
||||
} else if (mode == EXPORT_APPLICATION) {
|
||||
if (outputPath != null) {
|
||||
success = sketch.exportApplication(outputPath, platformIndex);
|
||||
} else {
|
||||
//String sketchFolder =
|
||||
// pdePath.substring(0, pdePath.lastIndexOf(File.separatorChar));
|
||||
outputPath =
|
||||
sketchFolder + File.separatorChar +
|
||||
"application." + Base.getPlatformName(platformIndex);
|
||||
success = sketch.exportApplication(outputPath, platformIndex);
|
||||
}
|
||||
}
|
||||
System.exit(success ? 0 : 1);
|
||||
|
||||
} catch (RunnerException re) {
|
||||
statusError(re);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void statusError(String message) {
|
||||
System.err.println(message);
|
||||
}
|
||||
|
||||
|
||||
public void statusError(Exception exception) {
|
||||
if (exception instanceof RunnerException) {
|
||||
RunnerException re = (RunnerException) exception;
|
||||
|
||||
// format the runner exception like emacs
|
||||
//blah.java:2:10:2:13: Syntax Error: This is a big error message
|
||||
String filename = sketch.getCode(re.getCodeIndex()).getFileName();
|
||||
int line = re.getCodeLine();
|
||||
int column = re.getCodeColumn();
|
||||
if (column == -1) column = 0;
|
||||
// TODO if column not specified, should just select the whole line.
|
||||
System.err.println(filename + ":" +
|
||||
line + ":" + column + ":" +
|
||||
line + ":" + column + ":" + " " + re.getMessage());
|
||||
} else {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void complainAndQuit(String lastWords) {
|
||||
printCommandLine(System.err);
|
||||
System.err.println(lastWords);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
static void printCommandLine(PrintStream out) {
|
||||
out.println("Processing " + Base.VERSION_NAME + " rocks the console.");
|
||||
out.println();
|
||||
out.println("--help Show this help text.");
|
||||
out.println();
|
||||
out.println("--sketch=<name> Specify the sketch folder (required)");
|
||||
out.println("--output=<name> Specify the output folder (required and");
|
||||
out.println(" cannot be the same as the sketch folder.)");
|
||||
out.println();
|
||||
out.println("--preprocess Preprocess a sketch into .java files.");
|
||||
out.println("--build Preprocess and compile a sketch into .class files.");
|
||||
out.println("--run Preprocess, compile, and run a sketch.");
|
||||
out.println("--present Preprocess, compile, and run a sketch full screen.");
|
||||
out.println();
|
||||
out.println("--export-applet Export an applet.");
|
||||
out.println("--export-application Export an application.");
|
||||
out.println("--platform Specify the platform (export to application only).");
|
||||
out.println(" Should be one of 'windows', 'macosx', or 'linux'.");
|
||||
out.println();
|
||||
out.println("--preferences=<file> Specify a preferences file to use (optional).");
|
||||
}
|
||||
}
|
2301
app/src/processing/app/Editor.java
Normal file
2301
app/src/processing/app/Editor.java
Normal file
File diff suppressed because it is too large
Load Diff
460
app/src/processing/app/EditorConsole.java
Normal file
460
app/src/processing/app/EditorConsole.java
Normal file
@ -0,0 +1,460 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Message console that sits below the editing area.
|
||||
* <P>
|
||||
* Debugging this class is tricky... If it's throwing exceptions,
|
||||
* don't take over System.err, and debug while watching just System.out
|
||||
* or just write println() or whatever directly to systemOut or systemErr.
|
||||
*/
|
||||
public class EditorConsole extends JScrollPane {
|
||||
Editor editor;
|
||||
|
||||
JTextPane consoleTextPane;
|
||||
BufferedStyledDocument consoleDoc;
|
||||
|
||||
MutableAttributeSet stdStyle;
|
||||
MutableAttributeSet errStyle;
|
||||
|
||||
boolean cerror;
|
||||
|
||||
int maxLineCount;
|
||||
|
||||
static File errFile;
|
||||
static File outFile;
|
||||
static File tempFolder;
|
||||
|
||||
// Single static instance shared because there's only one real System.out.
|
||||
// Within the input handlers, the currentConsole variable will be used to
|
||||
// echo things to the correct location.
|
||||
|
||||
static public PrintStream systemOut;
|
||||
static public PrintStream systemErr;
|
||||
|
||||
static PrintStream consoleOut;
|
||||
static PrintStream consoleErr;
|
||||
|
||||
static OutputStream stdoutFile;
|
||||
static OutputStream stderrFile;
|
||||
|
||||
static EditorConsole currentConsole;
|
||||
|
||||
|
||||
public EditorConsole(Editor editor) {
|
||||
this.editor = editor;
|
||||
|
||||
maxLineCount = Preferences.getInteger("console.length");
|
||||
|
||||
consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
|
||||
consoleTextPane = new JTextPane(consoleDoc);
|
||||
consoleTextPane.setEditable(false);
|
||||
|
||||
// necessary?
|
||||
MutableAttributeSet standard = new SimpleAttributeSet();
|
||||
StyleConstants.setAlignment(standard, StyleConstants.ALIGN_LEFT);
|
||||
consoleDoc.setParagraphAttributes(0, 0, standard, true);
|
||||
|
||||
// build styles for different types of console output
|
||||
Color bgColor = Theme.getColor("console.color");
|
||||
Color fgColorOut = Theme.getColor("console.output.color");
|
||||
Color fgColorErr = Theme.getColor("console.error.color");
|
||||
Font font = Theme.getFont("console.font");
|
||||
|
||||
stdStyle = new SimpleAttributeSet();
|
||||
StyleConstants.setForeground(stdStyle, fgColorOut);
|
||||
StyleConstants.setBackground(stdStyle, bgColor);
|
||||
StyleConstants.setFontSize(stdStyle, font.getSize());
|
||||
StyleConstants.setFontFamily(stdStyle, font.getFamily());
|
||||
StyleConstants.setBold(stdStyle, font.isBold());
|
||||
StyleConstants.setItalic(stdStyle, font.isItalic());
|
||||
|
||||
errStyle = new SimpleAttributeSet();
|
||||
StyleConstants.setForeground(errStyle, fgColorErr);
|
||||
StyleConstants.setBackground(errStyle, bgColor);
|
||||
StyleConstants.setFontSize(errStyle, font.getSize());
|
||||
StyleConstants.setFontFamily(errStyle, font.getFamily());
|
||||
StyleConstants.setBold(errStyle, font.isBold());
|
||||
StyleConstants.setItalic(errStyle, font.isItalic());
|
||||
|
||||
consoleTextPane.setBackground(bgColor);
|
||||
|
||||
// add the jtextpane to this scrollpane
|
||||
this.setViewportView(consoleTextPane);
|
||||
|
||||
// calculate height of a line of text in pixels
|
||||
// and size window accordingly
|
||||
FontMetrics metrics = this.getFontMetrics(font);
|
||||
int height = metrics.getAscent() + metrics.getDescent();
|
||||
int lines = Preferences.getInteger("console.lines"); //, 4);
|
||||
int sizeFudge = 6; //10; // unclear why this is necessary, but it is
|
||||
setPreferredSize(new Dimension(1024, (height * lines) + sizeFudge));
|
||||
setMinimumSize(new Dimension(1024, (height * 4) + sizeFudge));
|
||||
|
||||
if (systemOut == null) {
|
||||
systemOut = System.out;
|
||||
systemErr = System.err;
|
||||
|
||||
// Create a temporary folder which will have a randomized name. Has to
|
||||
// be randomized otherwise another instance of Processing (or one of its
|
||||
// sister IDEs) might collide with the file causing permissions problems.
|
||||
// The files and folders are not deleted on exit because they may be
|
||||
// needed for debugging or bug reporting.
|
||||
tempFolder = Base.createTempFolder("console");
|
||||
try {
|
||||
String outFileName = Preferences.get("console.output.file");
|
||||
if (outFileName != null) {
|
||||
outFile = new File(tempFolder, outFileName);
|
||||
stdoutFile = new FileOutputStream(outFile);
|
||||
}
|
||||
|
||||
String errFileName = Preferences.get("console.error.file");
|
||||
if (errFileName != null) {
|
||||
errFile = new File(tempFolder, errFileName);
|
||||
stderrFile = new FileOutputStream(errFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Base.showWarning("Console Error",
|
||||
"A problem occurred while trying to open the\n" +
|
||||
"files used to store the console output.", e);
|
||||
}
|
||||
consoleOut = new PrintStream(new EditorConsoleStream(false));
|
||||
consoleErr = new PrintStream(new EditorConsoleStream(true));
|
||||
|
||||
if (Preferences.getBoolean("console")) {
|
||||
try {
|
||||
System.setOut(consoleOut);
|
||||
System.setErr(consoleErr);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(systemOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// to fix ugliness.. normally macosx java 1.3 puts an
|
||||
// ugly white border around this object, so turn it off.
|
||||
if (Base.isMacOS()) {
|
||||
setBorder(null);
|
||||
}
|
||||
|
||||
// periodically post buffered messages to the console
|
||||
// should the interval come from the preferences file?
|
||||
new javax.swing.Timer(250, new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
// only if new text has been added
|
||||
if (consoleDoc.hasAppendage) {
|
||||
// insert the text that's been added in the meantime
|
||||
consoleDoc.insertAll();
|
||||
// always move to the end of the text as it's added
|
||||
consoleTextPane.setCaretPosition(consoleDoc.getLength());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
static public void setEditor(Editor editor) {
|
||||
currentConsole = editor.console;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the streams so that the temporary files can be deleted.
|
||||
* <p/>
|
||||
* File.deleteOnExit() cannot be used because the stdout and stderr
|
||||
* files are inside a folder, and have to be deleted before the
|
||||
* folder itself is deleted, which can't be guaranteed when using
|
||||
* the deleteOnExit() method.
|
||||
*/
|
||||
public void handleQuit() {
|
||||
// replace original streams to remove references to console's streams
|
||||
System.setOut(systemOut);
|
||||
System.setErr(systemErr);
|
||||
|
||||
// close the PrintStream
|
||||
consoleOut.close();
|
||||
consoleErr.close();
|
||||
|
||||
// also have to close the original FileOutputStream
|
||||
// otherwise it won't be shut down completely
|
||||
try {
|
||||
stdoutFile.close();
|
||||
stderrFile.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(systemOut);
|
||||
}
|
||||
|
||||
outFile.delete();
|
||||
errFile.delete();
|
||||
tempFolder.delete();
|
||||
}
|
||||
|
||||
|
||||
public void write(byte b[], int offset, int length, boolean err) {
|
||||
if (err != cerror) {
|
||||
// advance the line because switching between err/out streams
|
||||
// potentially, could check whether we're already on a new line
|
||||
message("", cerror, true);
|
||||
}
|
||||
|
||||
// we could do some cross platform CR/LF mangling here before outputting
|
||||
|
||||
// add text to output document
|
||||
message(new String(b, offset, length), err, false);
|
||||
// set last error state
|
||||
cerror = err;
|
||||
}
|
||||
|
||||
|
||||
// added sync for 0091.. not sure if it helps or hinders
|
||||
synchronized public void message(String what, boolean err, boolean advance) {
|
||||
if (err) {
|
||||
systemErr.print(what);
|
||||
//systemErr.print("CE" + what);
|
||||
} else {
|
||||
systemOut.print(what);
|
||||
//systemOut.print("CO" + what);
|
||||
}
|
||||
|
||||
if (advance) {
|
||||
appendText("\n", err);
|
||||
if (err) {
|
||||
systemErr.println();
|
||||
} else {
|
||||
systemOut.println();
|
||||
}
|
||||
}
|
||||
|
||||
// to console display
|
||||
appendText(what, err);
|
||||
// moved down here since something is punting
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append a piece of text to the console.
|
||||
* <P>
|
||||
* Swing components are NOT thread-safe, and since the MessageSiphon
|
||||
* instantiates new threads, and in those callbacks, they often print
|
||||
* output to stdout and stderr, which are wrapped by EditorConsoleStream
|
||||
* and eventually leads to EditorConsole.appendText(), which directly
|
||||
* updates the Swing text components, causing deadlock.
|
||||
* <P>
|
||||
* Updates are buffered to the console and displayed at regular
|
||||
* intervals on Swing's event-dispatching thread. (patch by David Mellis)
|
||||
*/
|
||||
synchronized private void appendText(String txt, boolean e) {
|
||||
consoleDoc.appendString(txt, e ? errStyle : stdStyle);
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
try {
|
||||
consoleDoc.remove(0, consoleDoc.getLength());
|
||||
} catch (BadLocationException e) {
|
||||
// ignore the error otherwise this will cause an infinite loop
|
||||
// maybe not a good idea in the long run?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
class EditorConsoleStream extends OutputStream {
|
||||
//static EditorConsole current;
|
||||
boolean err; // whether stderr or stdout
|
||||
byte single[] = new byte[1];
|
||||
|
||||
public EditorConsoleStream(boolean err) {
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
public void close() { }
|
||||
|
||||
public void flush() { }
|
||||
|
||||
public void write(byte b[]) { // appears never to be used
|
||||
// if (currentConsole.isDisplayable()) {
|
||||
currentConsole.write(b, 0, b.length, err);
|
||||
// } else {
|
||||
// systemOut.println("not displayable");
|
||||
// if (err) {
|
||||
// systemErr.write(b, 0, b.length);
|
||||
// } else {
|
||||
// systemOut.write(b, 0, b.length);
|
||||
// }
|
||||
// }
|
||||
|
||||
OutputStream echo = err ? stderrFile : stdoutFile;
|
||||
if (echo != null) {
|
||||
try {
|
||||
echo.write(b);
|
||||
echo.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
echo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(byte b[], int offset, int length) {
|
||||
currentConsole.write(b, offset, length, err);
|
||||
// if (currentConsole.isDisplayable()) {
|
||||
// systemOut.println("is displayable");
|
||||
// currentConsole.write(b, offset, length, err);
|
||||
// } else {
|
||||
// systemOut.println("not displayable");
|
||||
// if (err) {
|
||||
// systemErr.write(b, offset, length);
|
||||
// } else {
|
||||
// systemOut.write(b, offset, length);
|
||||
// }
|
||||
// }
|
||||
|
||||
OutputStream echo = err ? stderrFile : stdoutFile;
|
||||
if (echo != null) {
|
||||
try {
|
||||
echo.write(b, offset, length);
|
||||
echo.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
echo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
single[0] = (byte)b;
|
||||
currentConsole.write(single, 0, 1, err);
|
||||
|
||||
OutputStream echo = err ? stderrFile : stdoutFile;
|
||||
if (echo != null) {
|
||||
try {
|
||||
echo.write(b);
|
||||
echo.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
echo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
/**
|
||||
* Buffer updates to the console and output them in batches. For info, see:
|
||||
* http://java.sun.com/products/jfc/tsc/articles/text/element_buffer and
|
||||
* http://javatechniques.com/public/java/docs/gui/jtextpane-speed-part2.html
|
||||
* appendString() is called from multiple threads, and insertAll from the
|
||||
* swing event thread, so they need to be synchronized
|
||||
*/
|
||||
class BufferedStyledDocument extends DefaultStyledDocument {
|
||||
ArrayList elements = new ArrayList();
|
||||
int maxLineLength, maxLineCount;
|
||||
int currentLineLength = 0;
|
||||
boolean needLineBreak = false;
|
||||
boolean hasAppendage = false;
|
||||
|
||||
public BufferedStyledDocument(int maxLineLength, int maxLineCount) {
|
||||
this.maxLineLength = maxLineLength;
|
||||
this.maxLineCount = maxLineCount;
|
||||
}
|
||||
|
||||
/** buffer a string for insertion at the end of the DefaultStyledDocument */
|
||||
public synchronized void appendString(String str, AttributeSet a) {
|
||||
// do this so that it's only updated when needed (otherwise console
|
||||
// updates every 250 ms when an app isn't even running.. see bug 180)
|
||||
hasAppendage = true;
|
||||
|
||||
// process each line of the string
|
||||
while (str.length() > 0) {
|
||||
// newlines within an element have (almost) no effect, so we need to
|
||||
// replace them with proper paragraph breaks (start and end tags)
|
||||
if (needLineBreak || currentLineLength > maxLineLength) {
|
||||
elements.add(new ElementSpec(a, ElementSpec.EndTagType));
|
||||
elements.add(new ElementSpec(a, ElementSpec.StartTagType));
|
||||
currentLineLength = 0;
|
||||
}
|
||||
|
||||
if (str.indexOf('\n') == -1) {
|
||||
elements.add(new ElementSpec(a, ElementSpec.ContentType,
|
||||
str.toCharArray(), 0, str.length()));
|
||||
currentLineLength += str.length();
|
||||
needLineBreak = false;
|
||||
str = str.substring(str.length()); // eat the string
|
||||
} else {
|
||||
elements.add(new ElementSpec(a, ElementSpec.ContentType,
|
||||
str.toCharArray(), 0, str.indexOf('\n') + 1));
|
||||
needLineBreak = true;
|
||||
str = str.substring(str.indexOf('\n') + 1); // eat the line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** insert the buffered strings */
|
||||
public synchronized void insertAll() {
|
||||
ElementSpec[] elementArray = new ElementSpec[elements.size()];
|
||||
elements.toArray(elementArray);
|
||||
|
||||
try {
|
||||
// check how many lines have been used so far
|
||||
// if too many, shave off a few lines from the beginning
|
||||
Element element = super.getDefaultRootElement();
|
||||
int lineCount = element.getElementCount();
|
||||
int overage = lineCount - maxLineCount;
|
||||
if (overage > 0) {
|
||||
// if 1200 lines, and 1000 lines is max,
|
||||
// find the position of the end of the 200th line
|
||||
//systemOut.println("overage is " + overage);
|
||||
Element lineElement = element.getElement(overage);
|
||||
if (lineElement == null) return; // do nuthin
|
||||
|
||||
int endOffset = lineElement.getEndOffset();
|
||||
// remove to the end of the 200th line
|
||||
super.remove(0, endOffset);
|
||||
}
|
||||
super.insert(super.getLength(), elementArray);
|
||||
|
||||
} catch (BadLocationException e) {
|
||||
// ignore the error otherwise this will cause an infinite loop
|
||||
// maybe not a good idea in the long run?
|
||||
}
|
||||
elements.clear();
|
||||
hasAppendage = false;
|
||||
}
|
||||
}
|
394
app/src/processing/app/EditorHeader.java
Normal file
394
app/src/processing/app/EditorHeader.java
Normal file
@ -0,0 +1,394 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
/**
|
||||
* Sketch tabs at the top of the editor window.
|
||||
*/
|
||||
public class EditorHeader extends JComponent {
|
||||
static Color backgroundColor;
|
||||
static Color textColor[] = new Color[2];
|
||||
|
||||
Editor editor;
|
||||
|
||||
int tabLeft[];
|
||||
int tabRight[];
|
||||
|
||||
Font font;
|
||||
FontMetrics metrics;
|
||||
int fontAscent;
|
||||
|
||||
JMenu menu;
|
||||
JPopupMenu popup;
|
||||
|
||||
int menuLeft;
|
||||
int menuRight;
|
||||
|
||||
//
|
||||
|
||||
static final String STATUS[] = { "unsel", "sel" };
|
||||
static final int UNSELECTED = 0;
|
||||
static final int SELECTED = 1;
|
||||
|
||||
static final String WHERE[] = { "left", "mid", "right", "menu" };
|
||||
static final int LEFT = 0;
|
||||
static final int MIDDLE = 1;
|
||||
static final int RIGHT = 2;
|
||||
static final int MENU = 3;
|
||||
|
||||
static final int PIECE_WIDTH = 4;
|
||||
|
||||
static Image[][] pieces;
|
||||
|
||||
//
|
||||
|
||||
Image offscreen;
|
||||
int sizeW, sizeH;
|
||||
int imageW, imageH;
|
||||
|
||||
|
||||
public EditorHeader(Editor eddie) {
|
||||
this.editor = eddie; // weird name for listener
|
||||
|
||||
if (pieces == null) {
|
||||
pieces = new Image[STATUS.length][WHERE.length];
|
||||
for (int i = 0; i < STATUS.length; i++) {
|
||||
for (int j = 0; j < WHERE.length; j++) {
|
||||
String path = "tab-" + STATUS[i] + "-" + WHERE[j] + ".gif";
|
||||
pieces[i][j] = Base.getThemeImage(path, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backgroundColor == null) {
|
||||
backgroundColor =
|
||||
Theme.getColor("header.bgcolor");
|
||||
textColor[SELECTED] =
|
||||
Theme.getColor("header.text.selected.color");
|
||||
textColor[UNSELECTED] =
|
||||
Theme.getColor("header.text.unselected.color");
|
||||
}
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int x = e.getX();
|
||||
int y = e.getY();
|
||||
|
||||
if ((x > menuLeft) && (x < menuRight)) {
|
||||
popup.show(EditorHeader.this, x, y);
|
||||
|
||||
} else {
|
||||
Sketch sketch = editor.getSketch();
|
||||
for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
if ((x > tabLeft[i]) && (x < tabRight[i])) {
|
||||
sketch.setCurrentCode(i);
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void paintComponent(Graphics screen) {
|
||||
if (screen == null) return;
|
||||
|
||||
Sketch sketch = editor.getSketch();
|
||||
if (sketch == null) return; // ??
|
||||
|
||||
Dimension size = getSize();
|
||||
if ((size.width != sizeW) || (size.height != sizeH)) {
|
||||
// component has been resized
|
||||
|
||||
if ((size.width > imageW) || (size.height > imageH)) {
|
||||
// nix the image and recreate, it's too small
|
||||
offscreen = null;
|
||||
|
||||
} else {
|
||||
// who cares, just resize
|
||||
sizeW = size.width;
|
||||
sizeH = size.height;
|
||||
}
|
||||
}
|
||||
|
||||
if (offscreen == null) {
|
||||
sizeW = size.width;
|
||||
sizeH = size.height;
|
||||
imageW = sizeW;
|
||||
imageH = sizeH;
|
||||
offscreen = createImage(imageW, imageH);
|
||||
}
|
||||
|
||||
Graphics g = offscreen.getGraphics();
|
||||
if (font == null) {
|
||||
font = Theme.getFont("header.text.font");
|
||||
}
|
||||
g.setFont(font); // need to set this each time through
|
||||
metrics = g.getFontMetrics();
|
||||
fontAscent = metrics.getAscent();
|
||||
//}
|
||||
|
||||
//Graphics2D g2 = (Graphics2D) g;
|
||||
//g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
// RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
// set the background for the offscreen
|
||||
g.setColor(backgroundColor);
|
||||
g.fillRect(0, 0, imageW, imageH);
|
||||
|
||||
int codeCount = sketch.getCodeCount();
|
||||
if ((tabLeft == null) || (tabLeft.length < codeCount)) {
|
||||
tabLeft = new int[codeCount];
|
||||
tabRight = new int[codeCount];
|
||||
}
|
||||
|
||||
int x = 6; // offset from left edge of the component
|
||||
for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
SketchCode code = sketch.getCode(i);
|
||||
|
||||
String codeName = sketch.hideExtension(code.getExtension()) ?
|
||||
code.getPrettyName() : code.getFileName();
|
||||
|
||||
// if modified, add the li'l glyph next to the name
|
||||
String text = " " + codeName + (code.isModified() ? " \u00A7" : " ");
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
int textWidth = (int)
|
||||
font.getStringBounds(text, g2.getFontRenderContext()).getWidth();
|
||||
|
||||
int pieceCount = 2 + (textWidth / PIECE_WIDTH);
|
||||
int pieceWidth = pieceCount * PIECE_WIDTH;
|
||||
|
||||
int state = (code == sketch.getCurrentCode()) ? SELECTED : UNSELECTED;
|
||||
g.drawImage(pieces[state][LEFT], x, 0, null);
|
||||
x += PIECE_WIDTH;
|
||||
|
||||
int contentLeft = x;
|
||||
tabLeft[i] = x;
|
||||
for (int j = 0; j < pieceCount; j++) {
|
||||
g.drawImage(pieces[state][MIDDLE], x, 0, null);
|
||||
x += PIECE_WIDTH;
|
||||
}
|
||||
tabRight[i] = x;
|
||||
int textLeft = contentLeft + (pieceWidth - textWidth) / 2;
|
||||
|
||||
g.setColor(textColor[state]);
|
||||
int baseline = (sizeH + fontAscent) / 2;
|
||||
//g.drawString(sketch.code[i].name, textLeft, baseline);
|
||||
g.drawString(text, textLeft, baseline);
|
||||
|
||||
g.drawImage(pieces[state][RIGHT], x, 0, null);
|
||||
x += PIECE_WIDTH - 1; // overlap by 1 pixel
|
||||
}
|
||||
|
||||
menuLeft = sizeW - (16 + pieces[0][MENU].getWidth(this));
|
||||
menuRight = sizeW - 16;
|
||||
// draw the dropdown menu target
|
||||
g.drawImage(pieces[popup.isVisible() ? SELECTED : UNSELECTED][MENU],
|
||||
menuLeft, 0, null);
|
||||
|
||||
screen.drawImage(offscreen, 0, 0, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when a new sketch is opened.
|
||||
*/
|
||||
public void rebuild() {
|
||||
//System.out.println("rebuilding editor header");
|
||||
rebuildMenu();
|
||||
repaint();
|
||||
Toolkit.getDefaultToolkit().sync();
|
||||
}
|
||||
|
||||
|
||||
public void rebuildMenu() {
|
||||
//System.out.println("rebuilding");
|
||||
if (menu != null) {
|
||||
menu.removeAll();
|
||||
|
||||
} else {
|
||||
menu = new JMenu();
|
||||
popup = menu.getPopupMenu();
|
||||
add(popup);
|
||||
popup.setLightWeightPopupEnabled(true);
|
||||
|
||||
/*
|
||||
popup.addPopupMenuListener(new PopupMenuListener() {
|
||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||
// on redraw, the isVisible() will get checked.
|
||||
// actually, a repaint may be fired anyway, so this
|
||||
// may be redundant.
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
|
||||
});
|
||||
*/
|
||||
}
|
||||
JMenuItem item;
|
||||
|
||||
// maybe this shouldn't have a command key anyways..
|
||||
// since we're not trying to make this a full ide..
|
||||
//item = Editor.newJMenuItem("New", 'T');
|
||||
|
||||
/*
|
||||
item = Editor.newJMenuItem("Previous", KeyEvent.VK_PAGE_UP);
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
System.out.println("prev");
|
||||
}
|
||||
});
|
||||
if (editor.sketch != null) {
|
||||
item.setEnabled(editor.sketch.codeCount > 1);
|
||||
}
|
||||
menu.add(item);
|
||||
|
||||
item = Editor.newJMenuItem("Next", KeyEvent.VK_PAGE_DOWN);
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
System.out.println("ext");
|
||||
}
|
||||
});
|
||||
if (editor.sketch != null) {
|
||||
item.setEnabled(editor.sketch.codeCount > 1);
|
||||
}
|
||||
menu.add(item);
|
||||
|
||||
menu.addSeparator();
|
||||
*/
|
||||
|
||||
//item = new JMenuItem("New Tab");
|
||||
item = Editor.newJMenuItemShift("New Tab", 'N');
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.getSketch().handleNewCode();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
item = new JMenuItem("Rename");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.getSketch().handleRenameCode();
|
||||
/*
|
||||
// this is already being called by nameCode(), the second stage of rename
|
||||
if (editor.sketch.current == editor.sketch.code[0]) {
|
||||
editor.sketchbook.rebuildMenus();
|
||||
}
|
||||
*/
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
item = new JMenuItem("Delete");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.getSketch().handleDeleteCode();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
// KeyEvent.VK_LEFT and VK_RIGHT will make Windows beep
|
||||
|
||||
item = new JMenuItem("Previous Tab");
|
||||
KeyStroke ctrlAltLeft =
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Editor.SHORTCUT_ALT_KEY_MASK);
|
||||
item.setAccelerator(ctrlAltLeft);
|
||||
// this didn't want to work consistently
|
||||
/*
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.sketch.prevCode();
|
||||
}
|
||||
});
|
||||
*/
|
||||
menu.add(item);
|
||||
|
||||
item = new JMenuItem("Next Tab");
|
||||
KeyStroke ctrlAltRight =
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Editor.SHORTCUT_ALT_KEY_MASK);
|
||||
item.setAccelerator(ctrlAltRight);
|
||||
/*
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.sketch.nextCode();
|
||||
}
|
||||
});
|
||||
*/
|
||||
menu.add(item);
|
||||
|
||||
Sketch sketch = editor.getSketch();
|
||||
if (sketch != null) {
|
||||
menu.addSeparator();
|
||||
|
||||
ActionListener jumpListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.getSketch().setCurrentCode(e.getActionCommand());
|
||||
}
|
||||
};
|
||||
for (SketchCode code : sketch.getCode()) {
|
||||
item = new JMenuItem(code.getPrettyName());
|
||||
item.addActionListener(jumpListener);
|
||||
menu.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void deselectMenu() {
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return getMinimumSize();
|
||||
}
|
||||
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
if (Base.isMacOS()) {
|
||||
return new Dimension(300, Preferences.GRID_SIZE);
|
||||
}
|
||||
return new Dimension(300, Preferences.GRID_SIZE - 1);
|
||||
}
|
||||
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
if (Base.isMacOS()) {
|
||||
return new Dimension(3000, Preferences.GRID_SIZE);
|
||||
}
|
||||
return new Dimension(3000, Preferences.GRID_SIZE - 1);
|
||||
}
|
||||
}
|
116
app/src/processing/app/EditorLineStatus.java
Normal file
116
app/src/processing/app/EditorLineStatus.java
Normal file
@ -0,0 +1,116 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2005-07 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import processing.app.syntax.*;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
/**
|
||||
* Li'l status bar fella that shows the line number.
|
||||
*/
|
||||
public class EditorLineStatus extends JComponent {
|
||||
JEditTextArea textarea;
|
||||
int start = -1, stop;
|
||||
|
||||
Image resize;
|
||||
|
||||
Color foreground;
|
||||
Color background;
|
||||
Font font;
|
||||
int high;
|
||||
|
||||
String text = "";
|
||||
|
||||
|
||||
public EditorLineStatus(JEditTextArea textarea) {
|
||||
this.textarea = textarea;
|
||||
textarea.editorLineStatus = this;
|
||||
|
||||
background = Theme.getColor("linestatus.bgcolor");
|
||||
font = Theme.getFont("linestatus.font");
|
||||
foreground = Theme.getColor("linestatus.color");
|
||||
high = Theme.getInteger("linestatus.height");
|
||||
|
||||
if (Base.isMacOS()) {
|
||||
resize = Base.getThemeImage("resize.gif", this);
|
||||
}
|
||||
//linestatus.bgcolor = #000000
|
||||
//linestatus.font = SansSerif,plain,10
|
||||
//linestatus.color = #FFFFFF
|
||||
}
|
||||
|
||||
|
||||
public void set(int newStart, int newStop) {
|
||||
if ((newStart == start) && (newStop == stop)) return;
|
||||
|
||||
start = newStart;
|
||||
stop = newStop;
|
||||
|
||||
/*
|
||||
if (start == stop) {
|
||||
text = "Line " + (start + 1);
|
||||
} else {
|
||||
text = "Lines " + (start + 1) + " to " + (stop + 1);
|
||||
}
|
||||
*/
|
||||
if (start == stop) {
|
||||
text = String.valueOf(start+1);
|
||||
} else {
|
||||
text = (start+1) + " - " + (stop+1);
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
public void paintComponent(Graphics g) {
|
||||
g.setColor(background);
|
||||
Dimension size = getSize();
|
||||
g.fillRect(0, 0, size.width, size.height);
|
||||
|
||||
g.setFont(font);
|
||||
g.setColor(foreground);
|
||||
int baseline = (high + g.getFontMetrics().getAscent()) / 2;
|
||||
g.drawString(text, 6, baseline);
|
||||
|
||||
if (Base.isMacOS()) {
|
||||
g.drawImage(resize, size.width - 20, 0, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(300, high);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(3000, high);
|
||||
}
|
||||
}
|
612
app/src/processing/app/EditorListener.java
Normal file
612
app/src/processing/app/EditorListener.java
Normal file
@ -0,0 +1,612 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import processing.app.syntax.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
|
||||
/**
|
||||
* Filters key events for tab expansion/indent/etc.
|
||||
* <p/>
|
||||
* For version 0099, some changes have been made to make the indents
|
||||
* smarter. There are still issues though:
|
||||
* + indent happens when it picks up a curly brace on the previous line,
|
||||
* but not if there's a blank line between them.
|
||||
* + It also doesn't handle single indent situations where a brace
|
||||
* isn't used (i.e. an if statement or for loop that's a single line).
|
||||
* It shouldn't actually be using braces.
|
||||
* Solving these issues, however, would probably best be done by a
|
||||
* smarter parser/formatter, rather than continuing to hack this class.
|
||||
*/
|
||||
public class EditorListener {
|
||||
private Editor editor;
|
||||
private JEditTextArea textarea;
|
||||
|
||||
private boolean externalEditor;
|
||||
private boolean tabsExpand;
|
||||
private boolean tabsIndent;
|
||||
private int tabSize;
|
||||
private String tabString;
|
||||
private boolean autoIndent;
|
||||
|
||||
// private int selectionStart, selectionEnd;
|
||||
// private int position;
|
||||
|
||||
/** ctrl-alt on windows and linux, cmd-alt on mac os x */
|
||||
static final int CTRL_ALT = ActionEvent.ALT_MASK |
|
||||
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||
|
||||
|
||||
public EditorListener(Editor editor, JEditTextArea textarea) {
|
||||
this.editor = editor;
|
||||
this.textarea = textarea;
|
||||
|
||||
// let him know that i'm leechin'
|
||||
textarea.editorListener = this;
|
||||
|
||||
applyPreferences();
|
||||
}
|
||||
|
||||
|
||||
public void applyPreferences() {
|
||||
tabsExpand = Preferences.getBoolean("editor.tabs.expand");
|
||||
//tabsIndent = Preferences.getBoolean("editor.tabs.indent");
|
||||
tabSize = Preferences.getInteger("editor.tabs.size");
|
||||
tabString = Editor.EMPTY.substring(0, tabSize);
|
||||
autoIndent = Preferences.getBoolean("editor.indent");
|
||||
externalEditor = Preferences.getBoolean("editor.external");
|
||||
}
|
||||
|
||||
|
||||
//public void setExternalEditor(boolean externalEditor) {
|
||||
//this.externalEditor = externalEditor;
|
||||
//}
|
||||
|
||||
|
||||
/**
|
||||
* Intercepts key pressed events for JEditTextArea.
|
||||
* <p/>
|
||||
* Called by JEditTextArea inside processKeyEvent(). Note that this
|
||||
* won't intercept actual characters, because those are fired on
|
||||
* keyTyped().
|
||||
* @return true if the event has been handled (to remove it from the queue)
|
||||
*/
|
||||
public boolean keyPressed(KeyEvent event) {
|
||||
// don't do things if the textarea isn't editable
|
||||
if (externalEditor) return false;
|
||||
|
||||
//deselect(); // this is for paren balancing
|
||||
char c = event.getKeyChar();
|
||||
int code = event.getKeyCode();
|
||||
|
||||
//System.out.println((int)c + " " + code + " " + event);
|
||||
//System.out.println();
|
||||
|
||||
Sketch sketch = editor.getSketch();
|
||||
|
||||
if ((event.getModifiers() & CTRL_ALT) == CTRL_ALT) {
|
||||
if (code == KeyEvent.VK_LEFT) {
|
||||
sketch.handlePrevCode();
|
||||
return true;
|
||||
} else if (code == KeyEvent.VK_RIGHT) {
|
||||
sketch.handleNextCode();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((event.getModifiers() & KeyEvent.META_MASK) != 0) {
|
||||
//event.consume(); // does nothing
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO i don't like these accessors. clean em up later.
|
||||
if (!editor.getSketch().isModified()) {
|
||||
if ((code == KeyEvent.VK_BACK_SPACE) || (code == KeyEvent.VK_TAB) ||
|
||||
(code == KeyEvent.VK_ENTER) || ((c >= 32) && (c < 128))) {
|
||||
sketch.setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
if ((code == KeyEvent.VK_UP) &&
|
||||
((event.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
||||
// back up to the last empty line
|
||||
char contents[] = textarea.getText().toCharArray();
|
||||
//int origIndex = textarea.getCaretPosition() - 1;
|
||||
int caretIndex = textarea.getCaretPosition();
|
||||
|
||||
int index = calcLineStart(caretIndex - 1, contents);
|
||||
//System.out.println("line start " + (int) contents[index]);
|
||||
index -= 2; // step over the newline
|
||||
//System.out.println((int) contents[index]);
|
||||
boolean onlySpaces = true;
|
||||
while (index > 0) {
|
||||
if (contents[index] == 10) {
|
||||
if (onlySpaces) {
|
||||
index++;
|
||||
break;
|
||||
} else {
|
||||
onlySpaces = true; // reset
|
||||
}
|
||||
} else if (contents[index] != ' ') {
|
||||
onlySpaces = false;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
// if the first char, index will be -2
|
||||
if (index < 0) index = 0;
|
||||
|
||||
if ((event.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
|
||||
textarea.setSelectionStart(caretIndex);
|
||||
textarea.setSelectionEnd(index);
|
||||
} else {
|
||||
textarea.setCaretPosition(index);
|
||||
}
|
||||
event.consume();
|
||||
return true;
|
||||
|
||||
} else if ((code == KeyEvent.VK_DOWN) &&
|
||||
((event.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
||||
char contents[] = textarea.getText().toCharArray();
|
||||
int caretIndex = textarea.getCaretPosition();
|
||||
|
||||
int index = caretIndex;
|
||||
int lineStart = 0;
|
||||
boolean onlySpaces = false; // don't count this line
|
||||
while (index < contents.length) {
|
||||
if (contents[index] == 10) {
|
||||
if (onlySpaces) {
|
||||
index = lineStart; // this is it
|
||||
break;
|
||||
} else {
|
||||
lineStart = index + 1;
|
||||
onlySpaces = true; // reset
|
||||
}
|
||||
} else if (contents[index] != ' ') {
|
||||
onlySpaces = false;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
// if the first char, index will be -2
|
||||
//if (index < 0) index = 0;
|
||||
|
||||
//textarea.setSelectionStart(index);
|
||||
//textarea.setSelectionEnd(index);
|
||||
if ((event.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
|
||||
textarea.setSelectionStart(caretIndex);
|
||||
textarea.setSelectionEnd(index);
|
||||
} else {
|
||||
textarea.setCaretPosition(index);
|
||||
}
|
||||
event.consume();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
switch ((int) c) {
|
||||
|
||||
case 9: // TAB
|
||||
if (textarea.isSelectionActive()) {
|
||||
boolean outdent = (event.getModifiers() & KeyEvent.SHIFT_MASK) != 0;
|
||||
editor.handleIndentOutdent(!outdent);
|
||||
|
||||
} else if (tabsExpand) { // expand tabs
|
||||
textarea.setSelectedText(tabString);
|
||||
event.consume();
|
||||
return true;
|
||||
|
||||
} else if (tabsIndent) {
|
||||
// this code is incomplete
|
||||
|
||||
// if this brace is the only thing on the line, outdent
|
||||
//char contents[] = getCleanedContents();
|
||||
char contents[] = textarea.getText().toCharArray();
|
||||
// index to the character to the left of the caret
|
||||
int prevCharIndex = textarea.getCaretPosition() - 1;
|
||||
|
||||
// now find the start of this line
|
||||
int lineStart = calcLineStart(prevCharIndex, contents);
|
||||
|
||||
int lineEnd = lineStart;
|
||||
while ((lineEnd < contents.length - 1) &&
|
||||
(contents[lineEnd] != 10)) {
|
||||
lineEnd++;
|
||||
}
|
||||
|
||||
// get the number of braces, to determine whether this is an indent
|
||||
int braceBalance = 0;
|
||||
int index = lineStart;
|
||||
while ((index < contents.length) &&
|
||||
(contents[index] != 10)) {
|
||||
if (contents[index] == '{') {
|
||||
braceBalance++;
|
||||
} else if (contents[index] == '}') {
|
||||
braceBalance--;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// if it's a starting indent, need to ignore it, so lineStart
|
||||
// will be the counting point. but if there's a closing indent,
|
||||
// then the lineEnd should be used.
|
||||
int where = (braceBalance > 0) ? lineStart : lineEnd;
|
||||
int indent = calcBraceIndent(where, contents);
|
||||
if (indent == -1) {
|
||||
// no braces to speak of, do nothing
|
||||
indent = 0;
|
||||
} else {
|
||||
indent += tabSize;
|
||||
}
|
||||
|
||||
// and the number of spaces it has
|
||||
int spaceCount = calcSpaceCount(prevCharIndex, contents);
|
||||
|
||||
textarea.setSelectionStart(lineStart);
|
||||
textarea.setSelectionEnd(lineStart + spaceCount);
|
||||
textarea.setSelectedText(Editor.EMPTY.substring(0, indent));
|
||||
|
||||
event.consume();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 10: // auto-indent
|
||||
case 13:
|
||||
if (autoIndent) {
|
||||
char contents[] = textarea.getText().toCharArray();
|
||||
|
||||
// this is the previous character
|
||||
// (i.e. when you hit return, it'll be the last character
|
||||
// just before where the newline will be inserted)
|
||||
int origIndex = textarea.getCaretPosition() - 1;
|
||||
|
||||
// NOTE all this cursing about CRLF stuff is probably moot
|
||||
// NOTE since the switch to JEditTextArea, which seems to use
|
||||
// NOTE only LFs internally (thank god). disabling for 0099.
|
||||
// walk through the array to the current caret position,
|
||||
// and count how many weirdo windows line endings there are,
|
||||
// which would be throwing off the caret position number
|
||||
/*
|
||||
int offset = 0;
|
||||
int realIndex = origIndex;
|
||||
for (int i = 0; i < realIndex-1; i++) {
|
||||
if ((contents[i] == 13) && (contents[i+1] == 10)) {
|
||||
offset++;
|
||||
realIndex++;
|
||||
}
|
||||
}
|
||||
// back up until \r \r\n or \n.. @#($* cross platform
|
||||
//System.out.println(origIndex + " offset = " + offset);
|
||||
origIndex += offset; // ARGH!#(* WINDOWS#@($*
|
||||
*/
|
||||
|
||||
// if the previous thing is a brace (whether prev line or
|
||||
// up farther) then the correct indent is the number of spaces
|
||||
// on that line + 'indent'.
|
||||
// if the previous line is not a brace, then just use the
|
||||
// identical indentation to the previous line
|
||||
|
||||
// calculate the amount of indent on the previous line
|
||||
// this will be used *only if the prev line is not an indent*
|
||||
int spaceCount = calcSpaceCount(origIndex, contents);
|
||||
|
||||
// If the last character was a left curly brace, then indent.
|
||||
// For 0122, walk backwards a bit to make sure that the there
|
||||
// isn't a curly brace several spaces (or lines) back. Also
|
||||
// moved this before calculating extraCount, since it'll affect
|
||||
// that as well.
|
||||
int index2 = origIndex;
|
||||
while ((index2 >= 0) &&
|
||||
Character.isWhitespace(contents[index2])) {
|
||||
index2--;
|
||||
}
|
||||
if (index2 != -1) {
|
||||
// still won't catch a case where prev stuff is a comment
|
||||
if (contents[index2] == '{') {
|
||||
// intermediate lines be damned,
|
||||
// use the indent for this line instead
|
||||
spaceCount = calcSpaceCount(index2, contents);
|
||||
spaceCount += tabSize;
|
||||
}
|
||||
}
|
||||
//System.out.println("spaceCount should be " + spaceCount);
|
||||
|
||||
// now before inserting this many spaces, walk forward from
|
||||
// the caret position and count the number of spaces,
|
||||
// so that the number of spaces aren't duplicated again
|
||||
int index = origIndex + 1;
|
||||
int extraCount = 0;
|
||||
while ((index < contents.length) &&
|
||||
(contents[index] == ' ')) {
|
||||
//spaceCount--;
|
||||
extraCount++;
|
||||
index++;
|
||||
}
|
||||
int braceCount = 0;
|
||||
while ((index < contents.length) && (contents[index] != '\n')) {
|
||||
if (contents[index] == '}') {
|
||||
braceCount++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// hitting return on a line with spaces *after* the caret
|
||||
// can cause trouble. for 0099, was ignoring the case, but this is
|
||||
// annoying, so in 0122 we're trying to fix that.
|
||||
/*
|
||||
if (spaceCount - extraCount > 0) {
|
||||
spaceCount -= extraCount;
|
||||
}
|
||||
*/
|
||||
spaceCount -= extraCount;
|
||||
//if (spaceCount < 0) spaceCount = 0;
|
||||
//System.out.println("extraCount is " + extraCount);
|
||||
|
||||
// now, check to see if the current line contains a } and if so,
|
||||
// outdent again by indent
|
||||
//if (braceCount > 0) {
|
||||
//spaceCount -= 2;
|
||||
//}
|
||||
|
||||
if (spaceCount < 0) {
|
||||
// for rev 0122, actually delete extra space
|
||||
//textarea.setSelectionStart(origIndex + 1);
|
||||
textarea.setSelectionEnd(textarea.getSelectionStop() - spaceCount);
|
||||
textarea.setSelectedText("\n");
|
||||
} else {
|
||||
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
|
||||
textarea.setSelectedText(insertion);
|
||||
}
|
||||
|
||||
// not gonna bother handling more than one brace
|
||||
if (braceCount > 0) {
|
||||
int sel = textarea.getSelectionStart();
|
||||
// sel - tabSize will be -1 if start/end parens on the same line
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=484
|
||||
if (sel - tabSize >= 0) {
|
||||
textarea.select(sel - tabSize, sel);
|
||||
String s = Editor.EMPTY.substring(0, tabSize);
|
||||
// if these are spaces that we can delete
|
||||
if (textarea.getSelectedText().equals(s)) {
|
||||
textarea.setSelectedText("");
|
||||
} else {
|
||||
textarea.select(sel, sel);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Enter/Return was being consumed by somehow even if false
|
||||
// was returned, so this is a band-aid to simply fire the event again.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=1073
|
||||
textarea.setSelectedText(String.valueOf(c));
|
||||
}
|
||||
// mark this event as already handled (all but ignored)
|
||||
event.consume();
|
||||
return true;
|
||||
|
||||
case '}':
|
||||
if (autoIndent) {
|
||||
// first remove anything that was there (in case this multiple
|
||||
// characters are selected, so that it's not in the way of the
|
||||
// spaces for the auto-indent
|
||||
if (textarea.getSelectionStart() != textarea.getSelectionStop()) {
|
||||
textarea.setSelectedText("");
|
||||
}
|
||||
|
||||
// if this brace is the only thing on the line, outdent
|
||||
char contents[] = textarea.getText().toCharArray();
|
||||
// index to the character to the left of the caret
|
||||
int prevCharIndex = textarea.getCaretPosition() - 1;
|
||||
|
||||
// backup from the current caret position to the last newline,
|
||||
// checking for anything besides whitespace along the way.
|
||||
// if there's something besides whitespace, exit without
|
||||
// messing any sort of indenting.
|
||||
int index = prevCharIndex;
|
||||
boolean finished = false;
|
||||
while ((index != -1) && (!finished)) {
|
||||
if (contents[index] == 10) {
|
||||
finished = true;
|
||||
index++;
|
||||
} else if (contents[index] != ' ') {
|
||||
// don't do anything, this line has other stuff on it
|
||||
return false;
|
||||
} else {
|
||||
index--;
|
||||
}
|
||||
}
|
||||
if (!finished) return false; // brace with no start
|
||||
int lineStartIndex = index;
|
||||
|
||||
int pairedSpaceCount = calcBraceIndent(prevCharIndex, contents); //, 1);
|
||||
if (pairedSpaceCount == -1) return false;
|
||||
|
||||
textarea.setSelectionStart(lineStartIndex);
|
||||
textarea.setSelectedText(Editor.EMPTY.substring(0, pairedSpaceCount));
|
||||
|
||||
// mark this event as already handled
|
||||
event.consume();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean keyTyped(KeyEvent event) {
|
||||
char c = event.getKeyChar();
|
||||
|
||||
if ((event.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
|
||||
// on linux, ctrl-comma (prefs) being passed through to the editor
|
||||
if (c == KeyEvent.VK_COMMA) {
|
||||
event.consume();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the index for the first character on this line.
|
||||
*/
|
||||
protected int calcLineStart(int index, char contents[]) {
|
||||
// backup from the current caret position to the last newline,
|
||||
// so that we can figure out how far this line was indented
|
||||
/*int spaceCount = 0;*/
|
||||
boolean finished = false;
|
||||
while ((index != -1) && (!finished)) {
|
||||
if ((contents[index] == 10) ||
|
||||
(contents[index] == 13)) {
|
||||
finished = true;
|
||||
//index++; // maybe ?
|
||||
} else {
|
||||
index--; // new
|
||||
}
|
||||
}
|
||||
// add one because index is either -1 (the start of the document)
|
||||
// or it's the newline character for the previous line
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the number of spaces on this line.
|
||||
*/
|
||||
protected int calcSpaceCount(int index, char contents[]) {
|
||||
index = calcLineStart(index, contents);
|
||||
|
||||
int spaceCount = 0;
|
||||
// now walk forward and figure out how many spaces there are
|
||||
while ((index < contents.length) && (index >= 0) &&
|
||||
(contents[index++] == ' ')) {
|
||||
spaceCount++;
|
||||
}
|
||||
return spaceCount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Walk back from 'index' until the brace that seems to be
|
||||
* the beginning of the current block, and return the number of
|
||||
* spaces found on that line.
|
||||
*/
|
||||
protected int calcBraceIndent(int index, char contents[]) {
|
||||
// now that we know things are ok to be indented, walk
|
||||
// backwards to the last { to see how far its line is indented.
|
||||
// this isn't perfect cuz it'll pick up commented areas,
|
||||
// but that's not really a big deal and can be fixed when
|
||||
// this is all given a more complete (proper) solution.
|
||||
int braceDepth = 1;
|
||||
boolean finished = false;
|
||||
while ((index != -1) && (!finished)) {
|
||||
if (contents[index] == '}') {
|
||||
// aww crap, this means we're one deeper
|
||||
// and will have to find one more extra {
|
||||
braceDepth++;
|
||||
//if (braceDepth == 0) {
|
||||
//finished = true;
|
||||
//}
|
||||
index--;
|
||||
} else if (contents[index] == '{') {
|
||||
braceDepth--;
|
||||
if (braceDepth == 0) {
|
||||
finished = true;
|
||||
}
|
||||
index--;
|
||||
} else {
|
||||
index--;
|
||||
}
|
||||
}
|
||||
// never found a proper brace, be safe and don't do anything
|
||||
if (!finished) return -1;
|
||||
|
||||
// check how many spaces on the line with the matching open brace
|
||||
//int pairedSpaceCount = calcSpaceCount(index, contents);
|
||||
//System.out.println(pairedSpaceCount);
|
||||
return calcSpaceCount(index, contents);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the character array and blank out the commented areas.
|
||||
* This hasn't yet been tested, the plan was to make auto-indent
|
||||
* less gullible (it gets fooled by braces that are commented out).
|
||||
*/
|
||||
protected char[] getCleanedContents() {
|
||||
char c[] = textarea.getText().toCharArray();
|
||||
|
||||
int index = 0;
|
||||
while (index < c.length - 1) {
|
||||
if ((c[index] == '/') && (c[index+1] == '*')) {
|
||||
c[index++] = 0;
|
||||
c[index++] = 0;
|
||||
while ((index < c.length - 1) &&
|
||||
!((c[index] == '*') && (c[index+1] == '/'))) {
|
||||
c[index++] = 0;
|
||||
}
|
||||
|
||||
} else if ((c[index] == '/') && (c[index+1] == '/')) {
|
||||
// clear out until the end of the line
|
||||
while ((index < c.length) && (c[index] != 10)) {
|
||||
c[index++] = 0;
|
||||
}
|
||||
if (index != c.length) {
|
||||
index++; // skip over the newline
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
protected char[] getCleanedContents() {
|
||||
char c[] = textarea.getText().toCharArray();
|
||||
boolean insideMulti; // multi-line comment
|
||||
boolean insideSingle; // single line double slash
|
||||
|
||||
//for (int i = 0; i < c.length - 1; i++) {
|
||||
int index = 0;
|
||||
while (index < c.length - 1) {
|
||||
if (insideMulti && (c[index] == '*') && (c[index+1] == '/')) {
|
||||
insideMulti = false;
|
||||
index += 2;
|
||||
} else if ((c[index] == '/') && (c[index+1] == '*')) {
|
||||
insideMulti = true;
|
||||
index += 2;
|
||||
} else if ((c[index] == '/') && (c[index+1] == '/')) {
|
||||
// clear out until the end of the line
|
||||
while (c[index] != 10) {
|
||||
c[index++] = 0;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
431
app/src/processing/app/EditorStatus.java
Normal file
431
app/src/processing/app/EditorStatus.java
Normal file
@ -0,0 +1,431 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
/**
|
||||
* Panel just below the editing area that contains status messages.
|
||||
*/
|
||||
public class EditorStatus extends JPanel /*implements ActionListener*/ {
|
||||
static Color bgcolor[];
|
||||
static Color fgcolor[];
|
||||
|
||||
static final int NOTICE = 0;
|
||||
static final int ERR = 1;
|
||||
//static final int PROMPT = 2;
|
||||
//static final int EDIT = 3;
|
||||
static final int EDIT = 2;
|
||||
|
||||
static final int YES = 1;
|
||||
static final int NO = 2;
|
||||
static final int CANCEL = 3;
|
||||
static final int OK = 4;
|
||||
|
||||
static final String NO_MESSAGE = "";
|
||||
|
||||
Editor editor;
|
||||
|
||||
int mode;
|
||||
String message;
|
||||
|
||||
Font font;
|
||||
FontMetrics metrics;
|
||||
int ascent;
|
||||
|
||||
Image offscreen;
|
||||
int sizeW, sizeH;
|
||||
int imageW, imageH;
|
||||
|
||||
//JButton yesButton;
|
||||
//JButton noButton;
|
||||
JButton cancelButton;
|
||||
JButton okButton;
|
||||
JTextField editField;
|
||||
|
||||
//Thread promptThread;
|
||||
int response;
|
||||
|
||||
|
||||
public EditorStatus(Editor editor) {
|
||||
this.editor = editor;
|
||||
empty();
|
||||
|
||||
if (bgcolor == null) {
|
||||
bgcolor = new Color[3]; //4];
|
||||
bgcolor[0] = Theme.getColor("status.notice.bgcolor");
|
||||
bgcolor[1] = Theme.getColor("status.error.bgcolor");
|
||||
bgcolor[2] = Theme.getColor("status.edit.bgcolor");
|
||||
|
||||
fgcolor = new Color[3]; //4];
|
||||
fgcolor[0] = Theme.getColor("status.notice.fgcolor");
|
||||
fgcolor[1] = Theme.getColor("status.error.fgcolor");
|
||||
fgcolor[2] = Theme.getColor("status.edit.fgcolor");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void empty() {
|
||||
mode = NOTICE;
|
||||
message = NO_MESSAGE;
|
||||
//update();
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
public void notice(String message) {
|
||||
mode = NOTICE;
|
||||
this.message = message;
|
||||
//update();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void unnotice(String unmessage) {
|
||||
if (message.equals(unmessage)) empty();
|
||||
}
|
||||
|
||||
|
||||
public void error(String message) {
|
||||
mode = ERR;
|
||||
this.message = message;
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public void prompt(String message) {
|
||||
mode = PROMPT;
|
||||
this.message = message;
|
||||
|
||||
response = 0;
|
||||
yesButton.setVisible(true);
|
||||
noButton.setVisible(true);
|
||||
cancelButton.setVisible(true);
|
||||
yesButton.requestFocus();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
// prompt has been handled, re-hide the buttons
|
||||
public void unprompt() {
|
||||
yesButton.setVisible(false);
|
||||
noButton.setVisible(false);
|
||||
cancelButton.setVisible(false);
|
||||
empty();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void edit(String message, String dflt) {
|
||||
mode = EDIT;
|
||||
this.message = message;
|
||||
|
||||
response = 0;
|
||||
okButton.setVisible(true);
|
||||
cancelButton.setVisible(true);
|
||||
editField.setVisible(true);
|
||||
editField.setText(dflt);
|
||||
editField.selectAll();
|
||||
editField.requestFocus();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void unedit() {
|
||||
okButton.setVisible(false);
|
||||
cancelButton.setVisible(false);
|
||||
editField.setVisible(false);
|
||||
empty();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public void update() {
|
||||
Graphics g = this.getGraphics();
|
||||
try {
|
||||
setBackground(bgcolor[mode]);
|
||||
} catch (NullPointerException e) { } // if not ready yet
|
||||
if (g != null) paint(g);
|
||||
}
|
||||
|
||||
public void update(Graphics g) {
|
||||
paint(g);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void paintComponent(Graphics screen) {
|
||||
//if (screen == null) return;
|
||||
if (okButton == null) setup();
|
||||
|
||||
//System.out.println("status.paintComponent");
|
||||
|
||||
Dimension size = getSize();
|
||||
if ((size.width != sizeW) || (size.height != sizeH)) {
|
||||
// component has been resized
|
||||
|
||||
if ((size.width > imageW) || (size.height > imageH)) {
|
||||
// nix the image and recreate, it's too small
|
||||
offscreen = null;
|
||||
|
||||
} else {
|
||||
// who cares, just resize
|
||||
sizeW = size.width;
|
||||
sizeH = size.height;
|
||||
setButtonBounds();
|
||||
}
|
||||
}
|
||||
|
||||
if (offscreen == null) {
|
||||
sizeW = size.width;
|
||||
sizeH = size.height;
|
||||
setButtonBounds();
|
||||
imageW = sizeW;
|
||||
imageH = sizeH;
|
||||
offscreen = createImage(imageW, imageH);
|
||||
}
|
||||
|
||||
Graphics g = offscreen.getGraphics();
|
||||
if (font == null) {
|
||||
font = Theme.getFont("status.font");
|
||||
//new Font("SansSerif", Font.PLAIN, 12));
|
||||
g.setFont(font);
|
||||
metrics = g.getFontMetrics();
|
||||
ascent = metrics.getAscent();
|
||||
}
|
||||
|
||||
//setBackground(bgcolor[mode]); // does nothing
|
||||
|
||||
g.setColor(bgcolor[mode]);
|
||||
g.fillRect(0, 0, imageW, imageH);
|
||||
|
||||
g.setColor(fgcolor[mode]);
|
||||
g.setFont(font); // needs to be set each time on osx
|
||||
g.drawString(message, Preferences.GUI_SMALL, (sizeH + ascent) / 2);
|
||||
|
||||
screen.drawImage(offscreen, 0, 0, null);
|
||||
}
|
||||
|
||||
|
||||
protected void setup() {
|
||||
if (okButton == null) {
|
||||
cancelButton = new JButton(Preferences.PROMPT_CANCEL);
|
||||
okButton = new JButton(Preferences.PROMPT_OK);
|
||||
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (mode == EDIT) {
|
||||
unedit();
|
||||
//editor.toolbar.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// answering to rename/new code question
|
||||
if (mode == EDIT) { // this if() isn't (shouldn't be?) necessary
|
||||
String answer = editField.getText();
|
||||
editor.getSketch().nameCode(answer);
|
||||
unedit();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// !@#(* aqua ui #($*(( that turtle-neck wearing #(** (#$@)(
|
||||
// os9 seems to work if bg of component is set, but x still a bastard
|
||||
if (Base.isMacOS()) {
|
||||
//yesButton.setBackground(bgcolor[EDIT]);
|
||||
//noButton.setBackground(bgcolor[EDIT]);
|
||||
cancelButton.setBackground(bgcolor[EDIT]);
|
||||
okButton.setBackground(bgcolor[EDIT]);
|
||||
}
|
||||
setLayout(null);
|
||||
|
||||
/*
|
||||
yesButton.addActionListener(this);
|
||||
noButton.addActionListener(this);
|
||||
cancelButton.addActionListener(this);
|
||||
okButton.addActionListener(this);
|
||||
*/
|
||||
|
||||
//add(yesButton);
|
||||
//add(noButton);
|
||||
add(cancelButton);
|
||||
add(okButton);
|
||||
|
||||
//yesButton.setVisible(false);
|
||||
//noButton.setVisible(false);
|
||||
cancelButton.setVisible(false);
|
||||
okButton.setVisible(false);
|
||||
|
||||
editField = new JTextField();
|
||||
// disabling, was not in use
|
||||
//editField.addActionListener(this);
|
||||
|
||||
//if (Base.platform != Base.MACOSX) {
|
||||
editField.addKeyListener(new KeyAdapter() {
|
||||
|
||||
// Grab ESC with keyPressed, because it's not making it to keyTyped
|
||||
public void keyPressed(KeyEvent event) {
|
||||
if (event.getKeyChar() == KeyEvent.VK_ESCAPE) {
|
||||
unedit();
|
||||
//editor.toolbar.clear();
|
||||
event.consume();
|
||||
}
|
||||
}
|
||||
|
||||
// use keyTyped to catch when the feller is actually
|
||||
// added to the text field. with keyTyped, as opposed to
|
||||
// keyPressed, the keyCode will be zero, even if it's
|
||||
// enter or backspace or whatever, so the keychar should
|
||||
// be used instead. grr.
|
||||
public void keyTyped(KeyEvent event) {
|
||||
//System.out.println("got event " + event);
|
||||
int c = event.getKeyChar();
|
||||
|
||||
if (c == KeyEvent.VK_ENTER) { // accept the input
|
||||
String answer = editField.getText();
|
||||
editor.getSketch().nameCode(answer);
|
||||
unedit();
|
||||
event.consume();
|
||||
|
||||
// easier to test the affirmative case than the negative
|
||||
} else if ((c == KeyEvent.VK_BACK_SPACE) ||
|
||||
(c == KeyEvent.VK_DELETE) ||
|
||||
(c == KeyEvent.VK_RIGHT) ||
|
||||
(c == KeyEvent.VK_LEFT) ||
|
||||
(c == KeyEvent.VK_UP) ||
|
||||
(c == KeyEvent.VK_DOWN) ||
|
||||
(c == KeyEvent.VK_HOME) ||
|
||||
(c == KeyEvent.VK_END) ||
|
||||
(c == KeyEvent.VK_SHIFT)) {
|
||||
// these events are ignored
|
||||
|
||||
/*
|
||||
} else if (c == KeyEvent.VK_ESCAPE) {
|
||||
unedit();
|
||||
editor.toolbar.clear();
|
||||
event.consume();
|
||||
*/
|
||||
|
||||
} else if (c == KeyEvent.VK_SPACE) {
|
||||
String t = editField.getText();
|
||||
int start = editField.getSelectionStart();
|
||||
int end = editField.getSelectionEnd();
|
||||
editField.setText(t.substring(0, start) + "_" +
|
||||
t.substring(end));
|
||||
editField.setCaretPosition(start+1);
|
||||
event.consume();
|
||||
|
||||
} else if ((c == '_') || (c == '.') || // allow .pde and .java
|
||||
((c >= 'A') && (c <= 'Z')) ||
|
||||
((c >= 'a') && (c <= 'z'))) {
|
||||
// these are ok, allow them through
|
||||
|
||||
} else if ((c >= '0') && (c <= '9')) {
|
||||
// getCaretPosition == 0 means that it's the first char
|
||||
// and the field is empty.
|
||||
// getSelectionStart means that it *will be* the first
|
||||
// char, because the selection is about to be replaced
|
||||
// with whatever is typed.
|
||||
if ((editField.getCaretPosition() == 0) ||
|
||||
(editField.getSelectionStart() == 0)) {
|
||||
// number not allowed as first digit
|
||||
//System.out.println("bad number bad");
|
||||
event.consume();
|
||||
}
|
||||
} else {
|
||||
event.consume();
|
||||
//System.out.println("code is " + code + " char = " + c);
|
||||
}
|
||||
//System.out.println("code is " + code + " char = " + c);
|
||||
}
|
||||
});
|
||||
add(editField);
|
||||
editField.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void setButtonBounds() {
|
||||
int top = (sizeH - Preferences.BUTTON_HEIGHT) / 2;
|
||||
int eachButton = Preferences.GUI_SMALL + Preferences.BUTTON_WIDTH;
|
||||
|
||||
int cancelLeft = sizeW - eachButton;
|
||||
int noLeft = cancelLeft - eachButton;
|
||||
int yesLeft = noLeft - eachButton;
|
||||
|
||||
//yesButton.setLocation(yesLeft, top);
|
||||
//noButton.setLocation(noLeft, top);
|
||||
cancelButton.setLocation(cancelLeft, top);
|
||||
okButton.setLocation(noLeft, top);
|
||||
|
||||
//yesButton.setSize(Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
|
||||
//noButton.setSize(Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
|
||||
cancelButton.setSize(Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
|
||||
okButton.setSize(Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
|
||||
|
||||
// edit field height is awkward, and very different between mac and pc,
|
||||
// so use at least the preferred height for now.
|
||||
int editWidth = 2*Preferences.BUTTON_WIDTH;
|
||||
int editHeight = editField.getPreferredSize().height;
|
||||
int editTop = (1 + sizeH - editHeight) / 2; // add 1 for ceil
|
||||
editField.setBounds(yesLeft - Preferences.BUTTON_WIDTH, editTop,
|
||||
editWidth, editHeight);
|
||||
}
|
||||
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return getMinimumSize();
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension(300, Preferences.GRID_SIZE);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(3000, Preferences.GRID_SIZE);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (e.getSource() == cancelButton) {
|
||||
if (mode == EDIT) unedit();
|
||||
//editor.toolbar.clear();
|
||||
|
||||
} else if (e.getSource() == okButton) {
|
||||
// answering to rename/new code question
|
||||
if (mode == EDIT) { // this if() isn't (shouldn't be?) necessary
|
||||
String answer = editField.getText();
|
||||
editor.getSketch().nameCode(answer);
|
||||
unedit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
447
app/src/processing/app/EditorToolbar.java
Normal file
447
app/src/processing/app/EditorToolbar.java
Normal file
@ -0,0 +1,447 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
|
||||
/**
|
||||
* run/stop/etc buttons for the ide
|
||||
*/
|
||||
public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
|
||||
static final String title[] = {
|
||||
"Run", "Stop", "New", "Open", "Save", "Export"
|
||||
};
|
||||
|
||||
static final int BUTTON_COUNT = title.length;
|
||||
/** Width of each toolbar button. */
|
||||
static final int BUTTON_WIDTH = 27;
|
||||
/** Height of each toolbar button. */
|
||||
static final int BUTTON_HEIGHT = 32;
|
||||
/** The amount of space between groups of buttons on the toolbar. */
|
||||
static final int BUTTON_GAP = 5;
|
||||
|
||||
static final int RUN = 0;
|
||||
static final int STOP = 1;
|
||||
|
||||
static final int NEW = 2;
|
||||
static final int OPEN = 3;
|
||||
static final int SAVE = 4;
|
||||
static final int EXPORT = 5;
|
||||
|
||||
static final int INACTIVE = 0;
|
||||
static final int ROLLOVER = 1;
|
||||
static final int ACTIVE = 2;
|
||||
|
||||
Editor editor;
|
||||
//boolean disableRun; // this was for library
|
||||
//Label status;
|
||||
|
||||
Image offscreen;
|
||||
int width, height;
|
||||
|
||||
Color bgcolor;
|
||||
|
||||
static Image buttons;
|
||||
static Image inactive[];
|
||||
static Image rollover[];
|
||||
static Image active[];
|
||||
int currentRollover;
|
||||
//int currentSelection;
|
||||
|
||||
JPopupMenu popup;
|
||||
JMenu menu;
|
||||
|
||||
int buttonCount;
|
||||
int state[] = new int[BUTTON_COUNT];
|
||||
Image stateImage[];
|
||||
int which[]; // mapping indices to implementation
|
||||
|
||||
int x1[], x2[];
|
||||
int y1, y2;
|
||||
|
||||
String status;
|
||||
Font statusFont;
|
||||
Color statusColor;
|
||||
|
||||
|
||||
public EditorToolbar(Editor editor, JMenu menu) {
|
||||
this.editor = editor;
|
||||
this.menu = menu;
|
||||
|
||||
if (buttons == null) {
|
||||
buttons = Base.getThemeImage("buttons.gif", this);
|
||||
}
|
||||
|
||||
buttonCount = 0;
|
||||
which = new int[BUTTON_COUNT];
|
||||
|
||||
//which[buttonCount++] = NOTHING;
|
||||
which[buttonCount++] = RUN;
|
||||
which[buttonCount++] = STOP;
|
||||
which[buttonCount++] = NEW;
|
||||
which[buttonCount++] = OPEN;
|
||||
which[buttonCount++] = SAVE;
|
||||
which[buttonCount++] = EXPORT;
|
||||
|
||||
currentRollover = -1;
|
||||
|
||||
bgcolor = Theme.getColor("buttons.bgcolor");
|
||||
|
||||
status = "";
|
||||
|
||||
statusFont = Theme.getFont("buttons.status.font");
|
||||
statusColor = Theme.getColor("buttons.status.color");
|
||||
|
||||
addMouseListener(this);
|
||||
addMouseMotionListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void paintComponent(Graphics screen) {
|
||||
// this data is shared by all EditorToolbar instances
|
||||
if (inactive == null) {
|
||||
inactive = new Image[BUTTON_COUNT];
|
||||
rollover = new Image[BUTTON_COUNT];
|
||||
active = new Image[BUTTON_COUNT];
|
||||
|
||||
int IMAGE_SIZE = 33;
|
||||
|
||||
for (int i = 0; i < BUTTON_COUNT; i++) {
|
||||
inactive[i] = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
Graphics g = inactive[i].getGraphics();
|
||||
g.drawImage(buttons, -(i*IMAGE_SIZE) - 3, -2*IMAGE_SIZE, null);
|
||||
|
||||
rollover[i] = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
g = rollover[i].getGraphics();
|
||||
g.drawImage(buttons, -(i*IMAGE_SIZE) - 3, -1*IMAGE_SIZE, null);
|
||||
|
||||
active[i] = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
g = active[i].getGraphics();
|
||||
g.drawImage(buttons, -(i*IMAGE_SIZE) - 3, -0*IMAGE_SIZE, null);
|
||||
}
|
||||
}
|
||||
|
||||
// this happens once per instance of EditorToolbar
|
||||
if (stateImage == null) {
|
||||
state = new int[buttonCount];
|
||||
stateImage = new Image[buttonCount];
|
||||
for (int i = 0; i < buttonCount; i++) {
|
||||
setState(i, INACTIVE, false);
|
||||
}
|
||||
y1 = 0;
|
||||
y2 = BUTTON_HEIGHT;
|
||||
x1 = new int[buttonCount];
|
||||
x2 = new int[buttonCount];
|
||||
}
|
||||
|
||||
Dimension size = getSize();
|
||||
if ((offscreen == null) ||
|
||||
(size.width != width) || (size.height != height)) {
|
||||
offscreen = createImage(size.width, size.height);
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
|
||||
int offsetX = 3;
|
||||
for (int i = 0; i < buttonCount; i++) {
|
||||
x1[i] = offsetX;
|
||||
if (i == 2) x1[i] += BUTTON_GAP;
|
||||
x2[i] = x1[i] + BUTTON_WIDTH;
|
||||
offsetX = x2[i];
|
||||
}
|
||||
}
|
||||
Graphics g = offscreen.getGraphics();
|
||||
g.setColor(bgcolor); //getBackground());
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
for (int i = 0; i < buttonCount; i++) {
|
||||
g.drawImage(stateImage[i], x1[i], y1, null);
|
||||
}
|
||||
|
||||
g.setColor(statusColor);
|
||||
g.setFont(statusFont);
|
||||
|
||||
/*
|
||||
// if i ever find the guy who wrote the java2d api, i will hurt him.
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
FontRenderContext frc = g2.getFontRenderContext();
|
||||
float statusW = (float) statusFont.getStringBounds(status, frc).getWidth();
|
||||
float statusX = (getSize().width - statusW) / 2;
|
||||
g2.drawString(status, statusX, statusY);
|
||||
*/
|
||||
//int statusY = (BUTTON_HEIGHT + statusFont.getAscent()) / 2;
|
||||
int statusY = (BUTTON_HEIGHT + g.getFontMetrics().getAscent()) / 2;
|
||||
g.drawString(status, buttonCount * BUTTON_WIDTH + 3 * BUTTON_GAP, statusY);
|
||||
|
||||
screen.drawImage(offscreen, 0, 0, null);
|
||||
}
|
||||
|
||||
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// mouse events before paint();
|
||||
if (state == null) return;
|
||||
|
||||
if (state[OPEN] != INACTIVE) {
|
||||
// avoid flicker, since there will probably be an update event
|
||||
setState(OPEN, INACTIVE, false);
|
||||
}
|
||||
//System.out.println(e);
|
||||
//mouseMove(e);
|
||||
handleMouse(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
|
||||
public void mouseDragged(MouseEvent e) { }
|
||||
|
||||
|
||||
public void handleMouse(int x, int y) {
|
||||
if (currentRollover != -1) {
|
||||
if ((x > x1[currentRollover]) && (y > y1) &&
|
||||
(x < x2[currentRollover]) && (y < y2)) {
|
||||
return;
|
||||
|
||||
} else {
|
||||
setState(currentRollover, INACTIVE, true);
|
||||
messageClear(title[currentRollover]);
|
||||
currentRollover = -1;
|
||||
}
|
||||
}
|
||||
int sel = findSelection(x, y);
|
||||
if (sel == -1) return;
|
||||
|
||||
if (state[sel] != ACTIVE) {
|
||||
//if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
|
||||
setState(sel, ROLLOVER, true);
|
||||
currentRollover = sel;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int findSelection(int x, int y) {
|
||||
// if app loads slowly and cursor is near the buttons
|
||||
// when it comes up, the app may not have time to load
|
||||
if ((x1 == null) || (x2 == null)) return -1;
|
||||
|
||||
for (int i = 0; i < buttonCount; i++) {
|
||||
if ((y > y1) && (x > x1[i]) &&
|
||||
(y < y2) && (x < x2[i])) {
|
||||
//System.out.println("sel is " + i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private void setState(int slot, int newState, boolean updateAfter) {
|
||||
//if (inactive == null) return;
|
||||
state[slot] = newState;
|
||||
switch (newState) {
|
||||
case INACTIVE:
|
||||
stateImage[slot] = inactive[which[slot]];
|
||||
break;
|
||||
case ACTIVE:
|
||||
stateImage[slot] = active[which[slot]];
|
||||
break;
|
||||
case ROLLOVER:
|
||||
stateImage[slot] = rollover[which[slot]];
|
||||
message(title[which[slot]]);
|
||||
break;
|
||||
}
|
||||
if (updateAfter) {
|
||||
//System.out.println("trying to update " + slot + " " + state[slot]);
|
||||
//new Exception("setting slot " + slot + " to " + state[slot]).printStackTrace();
|
||||
repaint(); // changed for swing from update();
|
||||
//Toolkit.getDefaultToolkit().sync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
//mouseMove(e);
|
||||
handleMouse(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
|
||||
public void mouseExited(MouseEvent e) {
|
||||
// if the popup menu for is visible, don't register this,
|
||||
// because the popup being set visible will fire a mouseExited() event
|
||||
if ((popup != null) && popup.isVisible()) return;
|
||||
|
||||
if (state[OPEN] != INACTIVE) {
|
||||
setState(OPEN, INACTIVE, true);
|
||||
}
|
||||
status = "";
|
||||
handleMouse(e.getX(), e.getY());
|
||||
}
|
||||
|
||||
int wasDown = -1;
|
||||
|
||||
|
||||
public void mousePressed(MouseEvent e) {
|
||||
final int x = e.getX();
|
||||
final int y = e.getY();
|
||||
|
||||
int sel = findSelection(x, y);
|
||||
///if (sel == -1) return false;
|
||||
if (sel == -1) return;
|
||||
currentRollover = -1;
|
||||
|
||||
switch (sel) {
|
||||
case RUN:
|
||||
editor.handleRun(e.isShiftDown());
|
||||
break;
|
||||
|
||||
case STOP:
|
||||
editor.handleStop();
|
||||
break;
|
||||
|
||||
case OPEN:
|
||||
popup = menu.getPopupMenu();
|
||||
popup.show(EditorToolbar.this, x, y);
|
||||
break;
|
||||
|
||||
case NEW:
|
||||
//editor.base.handleNew(e.isShiftDown());
|
||||
editor.base.handleNewReplace();
|
||||
break;
|
||||
|
||||
case SAVE:
|
||||
editor.handleSave(false);
|
||||
break;
|
||||
|
||||
case EXPORT:
|
||||
if (e.isShiftDown()) {
|
||||
editor.handleExportApplication();
|
||||
} else {
|
||||
editor.handleExport();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void mouseClicked(MouseEvent e) { }
|
||||
|
||||
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
/*
|
||||
switch (currentSelection) {
|
||||
|
||||
case OPEN:
|
||||
setState(OPEN, INACTIVE, true);
|
||||
break;
|
||||
}
|
||||
currentSelection = -1;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//public void disableRun(boolean what) {
|
||||
//disableRun = what;
|
||||
//}
|
||||
|
||||
|
||||
/*
|
||||
public void run() {
|
||||
if (inactive == null) return;
|
||||
clear();
|
||||
setState(RUN, ACTIVE, true);
|
||||
}
|
||||
*/
|
||||
|
||||
// public void running(boolean yesno) {
|
||||
// setState(RUN, yesno ? ACTIVE : INACTIVE, true);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Set a particular button to be active.
|
||||
*/
|
||||
public void activate(int what) {
|
||||
//System.out.println("activating " + what);
|
||||
if (inactive == null) return;
|
||||
setState(what, ACTIVE, true);
|
||||
}
|
||||
|
||||
//public void clearRun() {
|
||||
//if (inactive == null) return;
|
||||
//setState(RUN, INACTIVE, true);
|
||||
//}
|
||||
|
||||
|
||||
/**
|
||||
* Set a particular button to be active.
|
||||
*/
|
||||
public void deactivate(int what) {
|
||||
if (inactive == null) return; // don't draw if not ready
|
||||
setState(what, INACTIVE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all the state of all buttons.
|
||||
*/
|
||||
// public void clear() { // (int button) {
|
||||
// if (inactive == null) return;
|
||||
//
|
||||
// System.out.println("clearing state of buttons");
|
||||
// // skip the run button, do the others
|
||||
// for (int i = 1; i < buttonCount; i++) {
|
||||
// setState(i, INACTIVE, false);
|
||||
// }
|
||||
// repaint(); // changed for swing from update();
|
||||
// }
|
||||
|
||||
|
||||
public void message(String msg) {
|
||||
//status.setText(msg + " "); // don't mind the hack
|
||||
status = msg;
|
||||
}
|
||||
|
||||
|
||||
public void messageClear(String msg) {
|
||||
//if (status.getText().equals(msg + " ")) status.setText(Editor.EMPTY);
|
||||
if (status.equals(msg)) status = "";
|
||||
}
|
||||
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return getMinimumSize();
|
||||
}
|
||||
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension((BUTTON_COUNT + 1)*BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
}
|
||||
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(3000, BUTTON_HEIGHT);
|
||||
}
|
||||
}
|
350
app/src/processing/app/FindReplace.java
Normal file
350
app/src/processing/app/FindReplace.java
Normal file
@ -0,0 +1,350 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
/**
|
||||
* Find & Replace window for the Processing editor.
|
||||
* <p/>
|
||||
* One major annoyance in this is that the window is re-created each time
|
||||
* that "Find" is called. This is because Mac OS X has a strange focus
|
||||
* issue with windows that are re-shown with setVisible() or show().
|
||||
* requestFocusInWindow() properly sets the focus to the find field,
|
||||
* however, just a short moment later, the focus is set to null. Even
|
||||
* trying to catch this scenario and request it again doesn't seem to work.
|
||||
* Most likely this is some annoyance buried deep in one of Apple's docs,
|
||||
* or in the doc for the focus stuff (I tend to think the former because
|
||||
* Windows doesn't seem to be quite so beligerent). Filed as
|
||||
* <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=244"> Bug 244</A>
|
||||
* should anyone have clues about how to fix.
|
||||
*/
|
||||
public class FindReplace extends JFrame implements ActionListener {
|
||||
|
||||
static final int BIG = 13;
|
||||
static final int SMALL = 6;
|
||||
|
||||
Editor editor;
|
||||
|
||||
JTextField findField;
|
||||
JTextField replaceField;
|
||||
static String findString;
|
||||
static String replaceString;
|
||||
|
||||
JButton replaceButton;
|
||||
JButton replaceAllButton;
|
||||
JButton replaceFindButton;
|
||||
JButton findButton;
|
||||
|
||||
JCheckBox ignoreCaseBox;
|
||||
static boolean ignoreCase = true;
|
||||
|
||||
/// true when there's something selected in the editor
|
||||
boolean found;
|
||||
|
||||
|
||||
public FindReplace(Editor editor) {
|
||||
super("Find");
|
||||
setResizable(false);
|
||||
this.editor = editor;
|
||||
|
||||
Container pain = getContentPane();
|
||||
pain.setLayout(null);
|
||||
|
||||
JLabel findLabel = new JLabel("Find:");
|
||||
Dimension d0 = findLabel.getPreferredSize();
|
||||
JLabel replaceLabel = new JLabel("Replace with:");
|
||||
Dimension d1 = replaceLabel.getPreferredSize();
|
||||
|
||||
pain.add(findLabel);
|
||||
pain.add(replaceLabel);
|
||||
|
||||
pain.add(findField = new JTextField(20));
|
||||
pain.add(replaceField = new JTextField(20));
|
||||
Dimension d2 = findField.getPreferredSize();
|
||||
|
||||
if (findString != null) findField.setText(findString);
|
||||
if (replaceString != null) replaceField.setText(replaceString);
|
||||
//System.out.println("setting find str to " + findString);
|
||||
//findField.requestFocusInWindow();
|
||||
|
||||
//pain.setDefault
|
||||
/*
|
||||
findField.addFocusListener(new FocusListener() {
|
||||
public void focusGained(FocusEvent e) {
|
||||
System.out.println("Focus gained " + e.getOppositeComponent());
|
||||
}
|
||||
|
||||
public void focusLost(FocusEvent e) {
|
||||
System.out.println("Focus lost "); // + e.getOppositeComponent());
|
||||
if (e.getOppositeComponent() == null) {
|
||||
requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
// +1 since it's better to tend downwards
|
||||
int yoff = (1 + d2.height - d1.height) / 2;
|
||||
|
||||
findLabel.setBounds(BIG + (d1.width-d0.width) + yoff, BIG,
|
||||
d1.width, d1.height);
|
||||
replaceLabel.setBounds(BIG, BIG + d2.height + SMALL + yoff,
|
||||
d1.width, d1.height);
|
||||
|
||||
//ignoreCase = true;
|
||||
ignoreCaseBox = new JCheckBox("Ignore Case");
|
||||
ignoreCaseBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ignoreCase = ignoreCaseBox.isSelected();
|
||||
}
|
||||
});
|
||||
ignoreCaseBox.setSelected(ignoreCase);
|
||||
pain.add(ignoreCaseBox);
|
||||
|
||||
//
|
||||
|
||||
JPanel buttons = new JPanel();
|
||||
buttons.setLayout(new FlowLayout());
|
||||
|
||||
// ordering is different on mac versus pc
|
||||
if (Base.isMacOS()) {
|
||||
buttons.add(replaceAllButton = new JButton("Replace All"));
|
||||
buttons.add(replaceButton = new JButton("Replace"));
|
||||
buttons.add(replaceFindButton = new JButton("Replace & Find"));
|
||||
buttons.add(findButton = new JButton("Find"));
|
||||
|
||||
} else {
|
||||
buttons.add(findButton = new JButton("Find"));
|
||||
buttons.add(replaceFindButton = new JButton("Replace & Find"));
|
||||
buttons.add(replaceButton = new JButton("Replace"));
|
||||
buttons.add(replaceAllButton = new JButton("Replace All"));
|
||||
}
|
||||
pain.add(buttons);
|
||||
|
||||
// to fix ugliness.. normally macosx java 1.3 puts an
|
||||
// ugly white border around this object, so turn it off.
|
||||
if (Base.isMacOS()) {
|
||||
buttons.setBorder(null);
|
||||
}
|
||||
|
||||
Dimension d3 = buttons.getPreferredSize();
|
||||
//buttons.setBounds(BIG, BIG + d2.height*2 + SMALL + BIG,
|
||||
buttons.setBounds(BIG, BIG + d2.height*3 + SMALL*2 + BIG,
|
||||
d3.width, d3.height);
|
||||
|
||||
//
|
||||
|
||||
findField.setBounds(BIG + d1.width + SMALL, BIG,
|
||||
d3.width - (d1.width + SMALL), d2.height);
|
||||
replaceField.setBounds(BIG + d1.width + SMALL, BIG + d2.height + SMALL,
|
||||
d3.width - (d1.width + SMALL), d2.height);
|
||||
|
||||
ignoreCaseBox.setBounds(BIG + d1.width + SMALL,
|
||||
BIG + d2.height*2 + SMALL*2,
|
||||
d3.width, d2.height);
|
||||
|
||||
//
|
||||
|
||||
replaceButton.addActionListener(this);
|
||||
replaceAllButton.addActionListener(this);
|
||||
replaceFindButton.addActionListener(this);
|
||||
findButton.addActionListener(this);
|
||||
|
||||
// you mustn't replace what you haven't found, my son
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
|
||||
// so that typing will go straight to this field
|
||||
//findField.requestFocus();
|
||||
|
||||
// make the find button the blinky default
|
||||
getRootPane().setDefaultButton(findButton);
|
||||
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
|
||||
int wide = d3.width + BIG*2;
|
||||
Rectangle butt = buttons.getBounds(); // how big is your butt?
|
||||
int high = butt.y + butt.height + BIG*2 + SMALL;
|
||||
|
||||
setBounds((screen.width - wide) / 2,
|
||||
(screen.height - high) / 2, wide, high);
|
||||
|
||||
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
handleClose();
|
||||
}
|
||||
});
|
||||
Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
//hide();
|
||||
handleClose();
|
||||
}
|
||||
});
|
||||
Base.setIcon(this);
|
||||
|
||||
// hack to to get first field to focus properly on osx
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowActivated(WindowEvent e) {
|
||||
//System.out.println("activating");
|
||||
/*boolean ok =*/ findField.requestFocusInWindow();
|
||||
//System.out.println("got " + ok);
|
||||
findField.selectAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void handleClose() {
|
||||
//System.out.println("handling close now");
|
||||
findString = findField.getText();
|
||||
replaceString = replaceField.getText();
|
||||
|
||||
// this object should eventually become dereferenced
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public void show() {
|
||||
findField.requestFocusInWindow();
|
||||
super.show();
|
||||
//findField.selectAll();
|
||||
//findField.requestFocus();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Object source = e.getSource();
|
||||
|
||||
if (source == findButton) {
|
||||
find(true);
|
||||
|
||||
} else if (source == replaceFindButton) {
|
||||
replace();
|
||||
find(true);
|
||||
|
||||
} else if (source == replaceButton) {
|
||||
replace();
|
||||
|
||||
} else if (source == replaceAllButton) {
|
||||
replaceAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// look for the next instance of the find string
|
||||
// to be found later than the current caret selection
|
||||
|
||||
// once found, select it (and go to that line)
|
||||
|
||||
public void find(boolean wrap) {
|
||||
// in case search len is zero,
|
||||
// otherwise replace all will go into an infinite loop
|
||||
found = false;
|
||||
|
||||
String search = findField.getText();
|
||||
//System.out.println("finding for " + search + " " + findString);
|
||||
// this will catch "find next" being called when no search yet
|
||||
if (search.length() == 0) return;
|
||||
|
||||
String text = editor.getText();
|
||||
|
||||
if (ignoreCase) {
|
||||
search = search.toLowerCase();
|
||||
text = text.toLowerCase();
|
||||
}
|
||||
|
||||
//int selectionStart = editor.textarea.getSelectionStart();
|
||||
int selectionEnd = editor.getSelectionStop();
|
||||
|
||||
int nextIndex = text.indexOf(search, selectionEnd);
|
||||
if (nextIndex == -1) {
|
||||
if (wrap) {
|
||||
// if wrapping, a second chance is ok, start from beginning
|
||||
nextIndex = text.indexOf(search, 0);
|
||||
}
|
||||
|
||||
if (nextIndex == -1) {
|
||||
found = false;
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
//Toolkit.getDefaultToolkit().beep();
|
||||
return;
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
replaceButton.setEnabled(true);
|
||||
replaceFindButton.setEnabled(true);
|
||||
editor.setSelection(nextIndex, nextIndex + search.length());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace the current selection with whatever's in the
|
||||
* replacement text field.
|
||||
*/
|
||||
public void replace() {
|
||||
if (!found) return; // don't replace if nothing found
|
||||
|
||||
// check to see if the document has wrapped around
|
||||
// otherwise this will cause an infinite loop
|
||||
String sel = editor.getSelectedText();
|
||||
if (sel.equals(replaceField.getText())) {
|
||||
found = false;
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
editor.setSelectedText(replaceField.getText());
|
||||
//editor.setSketchModified(true);
|
||||
//editor.sketch.setCurrentModified(true);
|
||||
editor.getSketch().setModified(true); // TODO is this necessary?
|
||||
|
||||
// don't allow a double replace
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace everything that matches by doing find and replace
|
||||
* alternately until nothing more found.
|
||||
*/
|
||||
public void replaceAll() {
|
||||
// move to the beginning
|
||||
editor.setSelection(0, 0);
|
||||
|
||||
do {
|
||||
find(false);
|
||||
replace();
|
||||
} while (found);
|
||||
}
|
||||
}
|
139
app/src/processing/app/Platform.java
Normal file
139
app/src/processing/app/Platform.java
Normal file
@ -0,0 +1,139 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
|
||||
/**
|
||||
* Used by Base for platform-specific tweaking, for instance finding the
|
||||
* sketchbook location using the Windows registry, or OS X event handling.
|
||||
*
|
||||
* The methods in this implementation are used by default, and can be
|
||||
* overridden by a subclass, if loaded by Base.main().
|
||||
*
|
||||
* These methods throw vanilla-flavored Exceptions, so that error handling
|
||||
* occurs inside Base.
|
||||
*
|
||||
* There is currently no mechanism for adding new platforms, as the setup is
|
||||
* not automated. We could use getProperty("os.arch") perhaps, but that's
|
||||
* debatable (could be upper/lowercase, have spaces, etc.. basically we don't
|
||||
* know if name is proper Java package syntax.)
|
||||
*/
|
||||
public class Platform {
|
||||
Base base;
|
||||
|
||||
|
||||
/**
|
||||
* Set the default L & F. While I enjoy the bounty of the sixteen possible
|
||||
* exception types that this UIManager method might throw, I feel that in
|
||||
* just this one particular case, I'm being spoiled by those engineers
|
||||
* at Sun, those Masters of the Abstractionverse. It leaves me feeling sad
|
||||
* and overweight. So instead, I'll pretend that I'm not offered eleven dozen
|
||||
* ways to report to the user exactly what went wrong, and I'll bundle them
|
||||
* all into a single catch-all "Exception". Because in the end, all I really
|
||||
* care about is whether things worked or not. And even then, I don't care.
|
||||
*
|
||||
* @throws Exception Just like I said.
|
||||
*/
|
||||
public void setLookAndFeel() throws Exception {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
}
|
||||
|
||||
|
||||
public void init(Base base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
|
||||
public File getSettingsFolder() throws Exception {
|
||||
// otherwise make a .processing directory int the user's home dir
|
||||
File home = new File(System.getProperty("user.home"));
|
||||
File dataFolder = new File(home, ".processing");
|
||||
return dataFolder;
|
||||
|
||||
/*
|
||||
try {
|
||||
Class clazz = Class.forName("processing.app.macosx.ThinkDifferent");
|
||||
Method m = clazz.getMethod("getLibraryFolder", new Class[] { });
|
||||
String libraryPath = (String) m.invoke(null, new Object[] { });
|
||||
//String libraryPath = BaseMacOS.getLibraryFolder();
|
||||
File libraryFolder = new File(libraryPath);
|
||||
dataFolder = new File(libraryFolder, "Processing");
|
||||
|
||||
} catch (Exception e) {
|
||||
showError("Problem getting data folder",
|
||||
"Error getting the Processing data folder.", e);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return null if not overridden, which will cause a prompt to show instead.
|
||||
* @throws Exception
|
||||
*/
|
||||
public File getDefaultSketchbookFolder() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void openURL(String url) throws Exception {
|
||||
String launcher = Preferences.get("launcher");
|
||||
if (launcher != null) {
|
||||
Runtime.getRuntime().exec(new String[] { launcher, url });
|
||||
} else {
|
||||
showLauncherWarning();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean openFolderAvailable() {
|
||||
return Preferences.get("launcher") != null;
|
||||
}
|
||||
|
||||
|
||||
public void openFolder(File file) throws Exception {
|
||||
String launcher = Preferences.get("launcher");
|
||||
if (launcher != null) {
|
||||
String folder = file.getAbsolutePath();
|
||||
Runtime.getRuntime().exec(new String[] { launcher, folder });
|
||||
} else {
|
||||
showLauncherWarning();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
protected void showLauncherWarning() {
|
||||
Base.showWarning("No launcher available",
|
||||
"Unspecified platform, no launcher available.\n" +
|
||||
"To enable opening URLs or folders, add a \n" +
|
||||
"\"launcher=/path/to/app\" line to preferences.txt",
|
||||
null);
|
||||
}
|
||||
}
|
909
app/src/processing/app/Preferences.java
Normal file
909
app/src/processing/app/Preferences.java
Normal file
@ -0,0 +1,909 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import processing.app.syntax.*;
|
||||
import processing.core.*;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Storage class for user preferences and environment settings.
|
||||
* <P>
|
||||
* This class no longer uses the Properties class, since
|
||||
* properties files are iso8859-1, which is highly likely to
|
||||
* be a problem when trying to save sketch folders and locations.
|
||||
* <p>
|
||||
* The GUI portion in here is really ugly, as it uses exact layout. This was
|
||||
* done in frustration one evening (and pre-Swing), but that's long since past,
|
||||
* and it should all be moved to a proper swing layout like BoxLayout.
|
||||
* <p>
|
||||
* This is very poorly put together, that the preferences panel and the actual
|
||||
* preferences i/o is part of the same code. But there hasn't yet been a
|
||||
* compelling reason to bother with the separation aside from concern about
|
||||
* being lectured by strangers who feel that it doesn't look like what they
|
||||
* learned in CS class.
|
||||
* <p>
|
||||
* Would also be possible to change this to use the Java Preferences API.
|
||||
* Some useful articles
|
||||
* <a href="http://www.onjava.com/pub/a/onjava/synd/2001/10/17/j2se.html">here</a> and
|
||||
* <a href="http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter10/Preferences.html">here</a>.
|
||||
* However, haven't implemented this yet for lack of time, but more
|
||||
* importantly, because it would entail writing to the registry (on Windows),
|
||||
* or an obscure file location (on Mac OS X) and make it far more difficult to
|
||||
* find the preferences to tweak them by hand (no! stay out of regedit!)
|
||||
* or to reset the preferences by simply deleting the preferences.txt file.
|
||||
*/
|
||||
public class Preferences {
|
||||
|
||||
// what to call the feller
|
||||
|
||||
static final String PREFS_FILE = "preferences.txt";
|
||||
|
||||
|
||||
// platform strings (used to get settings for specific platforms)
|
||||
|
||||
//static final String platforms[] = {
|
||||
// "other", "windows", "macosx", "linux"
|
||||
//};
|
||||
|
||||
|
||||
// prompt text stuff
|
||||
|
||||
static final String PROMPT_YES = "Yes";
|
||||
static final String PROMPT_NO = "No";
|
||||
static final String PROMPT_CANCEL = "Cancel";
|
||||
static final String PROMPT_OK = "OK";
|
||||
static final String PROMPT_BROWSE = "Browse";
|
||||
|
||||
/**
|
||||
* Standardized width for buttons. Mac OS X 10.3 wants 70 as its default,
|
||||
* Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper.
|
||||
*/
|
||||
static public int BUTTON_WIDTH = 80;
|
||||
|
||||
/**
|
||||
* Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29,
|
||||
* presumably because it now includes the blue border, where it didn't
|
||||
* in Java 1.3. Windows XP only wants 23 (not sure what default Linux
|
||||
* would be). Because of the disparity, on Mac OS X, it will be set
|
||||
* inside a static block.
|
||||
*/
|
||||
static public int BUTTON_HEIGHT = 24;
|
||||
/*
|
||||
// remove this for 0121, because quaqua takes care of it
|
||||
static {
|
||||
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
|
||||
}
|
||||
*/
|
||||
|
||||
// value for the size bars, buttons, etc
|
||||
|
||||
static final int GRID_SIZE = 33;
|
||||
|
||||
|
||||
// indents and spacing standards. these probably need to be modified
|
||||
// per platform as well, since macosx is so huge, windows is smaller,
|
||||
// and linux is all over the map
|
||||
|
||||
static final int GUI_BIG = 13;
|
||||
static final int GUI_BETWEEN = 10;
|
||||
static final int GUI_SMALL = 6;
|
||||
|
||||
// gui elements
|
||||
|
||||
JFrame dialog;
|
||||
int wide, high;
|
||||
|
||||
JTextField sketchbookLocationField;
|
||||
JCheckBox exportSeparateBox;
|
||||
JCheckBox deletePreviousBox;
|
||||
// JCheckBox closingLastQuitsBox;
|
||||
JCheckBox externalEditorBox;
|
||||
JCheckBox memoryOverrideBox;
|
||||
JTextField memoryField;
|
||||
JCheckBox checkUpdatesBox;
|
||||
JTextField fontSizeField;
|
||||
JCheckBox autoAssociateBox;
|
||||
JCheckBox menubarWorkaroundBox;
|
||||
|
||||
|
||||
// the calling editor, so updates can be applied
|
||||
|
||||
Editor editor;
|
||||
|
||||
|
||||
// data model
|
||||
|
||||
static Hashtable defaults;
|
||||
static Hashtable table = new Hashtable();;
|
||||
static File preferencesFile;
|
||||
|
||||
|
||||
static protected void init(String commandLinePrefs) {
|
||||
|
||||
// start by loading the defaults, in case something
|
||||
// important was deleted from the user prefs
|
||||
try {
|
||||
load(Base.getLibStream("preferences.txt"));
|
||||
} catch (Exception e) {
|
||||
Base.showError(null, "Could not read default settings.\n" +
|
||||
"You'll need to reinstall Processing.", e);
|
||||
}
|
||||
|
||||
// check for platform-specific properties in the defaults
|
||||
String platformExt = "." + PConstants.platformNames[PApplet.platform];
|
||||
int platformExtLength = platformExt.length();
|
||||
Enumeration e = table.keys();
|
||||
while (e.hasMoreElements()) {
|
||||
String key = (String) e.nextElement();
|
||||
if (key.endsWith(platformExt)) {
|
||||
// this is a key specific to a particular platform
|
||||
String actualKey = key.substring(0, key.length() - platformExtLength);
|
||||
String value = get(key);
|
||||
table.put(actualKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
// clone the hash table
|
||||
defaults = (Hashtable) table.clone();
|
||||
|
||||
// other things that have to be set explicitly for the defaults
|
||||
setColor("run.window.bgcolor", SystemColor.control);
|
||||
|
||||
// Load a prefs file if specified on the command line
|
||||
if (commandLinePrefs != null) {
|
||||
try {
|
||||
load(new FileInputStream(commandLinePrefs));
|
||||
|
||||
} catch (Exception poe) {
|
||||
Base.showError("Error",
|
||||
"Could not read preferences from " +
|
||||
commandLinePrefs, poe);
|
||||
}
|
||||
} else if (!Base.isCommandLine()) {
|
||||
// next load user preferences file
|
||||
preferencesFile = Base.getSettingsFile(PREFS_FILE);
|
||||
if (!preferencesFile.exists()) {
|
||||
// create a new preferences file if none exists
|
||||
// saves the defaults out to the file
|
||||
save();
|
||||
|
||||
} else {
|
||||
// load the previous preferences file
|
||||
|
||||
try {
|
||||
load(new FileInputStream(preferencesFile));
|
||||
|
||||
} catch (Exception ex) {
|
||||
Base.showError("Error reading preferences",
|
||||
"Error reading the preferences file. " +
|
||||
"Please delete (or move)\n" +
|
||||
preferencesFile.getAbsolutePath() +
|
||||
" and restart Processing.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Theme settings always override preferences
|
||||
// try {
|
||||
// load(Base.getStream("theme/theme.txt"));
|
||||
// } catch (Exception te) {
|
||||
// Base.showError(null, "Could not read color theme settings.\n" +
|
||||
// "You'll need to reinstall Processing.", te);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Preferences() {
|
||||
|
||||
// setup dialog for the prefs
|
||||
|
||||
//dialog = new JDialog(editor, "Preferences", true);
|
||||
dialog = new JFrame("Preferences");
|
||||
dialog.setResizable(false);
|
||||
|
||||
Container pain = dialog.getContentPane();
|
||||
pain.setLayout(null);
|
||||
|
||||
int top = GUI_BIG;
|
||||
int left = GUI_BIG;
|
||||
int right = 0;
|
||||
|
||||
JLabel label;
|
||||
JButton button; //, button2;
|
||||
//JComboBox combo;
|
||||
Dimension d, d2; //, d3;
|
||||
int h, vmax;
|
||||
|
||||
|
||||
// [ ] Quit after closing last sketch window
|
||||
/*
|
||||
closingLastQuitsBox =
|
||||
new JCheckBox("Quit after closing last sketch window");
|
||||
pain.add(closingLastQuitsBox);
|
||||
d = closingLastQuitsBox.getPreferredSize();
|
||||
closingLastQuitsBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
// [ ] Prompt for name and folder when creating new sketch
|
||||
|
||||
sketchPromptBox =
|
||||
new JCheckBox("Prompt for name when opening or creating a sketch");
|
||||
pain.add(sketchPromptBox);
|
||||
d = sketchPromptBox.getPreferredSize();
|
||||
sketchPromptBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
*/
|
||||
|
||||
|
||||
// [ ] Delete empty sketches on Quit
|
||||
|
||||
/*
|
||||
sketchCleanBox = new JCheckBox("Delete empty sketches on Quit");
|
||||
pain.add(sketchCleanBox);
|
||||
d = sketchCleanBox.getPreferredSize();
|
||||
sketchCleanBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
*/
|
||||
|
||||
|
||||
// Sketchbook location:
|
||||
// [...............................] [ Browse ]
|
||||
|
||||
label = new JLabel("Sketchbook location:");
|
||||
pain.add(label);
|
||||
d = label.getPreferredSize();
|
||||
label.setBounds(left, top, d.width, d.height);
|
||||
top += d.height; // + GUI_SMALL;
|
||||
|
||||
sketchbookLocationField = new JTextField(40);
|
||||
pain.add(sketchbookLocationField);
|
||||
d = sketchbookLocationField.getPreferredSize();
|
||||
|
||||
button = new JButton(PROMPT_BROWSE);
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
/*
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.setSelectedFile(new File(sketchbookLocationField.getText()));
|
||||
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
|
||||
int returned = fc.showOpenDialog(new JDialog());
|
||||
if (returned == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fc.getSelectedFile();
|
||||
sketchbookLocationField.setText(file.getAbsolutePath());
|
||||
}
|
||||
*/
|
||||
File dflt = new File(sketchbookLocationField.getText());
|
||||
File file =
|
||||
Base.selectFolder("Select new sketchbook location", dflt, dialog);
|
||||
if (file != null) {
|
||||
sketchbookLocationField.setText(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
});
|
||||
pain.add(button);
|
||||
d2 = button.getPreferredSize();
|
||||
|
||||
// take max height of all components to vertically align em
|
||||
vmax = Math.max(d.height, d2.height);
|
||||
//label.setBounds(left, top + (vmax-d.height)/2,
|
||||
// d.width, d.height);
|
||||
|
||||
//h = left + d.width + GUI_BETWEEN;
|
||||
sketchbookLocationField.setBounds(left, top + (vmax-d.height)/2,
|
||||
d.width, d.height);
|
||||
h = left + d.width + GUI_SMALL; //GUI_BETWEEN;
|
||||
button.setBounds(h, top + (vmax-d2.height)/2,
|
||||
d2.width, d2.height);
|
||||
|
||||
right = Math.max(right, h + d2.width + GUI_BIG);
|
||||
top += vmax + GUI_BETWEEN;
|
||||
|
||||
|
||||
// Editor font size [ ]
|
||||
|
||||
Container box = Box.createHorizontalBox();
|
||||
label = new JLabel("Editor font size: ");
|
||||
box.add(label);
|
||||
fontSizeField = new JTextField(4);
|
||||
box.add(fontSizeField);
|
||||
label = new JLabel(" (requires restart of Processing)");
|
||||
box.add(label);
|
||||
pain.add(box);
|
||||
d = box.getPreferredSize();
|
||||
box.setBounds(left, top, d.width, d.height);
|
||||
Font editorFont = Preferences.getFont("editor.font");
|
||||
fontSizeField.setText(String.valueOf(editorFont.getSize()));
|
||||
top += d.height + GUI_BETWEEN;
|
||||
|
||||
|
||||
// [ ] Increase maximum available memory to [______] MB
|
||||
|
||||
Container memoryBox = Box.createHorizontalBox();
|
||||
memoryOverrideBox = new JCheckBox("Increase maximum available memory to ");
|
||||
memoryBox.add(memoryOverrideBox);
|
||||
memoryField = new JTextField(4);
|
||||
memoryBox.add(memoryField);
|
||||
memoryBox.add(new JLabel(" MB"));
|
||||
pain.add(memoryBox);
|
||||
d = memoryBox.getPreferredSize();
|
||||
memoryBox.setBounds(left, top, d.width, d.height);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
|
||||
|
||||
// [ ] Use multiple .jar files when exporting applets
|
||||
|
||||
exportSeparateBox =
|
||||
new JCheckBox("Use multiple .jar files when exporting applets " +
|
||||
"(ignored when using libraries)");
|
||||
pain.add(exportSeparateBox);
|
||||
d = exportSeparateBox.getPreferredSize();
|
||||
// adding +10 because ubuntu + jre 1.5 truncating items
|
||||
exportSeparateBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
|
||||
|
||||
// [ ] Delete previous applet or application folder on export
|
||||
|
||||
deletePreviousBox =
|
||||
new JCheckBox("Delete previous applet or application folder on export");
|
||||
pain.add(deletePreviousBox);
|
||||
d = deletePreviousBox.getPreferredSize();
|
||||
deletePreviousBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
|
||||
|
||||
// [ ] Use external editor
|
||||
|
||||
externalEditorBox = new JCheckBox("Use external editor");
|
||||
pain.add(externalEditorBox);
|
||||
d = externalEditorBox.getPreferredSize();
|
||||
externalEditorBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
|
||||
|
||||
// [ ] Check for updates on startup
|
||||
|
||||
checkUpdatesBox = new JCheckBox("Check for updates on startup");
|
||||
pain.add(checkUpdatesBox);
|
||||
d = checkUpdatesBox.getPreferredSize();
|
||||
checkUpdatesBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
|
||||
|
||||
// [ ] Automatically associate .pde files with Processing
|
||||
|
||||
if (Base.isWindows()) {
|
||||
autoAssociateBox =
|
||||
new JCheckBox("Automatically associate .pde files with Processing");
|
||||
pain.add(autoAssociateBox);
|
||||
d = autoAssociateBox.getPreferredSize();
|
||||
autoAssociateBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
}
|
||||
|
||||
|
||||
// [ ] Place menu bar inside
|
||||
|
||||
if (Base.isMacOS()) {
|
||||
if (System.getProperty("os.version").startsWith("10.5")) {
|
||||
menubarWorkaroundBox =
|
||||
new JCheckBox("Place menus inside editor window to avoid " +
|
||||
"Apple Java bug (requires restart)");
|
||||
pain.add(menubarWorkaroundBox);
|
||||
d = menubarWorkaroundBox.getPreferredSize();
|
||||
menubarWorkaroundBox.setBounds(left, top, d.width + 10, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height + GUI_BETWEEN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// More preferences are in the ...
|
||||
|
||||
label = new JLabel("More preferences can be edited directly in the file");
|
||||
pain.add(label);
|
||||
d = label.getPreferredSize();
|
||||
label.setForeground(Color.gray);
|
||||
label.setBounds(left, top, d.width, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height; // + GUI_SMALL;
|
||||
|
||||
label = new JLabel(preferencesFile.getAbsolutePath());
|
||||
pain.add(label);
|
||||
d = label.getPreferredSize();
|
||||
label.setBounds(left, top, d.width, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height;
|
||||
|
||||
label = new JLabel("(edit only when Processing is not running)");
|
||||
pain.add(label);
|
||||
d = label.getPreferredSize();
|
||||
label.setForeground(Color.gray);
|
||||
label.setBounds(left, top, d.width, d.height);
|
||||
right = Math.max(right, left + d.width);
|
||||
top += d.height; // + GUI_SMALL;
|
||||
|
||||
|
||||
// [ OK ] [ Cancel ] maybe these should be next to the message?
|
||||
|
||||
button = new JButton(PROMPT_OK);
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
applyFrame();
|
||||
disposeFrame();
|
||||
}
|
||||
});
|
||||
pain.add(button);
|
||||
d2 = button.getPreferredSize();
|
||||
BUTTON_HEIGHT = d2.height;
|
||||
|
||||
h = right - (BUTTON_WIDTH + GUI_SMALL + BUTTON_WIDTH);
|
||||
button.setBounds(h, top, BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
h += BUTTON_WIDTH + GUI_SMALL;
|
||||
|
||||
button = new JButton(PROMPT_CANCEL);
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
disposeFrame();
|
||||
}
|
||||
});
|
||||
pain.add(button);
|
||||
button.setBounds(h, top, BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
|
||||
top += BUTTON_HEIGHT + GUI_BETWEEN;
|
||||
|
||||
|
||||
// finish up
|
||||
|
||||
wide = right + GUI_BIG;
|
||||
high = top + GUI_SMALL;
|
||||
//setSize(wide, high);
|
||||
|
||||
|
||||
// closing the window is same as hitting cancel button
|
||||
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
disposeFrame();
|
||||
}
|
||||
});
|
||||
|
||||
ActionListener disposer = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
disposeFrame();
|
||||
}
|
||||
};
|
||||
Base.registerWindowCloseKeys(dialog.getRootPane(), disposer);
|
||||
Base.setIcon(dialog);
|
||||
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
dialog.setLocation((screen.width - wide) / 2,
|
||||
(screen.height - high) / 2);
|
||||
|
||||
dialog.pack(); // get insets
|
||||
Insets insets = dialog.getInsets();
|
||||
dialog.setSize(wide + insets.left + insets.right,
|
||||
high + insets.top + insets.bottom);
|
||||
|
||||
|
||||
// handle window closing commands for ctrl/cmd-W or hitting ESC.
|
||||
|
||||
pain.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
//System.out.println(e);
|
||||
KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE;
|
||||
if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
|
||||
(KeyStroke.getKeyStrokeForEvent(e).equals(wc))) {
|
||||
disposeFrame();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected JRootPane createRootPane() {
|
||||
System.out.println("creating root pane esc received");
|
||||
|
||||
ActionListener actionListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
//setVisible(false);
|
||||
System.out.println("esc received");
|
||||
}
|
||||
};
|
||||
|
||||
JRootPane rootPane = new JRootPane();
|
||||
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
||||
rootPane.registerKeyboardAction(actionListener, stroke,
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
return rootPane;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(wide, high);
|
||||
}
|
||||
|
||||
|
||||
// .................................................................
|
||||
|
||||
|
||||
/**
|
||||
* Close the window after an OK or Cancel.
|
||||
*/
|
||||
protected void disposeFrame() {
|
||||
dialog.dispose();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change internal settings based on what was chosen in the prefs,
|
||||
* then send a message to the editor saying that it's time to do the same.
|
||||
*/
|
||||
protected void applyFrame() {
|
||||
// put each of the settings into the table
|
||||
setBoolean("export.applet.separate_jar_files",
|
||||
exportSeparateBox.isSelected());
|
||||
setBoolean("export.delete_target_folder",
|
||||
deletePreviousBox.isSelected());
|
||||
|
||||
// setBoolean("sketchbook.closing_last_window_quits",
|
||||
// closingLastQuitsBox.isSelected());
|
||||
//setBoolean("sketchbook.prompt", sketchPromptBox.isSelected());
|
||||
//setBoolean("sketchbook.auto_clean", sketchCleanBox.isSelected());
|
||||
|
||||
// if the sketchbook path has changed, rebuild the menus
|
||||
String oldPath = get("sketchbook.path");
|
||||
String newPath = sketchbookLocationField.getText();
|
||||
if (!newPath.equals(oldPath)) {
|
||||
editor.base.rebuildSketchbookMenus();
|
||||
set("sketchbook.path", newPath);
|
||||
}
|
||||
|
||||
setBoolean("editor.external", externalEditorBox.isSelected());
|
||||
setBoolean("update.check", checkUpdatesBox.isSelected());
|
||||
|
||||
setBoolean("run.options.memory", memoryOverrideBox.isSelected());
|
||||
int memoryMin = Preferences.getInteger("run.options.memory.initial");
|
||||
int memoryMax = Preferences.getInteger("run.options.memory.maximum");
|
||||
try {
|
||||
memoryMax = Integer.parseInt(memoryField.getText().trim());
|
||||
// make sure memory setting isn't too small
|
||||
if (memoryMax < memoryMin) memoryMax = memoryMin;
|
||||
setInteger("run.options.memory.maximum", memoryMax);
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Ignoring bad memory setting");
|
||||
}
|
||||
|
||||
/*
|
||||
// was gonna use this to check memory settings,
|
||||
// but it quickly gets much too messy
|
||||
if (getBoolean("run.options.memory")) {
|
||||
Process process = Runtime.getRuntime().exec(new String[] {
|
||||
"java", "-Xms" + memoryMin + "m", "-Xmx" + memoryMax + "m"
|
||||
});
|
||||
processInput = new SystemOutSiphon(process.getInputStream());
|
||||
processError = new MessageSiphon(process.getErrorStream(), this);
|
||||
}
|
||||
*/
|
||||
|
||||
String newSizeText = fontSizeField.getText();
|
||||
try {
|
||||
int newSize = Integer.parseInt(newSizeText.trim());
|
||||
String pieces[] = PApplet.split(get("editor.font"), ',');
|
||||
pieces[2] = String.valueOf(newSize);
|
||||
set("editor.font", PApplet.join(pieces, ','));
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("ignoring invalid font size " + newSizeText);
|
||||
}
|
||||
|
||||
if (autoAssociateBox != null) {
|
||||
setBoolean("platform.auto_file_type_associations",
|
||||
autoAssociateBox.isSelected());
|
||||
}
|
||||
|
||||
if (menubarWorkaroundBox != null) {
|
||||
setBoolean("apple.laf.useScreenMenuBar",
|
||||
!menubarWorkaroundBox.isSelected());
|
||||
}
|
||||
|
||||
editor.applyPreferences();
|
||||
}
|
||||
|
||||
|
||||
protected void showFrame(Editor editor) {
|
||||
this.editor = editor;
|
||||
|
||||
// set all settings entry boxes to their actual status
|
||||
exportSeparateBox.
|
||||
setSelected(getBoolean("export.applet.separate_jar_files"));
|
||||
deletePreviousBox.
|
||||
setSelected(getBoolean("export.delete_target_folder"));
|
||||
|
||||
//closingLastQuitsBox.
|
||||
// setSelected(getBoolean("sketchbook.closing_last_window_quits"));
|
||||
//sketchPromptBox.
|
||||
// setSelected(getBoolean("sketchbook.prompt"));
|
||||
//sketchCleanBox.
|
||||
// setSelected(getBoolean("sketchbook.auto_clean"));
|
||||
|
||||
sketchbookLocationField.
|
||||
setText(get("sketchbook.path"));
|
||||
externalEditorBox.
|
||||
setSelected(getBoolean("editor.external"));
|
||||
checkUpdatesBox.
|
||||
setSelected(getBoolean("update.check"));
|
||||
memoryOverrideBox.
|
||||
setSelected(getBoolean("run.options.memory"));
|
||||
memoryField.
|
||||
setText(get("run.options.memory.maximum"));
|
||||
|
||||
if (autoAssociateBox != null) {
|
||||
autoAssociateBox.
|
||||
setSelected(getBoolean("platform.auto_file_type_associations"));
|
||||
}
|
||||
|
||||
if (menubarWorkaroundBox != null) {
|
||||
menubarWorkaroundBox.
|
||||
setSelected(!getBoolean("apple.laf.useScreenMenuBar"));
|
||||
}
|
||||
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
// .................................................................
|
||||
|
||||
|
||||
static protected void load(InputStream input) throws IOException {
|
||||
String[] lines = PApplet.loadStrings(input); // Reads as UTF-8
|
||||
for (String line : lines) {
|
||||
if ((line.length() == 0) ||
|
||||
(line.charAt(0) == '#')) continue;
|
||||
|
||||
// this won't properly handle = signs being in the text
|
||||
int equals = line.indexOf('=');
|
||||
if (equals != -1) {
|
||||
String key = line.substring(0, equals).trim();
|
||||
String value = line.substring(equals + 1).trim();
|
||||
table.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// .................................................................
|
||||
|
||||
|
||||
static protected void save() {
|
||||
// try {
|
||||
// on startup, don't worry about it
|
||||
// this is trying to update the prefs for who is open
|
||||
// before Preferences.init() has been called.
|
||||
if (preferencesFile == null) return;
|
||||
|
||||
// Fix for 0163 to properly use Unicode when writing preferences.txt
|
||||
PrintWriter writer = PApplet.createWriter(preferencesFile);
|
||||
|
||||
Enumeration e = table.keys(); //properties.propertyNames();
|
||||
while (e.hasMoreElements()) {
|
||||
String key = (String) e.nextElement();
|
||||
writer.println(key + "=" + ((String) table.get(key)));
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
// } catch (Exception ex) {
|
||||
// Base.showWarning(null, "Error while saving the settings file", ex);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// .................................................................
|
||||
|
||||
|
||||
// all the information from preferences.txt
|
||||
|
||||
//static public String get(String attribute) {
|
||||
//return get(attribute, null);
|
||||
//}
|
||||
|
||||
static public String get(String attribute /*, String defaultValue */) {
|
||||
return (String) table.get(attribute);
|
||||
/*
|
||||
//String value = (properties != null) ?
|
||||
//properties.getProperty(attribute) : applet.getParameter(attribute);
|
||||
String value = properties.getProperty(attribute);
|
||||
|
||||
return (value == null) ?
|
||||
defaultValue : value;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static public String getDefault(String attribute) {
|
||||
return (String) defaults.get(attribute);
|
||||
}
|
||||
|
||||
|
||||
static public void set(String attribute, String value) {
|
||||
table.put(attribute, value);
|
||||
}
|
||||
|
||||
|
||||
static public boolean getBoolean(String attribute) {
|
||||
String value = get(attribute); //, null);
|
||||
return (new Boolean(value)).booleanValue();
|
||||
|
||||
/*
|
||||
supposedly not needed, because anything besides 'true'
|
||||
(ignoring case) will just be false.. so if malformed -> false
|
||||
if (value == null) return defaultValue;
|
||||
|
||||
try {
|
||||
return (new Boolean(value)).booleanValue();
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("expecting an integer: " + attribute + " = " + value);
|
||||
}
|
||||
return defaultValue;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static public void setBoolean(String attribute, boolean value) {
|
||||
set(attribute, value ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
static public int getInteger(String attribute /*, int defaultValue*/) {
|
||||
return Integer.parseInt(get(attribute));
|
||||
|
||||
/*
|
||||
String value = get(attribute, null);
|
||||
if (value == null) return defaultValue;
|
||||
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
// ignored will just fall through to returning the default
|
||||
System.err.println("expecting an integer: " + attribute + " = " + value);
|
||||
}
|
||||
return defaultValue;
|
||||
//if (value == null) return defaultValue;
|
||||
//return (value == null) ? defaultValue :
|
||||
//Integer.parseInt(value);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static public void setInteger(String key, int value) {
|
||||
set(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
|
||||
static public Color getColor(String name) {
|
||||
Color parsed = Color.GRAY; // set a default
|
||||
String s = get(name);
|
||||
if ((s != null) && (s.indexOf("#") == 0)) {
|
||||
try {
|
||||
parsed = new Color(Integer.parseInt(s.substring(1), 16));
|
||||
} catch (Exception e) { }
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
|
||||
static public void setColor(String attr, Color what) {
|
||||
// String r = Integer.toHexString(what.getRed());
|
||||
// String g = Integer.toHexString(what.getGreen());
|
||||
// String b = Integer.toHexString(what.getBlue());
|
||||
// set(attr, "#" + r.substring(r.length() - 2) +
|
||||
// g.substring(g.length() - 2) + b.substring(b.length() - 2));
|
||||
set(attr, "#" + PApplet.hex(what.getRGB() & 0xffffff, 6));
|
||||
}
|
||||
|
||||
|
||||
static public Font getFont(String attr) {
|
||||
boolean replace = false;
|
||||
String value = get(attr);
|
||||
if (value == null) {
|
||||
//System.out.println("reset 1");
|
||||
value = getDefault(attr);
|
||||
replace = true;
|
||||
}
|
||||
|
||||
String[] pieces = PApplet.split(value, ',');
|
||||
if (pieces.length != 3) {
|
||||
value = getDefault(attr);
|
||||
//System.out.println("reset 2 for " + attr);
|
||||
pieces = PApplet.split(value, ',');
|
||||
//PApplet.println(pieces);
|
||||
replace = true;
|
||||
}
|
||||
|
||||
String name = pieces[0];
|
||||
int style = Font.PLAIN; // equals zero
|
||||
if (pieces[1].indexOf("bold") != -1) {
|
||||
style |= Font.BOLD;
|
||||
}
|
||||
if (pieces[1].indexOf("italic") != -1) {
|
||||
style |= Font.ITALIC;
|
||||
}
|
||||
int size = PApplet.parseInt(pieces[2], 12);
|
||||
Font font = new Font(name, style, size);
|
||||
|
||||
// replace bad font with the default
|
||||
if (replace) {
|
||||
set(attr, value);
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
static public SyntaxStyle getStyle(String what /*, String dflt*/) {
|
||||
String str = get("editor." + what + ".style"); //, dflt);
|
||||
|
||||
StringTokenizer st = new StringTokenizer(str, ",");
|
||||
|
||||
String s = st.nextToken();
|
||||
if (s.indexOf("#") == 0) s = s.substring(1);
|
||||
Color color = Color.DARK_GRAY;
|
||||
try {
|
||||
color = new Color(Integer.parseInt(s, 16));
|
||||
} catch (Exception e) { }
|
||||
|
||||
s = st.nextToken();
|
||||
boolean bold = (s.indexOf("bold") != -1);
|
||||
boolean italic = (s.indexOf("italic") != -1);
|
||||
//System.out.println(what + " = " + str + " " + bold + " " + italic);
|
||||
|
||||
return new SyntaxStyle(color, italic, bold);
|
||||
}
|
||||
}
|
128
app/src/processing/app/PresentMode.java
Normal file
128
app/src/processing/app/PresentMode.java
Normal file
@ -0,0 +1,128 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2005-06 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Vector;
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for full-screen presentation mode.
|
||||
*/
|
||||
public class PresentMode {
|
||||
|
||||
static GraphicsDevice devices[];
|
||||
|
||||
/**
|
||||
* Index of the default display device, probably the one that p5 was
|
||||
* started from.
|
||||
*/
|
||||
static int defaultIndex;
|
||||
|
||||
/**
|
||||
* Menu object for preferences window
|
||||
*/
|
||||
//JMenu preferencesMenu;
|
||||
static JComboBox selector;
|
||||
|
||||
/**
|
||||
* Index of the currently selected display to be used for present mode.
|
||||
*/
|
||||
static GraphicsDevice device;
|
||||
|
||||
|
||||
static {
|
||||
GraphicsEnvironment environment =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
devices = environment.getScreenDevices();
|
||||
GraphicsDevice defaultDevice = environment.getDefaultScreenDevice();
|
||||
|
||||
Vector names = new Vector();
|
||||
for (int i = 0; i < devices.length; i++) {
|
||||
String name = String.valueOf(i + 1);
|
||||
if (devices[i] == defaultDevice) {
|
||||
defaultIndex = i;
|
||||
name += " (default)";
|
||||
}
|
||||
names.add(name);
|
||||
}
|
||||
|
||||
selector = new JComboBox(names);
|
||||
selector.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int index = selector.getSelectedIndex();
|
||||
//device = devices[index];
|
||||
Preferences.setInteger("run.present.display", index + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static public JComboBox getSelector() {
|
||||
int deviceIndex = Preferences.getInteger("run.present.display") - 1;
|
||||
selector.setSelectedIndex(deviceIndex);
|
||||
return selector;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static public JFrame create() {
|
||||
int deviceIndex = PrePreferences.getInteger("run.present.display") - 1;
|
||||
if ((deviceIndex < 0) || (deviceIndex >= devices.length)) {
|
||||
Base.showWarning("Display doesn't exist",
|
||||
"Present Mode is set to use display " +
|
||||
(deviceIndex+1) +
|
||||
" but that doesn't seem to exist. \n" +
|
||||
"This preference will be reset to " +
|
||||
"use the default display.", null);
|
||||
deviceIndex = defaultIndex;
|
||||
}
|
||||
//GraphicsDevice device = devices[
|
||||
//JFrame frame = new JFrame(devices[deviceIndex]);
|
||||
PresentFrame frame = new PresentFrame(devices[deviceIndex]);
|
||||
}
|
||||
|
||||
|
||||
public void show() {
|
||||
setUndecorated(true);
|
||||
setResizable(false);
|
||||
device.setFullScreenWindow(this);
|
||||
}
|
||||
|
||||
|
||||
public Window getWindow() {
|
||||
return device.getFullScreenWindow(); // isn't this just me?
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
Window window = device.getFullScreenWindow();
|
||||
if (window != null) {
|
||||
window.dispose();
|
||||
}
|
||||
device.setFullScreenWindow(null);
|
||||
}
|
||||
*/
|
||||
}
|
3004
app/src/processing/app/Sketch.java
Normal file
3004
app/src/processing/app/Sketch.java
Normal file
File diff suppressed because it is too large
Load Diff
285
app/src/processing/app/SketchCode.java
Normal file
285
app/src/processing/app/SketchCode.java
Normal file
@ -0,0 +1,285 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
SketchCode - data class for a single file inside a sketch
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.undo.*;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a single tab of a sketch.
|
||||
*/
|
||||
public class SketchCode {
|
||||
/** Pretty name (no extension), not the full file name */
|
||||
private String prettyName;
|
||||
|
||||
/** File object for where this code is located */
|
||||
private File file;
|
||||
|
||||
/** Extension for this file (no dots, and in lowercase). */
|
||||
private String extension;
|
||||
|
||||
/** Text of the program text for this tab */
|
||||
private String program;
|
||||
|
||||
/** Document object for this tab. Currently this is a SyntaxDocument. */
|
||||
private Document document;
|
||||
|
||||
/**
|
||||
* Undo Manager for this tab, each tab keeps track of their own
|
||||
* Editor.undo will be set to this object when this code is the tab
|
||||
* that's currently the front.
|
||||
*/
|
||||
private UndoManager undo = new UndoManager();
|
||||
|
||||
// saved positions from last time this tab was used
|
||||
private int selectionStart;
|
||||
private int selectionStop;
|
||||
private int scrollPosition;
|
||||
|
||||
private boolean modified;
|
||||
|
||||
/** name of .java file after preproc */
|
||||
// private String preprocName;
|
||||
/** where this code starts relative to the concat'd code */
|
||||
private int preprocOffset;
|
||||
|
||||
|
||||
public SketchCode(File file, String extension) {
|
||||
this.file = file;
|
||||
this.extension = extension;
|
||||
|
||||
makePrettyName();
|
||||
|
||||
try {
|
||||
load();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error while loading code " + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void makePrettyName() {
|
||||
prettyName = file.getName();
|
||||
int dot = prettyName.indexOf('.');
|
||||
prettyName = prettyName.substring(0, dot);
|
||||
}
|
||||
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
protected boolean fileExists() {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
|
||||
protected boolean fileReadOnly() {
|
||||
return !file.canWrite();
|
||||
}
|
||||
|
||||
|
||||
protected boolean deleteFile() {
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
|
||||
protected boolean renameTo(File what, String ext) {
|
||||
boolean success = file.renameTo(what);
|
||||
if (success) {
|
||||
this.file = what; // necessary?
|
||||
this.extension = ext;
|
||||
makePrettyName();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
protected void copyTo(File dest) throws IOException {
|
||||
Base.saveFile(program, dest);
|
||||
}
|
||||
|
||||
|
||||
public String getFileName() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
|
||||
public String getPrettyName() {
|
||||
return prettyName;
|
||||
}
|
||||
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
|
||||
public boolean isExtension(String what) {
|
||||
return extension.equals(what);
|
||||
}
|
||||
|
||||
|
||||
public String getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
|
||||
public void setProgram(String replacement) {
|
||||
program = replacement;
|
||||
}
|
||||
|
||||
|
||||
public int getLineCount() {
|
||||
return Base.countLines(program);
|
||||
}
|
||||
|
||||
|
||||
public void setModified(boolean modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
public boolean isModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
||||
// public void setPreprocName(String preprocName) {
|
||||
// this.preprocName = preprocName;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public String getPreprocName() {
|
||||
// return preprocName;
|
||||
// }
|
||||
|
||||
|
||||
public void setPreprocOffset(int preprocOffset) {
|
||||
this.preprocOffset = preprocOffset;
|
||||
}
|
||||
|
||||
|
||||
public int getPreprocOffset() {
|
||||
return preprocOffset;
|
||||
}
|
||||
|
||||
|
||||
public void addPreprocOffset(int extra) {
|
||||
preprocOffset += extra;
|
||||
}
|
||||
|
||||
|
||||
public Document getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
|
||||
public void setDocument(Document d) {
|
||||
document = d;
|
||||
}
|
||||
|
||||
|
||||
public UndoManager getUndo() {
|
||||
return undo;
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// TODO these could probably be handled better, since it's a general state
|
||||
// issue that's read/write from only one location in Editor (on tab switch.)
|
||||
|
||||
|
||||
public int getSelectionStart() {
|
||||
return selectionStart;
|
||||
}
|
||||
|
||||
|
||||
public int getSelectionStop() {
|
||||
return selectionStop;
|
||||
}
|
||||
|
||||
|
||||
public int getScrollPosition() {
|
||||
return scrollPosition;
|
||||
}
|
||||
|
||||
|
||||
protected void setState(String p, int start, int stop, int pos) {
|
||||
program = p;
|
||||
selectionStart = start;
|
||||
selectionStop = stop;
|
||||
scrollPosition = pos;
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
/**
|
||||
* Load this piece of code from a file.
|
||||
*/
|
||||
public void load() throws IOException {
|
||||
program = Base.loadFile(file);
|
||||
|
||||
if (program.indexOf('\uFFFD') != -1) {
|
||||
System.err.println(file.getName() + " contains unrecognized characters.");
|
||||
System.err.println("If this code was created with an older version of Processing,");
|
||||
System.err.println("you may need to use Tools -> Fix Encoding & Reload to update");
|
||||
System.err.println("the sketch to use UTF-8 encoding. If not, you may need to");
|
||||
System.err.println("delete the bad characters to get rid of this warning.");
|
||||
System.err.println();
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save this piece of code, regardless of whether the modified
|
||||
* flag is set or not.
|
||||
*/
|
||||
public void save() throws IOException {
|
||||
// TODO re-enable history
|
||||
//history.record(s, SketchHistory.SAVE);
|
||||
|
||||
Base.saveFile(program, file);
|
||||
setModified(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save this file to another location, used by Sketch.saveAs()
|
||||
*/
|
||||
public void saveAs(File newFile) throws IOException {
|
||||
Base.saveFile(program, newFile);
|
||||
}
|
||||
}
|
208
app/src/processing/app/Theme.java
Normal file
208
app/src/processing/app/Theme.java
Normal file
@ -0,0 +1,208 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import processing.app.syntax.*;
|
||||
import processing.core.*;
|
||||
|
||||
|
||||
/**
|
||||
* Storage class for theme settings. This was separated from the Preferences
|
||||
* class for 1.0 so that the coloring wouldn't conflict with previous releases
|
||||
* and to make way for future ability to customize.
|
||||
*/
|
||||
public class Theme {
|
||||
|
||||
/** Copy of the defaults in case the user mangles a preference. */
|
||||
static Hashtable defaults;
|
||||
/** Table of attributes/values for the theme. */
|
||||
static Hashtable table = new Hashtable();;
|
||||
|
||||
|
||||
static protected void init() {
|
||||
try {
|
||||
load(Base.getLibStream("theme/theme.txt"));
|
||||
} catch (Exception te) {
|
||||
Base.showError(null, "Could not read color theme settings.\n" +
|
||||
"You'll need to reinstall Processing.", te);
|
||||
}
|
||||
|
||||
// check for platform-specific properties in the defaults
|
||||
String platformExt = "." + Base.getPlatformName();
|
||||
int platformExtLength = platformExt.length();
|
||||
Enumeration e = table.keys();
|
||||
while (e.hasMoreElements()) {
|
||||
String key = (String) e.nextElement();
|
||||
if (key.endsWith(platformExt)) {
|
||||
// this is a key specific to a particular platform
|
||||
String actualKey = key.substring(0, key.length() - platformExtLength);
|
||||
String value = get(key);
|
||||
table.put(actualKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
// other things that have to be set explicitly for the defaults
|
||||
setColor("run.window.bgcolor", SystemColor.control);
|
||||
|
||||
// clone the hash table
|
||||
defaults = (Hashtable) table.clone();
|
||||
}
|
||||
|
||||
|
||||
static protected void load(InputStream input) throws IOException {
|
||||
String[] lines = PApplet.loadStrings(input);
|
||||
for (String line : lines) {
|
||||
if ((line.length() == 0) ||
|
||||
(line.charAt(0) == '#')) continue;
|
||||
|
||||
// this won't properly handle = signs being in the text
|
||||
int equals = line.indexOf('=');
|
||||
if (equals != -1) {
|
||||
String key = line.substring(0, equals).trim();
|
||||
String value = line.substring(equals + 1).trim();
|
||||
table.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public String get(String attribute) {
|
||||
return (String) table.get(attribute);
|
||||
}
|
||||
|
||||
|
||||
static public String getDefault(String attribute) {
|
||||
return (String) defaults.get(attribute);
|
||||
}
|
||||
|
||||
|
||||
static public void set(String attribute, String value) {
|
||||
table.put(attribute, value);
|
||||
}
|
||||
|
||||
|
||||
static public boolean getBoolean(String attribute) {
|
||||
String value = get(attribute);
|
||||
return (new Boolean(value)).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
static public void setBoolean(String attribute, boolean value) {
|
||||
set(attribute, value ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
static public int getInteger(String attribute) {
|
||||
return Integer.parseInt(get(attribute));
|
||||
}
|
||||
|
||||
|
||||
static public void setInteger(String key, int value) {
|
||||
set(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
|
||||
static public Color getColor(String name) {
|
||||
Color parsed = null;
|
||||
String s = get(name);
|
||||
if ((s != null) && (s.indexOf("#") == 0)) {
|
||||
try {
|
||||
int v = Integer.parseInt(s.substring(1), 16);
|
||||
parsed = new Color(v);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
|
||||
static public void setColor(String attr, Color what) {
|
||||
String r = Integer.toHexString(what.getRed());
|
||||
String g = Integer.toHexString(what.getGreen());
|
||||
String b = Integer.toHexString(what.getBlue());
|
||||
set(attr, "#" + r.substring(r.length() - 2) +
|
||||
g.substring(g.length() - 2) + b.substring(b.length() - 2));
|
||||
}
|
||||
|
||||
|
||||
static public Font getFont(String attr) {
|
||||
boolean replace = false;
|
||||
String value = get(attr);
|
||||
if (value == null) {
|
||||
//System.out.println("reset 1");
|
||||
value = getDefault(attr);
|
||||
replace = true;
|
||||
}
|
||||
|
||||
String[] pieces = PApplet.split(value, ',');
|
||||
if (pieces.length != 3) {
|
||||
value = getDefault(attr);
|
||||
//System.out.println("reset 2 for " + attr);
|
||||
pieces = PApplet.split(value, ',');
|
||||
//PApplet.println(pieces);
|
||||
replace = true;
|
||||
}
|
||||
|
||||
String name = pieces[0];
|
||||
int style = Font.PLAIN; // equals zero
|
||||
if (pieces[1].indexOf("bold") != -1) {
|
||||
style |= Font.BOLD;
|
||||
}
|
||||
if (pieces[1].indexOf("italic") != -1) {
|
||||
style |= Font.ITALIC;
|
||||
}
|
||||
int size = PApplet.parseInt(pieces[2], 12);
|
||||
Font font = new Font(name, style, size);
|
||||
|
||||
// replace bad font with the default
|
||||
if (replace) {
|
||||
//System.out.println(attr + " > " + value);
|
||||
//setString(attr, font.getName() + ",plain," + font.getSize());
|
||||
set(attr, value);
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
static public SyntaxStyle getStyle(String what) {
|
||||
String str = get("editor." + what + ".style");
|
||||
|
||||
StringTokenizer st = new StringTokenizer(str, ",");
|
||||
|
||||
String s = st.nextToken();
|
||||
if (s.indexOf("#") == 0) s = s.substring(1);
|
||||
Color color = new Color(Integer.parseInt(s, 16));
|
||||
|
||||
s = st.nextToken();
|
||||
boolean bold = (s.indexOf("bold") != -1);
|
||||
boolean italic = (s.indexOf("italic") != -1);
|
||||
|
||||
return new SyntaxStyle(color, italic, bold);
|
||||
}
|
||||
}
|
134
app/src/processing/app/UpdateCheck.java
Normal file
134
app/src/processing/app/UpdateCheck.java
Normal file
@ -0,0 +1,134 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2005-06 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
/**
|
||||
* Threaded class to check for updates in the background.
|
||||
* <P>
|
||||
* This is the class that handles the mind control and stuff for
|
||||
* spying on our users and stealing their personal information.
|
||||
* A random ID number is generated for each user, and hits the server
|
||||
* to check for updates. Also included is the operating system and
|
||||
* its version and the version of Java being used to run Processing.
|
||||
* <P>
|
||||
* The ID number also helps provide us a general idea of how many
|
||||
* people are using Processing, which helps us when writing grant
|
||||
* proposals and that kind of thing so that we can keep Processing free.
|
||||
*/
|
||||
public class UpdateCheck implements Runnable {
|
||||
Base base;
|
||||
String downloadURL = "http://processing.org/download/latest.txt";
|
||||
|
||||
static final long ONE_DAY = 24 * 60 * 60 * 1000;
|
||||
|
||||
|
||||
public UpdateCheck(Base base) {
|
||||
Thread thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
//System.out.println("checking for updates...");
|
||||
|
||||
// generate a random id in case none exists yet
|
||||
Random r = new Random();
|
||||
long id = r.nextLong();
|
||||
|
||||
String idString = Preferences.get("update.id");
|
||||
if (idString != null) {
|
||||
id = Long.parseLong(idString);
|
||||
} else {
|
||||
Preferences.set("update.id", String.valueOf(id));
|
||||
}
|
||||
|
||||
try {
|
||||
String info;
|
||||
info = URLEncoder.encode(id + "\t" +
|
||||
PApplet.nf(Base.REVISION, 4) + "\t" +
|
||||
System.getProperty("java.version") + "\t" +
|
||||
System.getProperty("java.vendor") + "\t" +
|
||||
System.getProperty("os.name") + "\t" +
|
||||
System.getProperty("os.version") + "\t" +
|
||||
System.getProperty("os.arch"), "UTF-8");
|
||||
|
||||
int latest = readInt(downloadURL + "?" + info);
|
||||
|
||||
String lastString = Preferences.get("update.last");
|
||||
long now = System.currentTimeMillis();
|
||||
if (lastString != null) {
|
||||
long when = Long.parseLong(lastString);
|
||||
if (now - when < ONE_DAY) {
|
||||
// don't annoy the shit outta people
|
||||
return;
|
||||
}
|
||||
}
|
||||
Preferences.set("update.last", String.valueOf(now));
|
||||
|
||||
String prompt =
|
||||
"A new version of Processing is available,\n" +
|
||||
"would you like to visit the Processing download page?";
|
||||
|
||||
if (base.activeEditor != null) {
|
||||
if (latest > Base.REVISION) {
|
||||
Object[] options = { "Yes", "No" };
|
||||
int result = JOptionPane.showOptionDialog(base.activeEditor,
|
||||
prompt,
|
||||
"Update",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE,
|
||||
null,
|
||||
options,
|
||||
options[0]);
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
Base.openURL("http://processing.org/download/");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
//System.err.println("Error while trying to check for an update.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int readInt(String filename) throws Exception {
|
||||
URL url = new URL(filename);
|
||||
InputStream stream = url.openStream();
|
||||
InputStreamReader isr = new InputStreamReader(stream);
|
||||
BufferedReader reader = new BufferedReader(isr);
|
||||
return Integer.parseInt(reader.readLine());
|
||||
}
|
||||
}
|
569
app/src/processing/app/WebServer.java
Normal file
569
app/src/processing/app/WebServer.java
Normal file
@ -0,0 +1,569 @@
|
||||
package processing.app;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
//import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* An example of a very simple, multi-threaded HTTP server.
|
||||
* Taken from <a href="http://java.sun.com/developer/technicalArticles/Networking/Webserver/">this</a> article on java.sun.com.
|
||||
*/
|
||||
public class WebServer implements HttpConstants {
|
||||
|
||||
/* Where worker threads stand idle */
|
||||
static Vector threads = new Vector();
|
||||
|
||||
/* the web server's virtual root */
|
||||
//static File root;
|
||||
|
||||
/* timeout on client connections */
|
||||
static int timeout = 10000;
|
||||
|
||||
/* max # worker threads */
|
||||
static int workers = 5;
|
||||
|
||||
// static PrintStream log = System.out;
|
||||
|
||||
|
||||
/*
|
||||
static void loadProps() throws IOException {
|
||||
File f = new File
|
||||
(System.getProperty("java.home")+File.separator+
|
||||
"lib"+File.separator+"www-server.properties");
|
||||
if (f.exists()) {
|
||||
InputStream is =new BufferedInputStream(new
|
||||
FileInputStream(f));
|
||||
props.load(is);
|
||||
is.close();
|
||||
String r = props.getProperty("root");
|
||||
if (r != null) {
|
||||
root = new File(r);
|
||||
if (!root.exists()) {
|
||||
throw new Error(root + " doesn't exist as server root");
|
||||
}
|
||||
}
|
||||
r = props.getProperty("timeout");
|
||||
if (r != null) {
|
||||
timeout = Integer.parseInt(r);
|
||||
}
|
||||
r = props.getProperty("workers");
|
||||
if (r != null) {
|
||||
workers = Integer.parseInt(r);
|
||||
}
|
||||
r = props.getProperty("log");
|
||||
if (r != null) {
|
||||
p("opening log file: " + r);
|
||||
log = new PrintStream(new BufferedOutputStream(
|
||||
new FileOutputStream(r)));
|
||||
}
|
||||
}
|
||||
|
||||
// if no properties were specified, choose defaults
|
||||
if (root == null) {
|
||||
root = new File(System.getProperty("user.dir"));
|
||||
}
|
||||
if (timeout <= 1000) {
|
||||
timeout = 5000;
|
||||
}
|
||||
if (workers < 25) {
|
||||
workers = 5;
|
||||
}
|
||||
if (log == null) {
|
||||
p("logging to stdout");
|
||||
log = System.out;
|
||||
}
|
||||
}
|
||||
|
||||
static void printProps() {
|
||||
p("root="+root);
|
||||
p("timeout="+timeout);
|
||||
p("workers="+workers);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* print to stdout */
|
||||
// protected static void p(String s) {
|
||||
// System.out.println(s);
|
||||
// }
|
||||
|
||||
/* print to the log file */
|
||||
protected static void log(String s) {
|
||||
if (false) {
|
||||
System.out.println(s);
|
||||
}
|
||||
// synchronized (log) {
|
||||
// log.println(s);
|
||||
// log.flush();
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
//public static void main(String[] a) throws Exception {
|
||||
static public int launch(String zipPath) throws IOException {
|
||||
final ZipFile zip = new ZipFile(zipPath);
|
||||
final HashMap<String, ZipEntry> entries = new HashMap();
|
||||
Enumeration en = zip.entries();
|
||||
while (en.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) en.nextElement();
|
||||
entries.put(entry.getName(), entry);
|
||||
}
|
||||
|
||||
// if (a.length > 0) {
|
||||
// port = Integer.parseInt(a[0]);
|
||||
// }
|
||||
// loadProps();
|
||||
// printProps();
|
||||
// start worker threads
|
||||
for (int i = 0; i < workers; ++i) {
|
||||
WebServerWorker w = new WebServerWorker(zip, entries);
|
||||
Thread t = new Thread(w, "Web Server Worker #" + i);
|
||||
t.start();
|
||||
threads.addElement(w);
|
||||
}
|
||||
|
||||
final int port = 8080;
|
||||
|
||||
//SwingUtilities.invokeLater(new Runnable() {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket ss = new ServerSocket(port);
|
||||
while (true) {
|
||||
Socket s = ss.accept();
|
||||
WebServerWorker w = null;
|
||||
synchronized (threads) {
|
||||
if (threads.isEmpty()) {
|
||||
WebServerWorker ws = new WebServerWorker(zip, entries);
|
||||
ws.setSocket(s);
|
||||
(new Thread(ws, "additional worker")).start();
|
||||
} else {
|
||||
w = (WebServerWorker) threads.elementAt(0);
|
||||
threads.removeElementAt(0);
|
||||
w.setSocket(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
new Thread(r).start();
|
||||
// });
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WebServerWorker /*extends WebServer*/ implements HttpConstants, Runnable {
|
||||
ZipFile zip;
|
||||
HashMap<String, ZipEntry> entries;
|
||||
|
||||
final static int BUF_SIZE = 2048;
|
||||
|
||||
static final byte[] EOL = { (byte)'\r', (byte)'\n' };
|
||||
|
||||
/* buffer to use for requests */
|
||||
byte[] buf;
|
||||
/* Socket to client we're handling */
|
||||
private Socket s;
|
||||
|
||||
WebServerWorker(ZipFile zip, HashMap entries) {
|
||||
this.entries = entries;
|
||||
this.zip = zip;
|
||||
|
||||
buf = new byte[BUF_SIZE];
|
||||
s = null;
|
||||
}
|
||||
|
||||
// Worker() {
|
||||
// buf = new byte[BUF_SIZE];
|
||||
// s = null;
|
||||
// }
|
||||
//
|
||||
synchronized void setSocket(Socket s) {
|
||||
this.s = s;
|
||||
notify();
|
||||
}
|
||||
|
||||
public synchronized void run() {
|
||||
while(true) {
|
||||
if (s == null) {
|
||||
/* nothing to do */
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
/* should not happen */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
handleClient();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/* go back in wait queue if there's fewer
|
||||
* than numHandler connections.
|
||||
*/
|
||||
s = null;
|
||||
Vector pool = WebServer.threads;
|
||||
synchronized (pool) {
|
||||
if (pool.size() >= WebServer.workers) {
|
||||
/* too many threads, exit this one */
|
||||
return;
|
||||
} else {
|
||||
pool.addElement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleClient() throws IOException {
|
||||
InputStream is = new BufferedInputStream(s.getInputStream());
|
||||
PrintStream ps = new PrintStream(s.getOutputStream());
|
||||
// we will only block in read for this many milliseconds
|
||||
// before we fail with java.io.InterruptedIOException,
|
||||
// at which point we will abandon the connection.
|
||||
s.setSoTimeout(WebServer.timeout);
|
||||
s.setTcpNoDelay(true);
|
||||
// zero out the buffer from last time
|
||||
for (int i = 0; i < BUF_SIZE; i++) {
|
||||
buf[i] = 0;
|
||||
}
|
||||
try {
|
||||
// We only support HTTP GET/HEAD, and don't support any fancy HTTP
|
||||
// options, so we're only interested really in the first line.
|
||||
int nread = 0, r = 0;
|
||||
|
||||
outerloop:
|
||||
while (nread < BUF_SIZE) {
|
||||
r = is.read(buf, nread, BUF_SIZE - nread);
|
||||
if (r == -1) {
|
||||
return; // EOF
|
||||
}
|
||||
int i = nread;
|
||||
nread += r;
|
||||
for (; i < nread; i++) {
|
||||
if (buf[i] == (byte)'\n' || buf[i] == (byte)'\r') {
|
||||
break outerloop; // read one line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* are we doing a GET or just a HEAD */
|
||||
boolean doingGet;
|
||||
/* beginning of file name */
|
||||
int index;
|
||||
if (buf[0] == (byte)'G' &&
|
||||
buf[1] == (byte)'E' &&
|
||||
buf[2] == (byte)'T' &&
|
||||
buf[3] == (byte)' ') {
|
||||
doingGet = true;
|
||||
index = 4;
|
||||
} else if (buf[0] == (byte)'H' &&
|
||||
buf[1] == (byte)'E' &&
|
||||
buf[2] == (byte)'A' &&
|
||||
buf[3] == (byte)'D' &&
|
||||
buf[4] == (byte)' ') {
|
||||
doingGet = false;
|
||||
index = 5;
|
||||
} else {
|
||||
/* we don't support this method */
|
||||
ps.print("HTTP/1.0 " + HTTP_BAD_METHOD +
|
||||
" unsupported method type: ");
|
||||
ps.write(buf, 0, 5);
|
||||
ps.write(EOL);
|
||||
ps.flush();
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
/* find the file name, from:
|
||||
* GET /foo/bar.html HTTP/1.0
|
||||
* extract "/foo/bar.html"
|
||||
*/
|
||||
for (i = index; i < nread; i++) {
|
||||
if (buf[i] == (byte)' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String fname = new String(buf, index, i-index);
|
||||
// get the zip entry, remove the front slash
|
||||
ZipEntry entry = entries.get(fname.substring(1));
|
||||
//System.out.println(fname + " " + entry);
|
||||
boolean ok = printHeaders(entry, ps);
|
||||
if (entry != null) {
|
||||
InputStream stream = zip.getInputStream(entry);
|
||||
if (doingGet && ok) {
|
||||
sendFile(stream, ps);
|
||||
}
|
||||
} else {
|
||||
send404(ps);
|
||||
}
|
||||
/*
|
||||
String fname =
|
||||
(new String(buf, 0, index, i-index)).replace('/', File.separatorChar);
|
||||
if (fname.startsWith(File.separator)) {
|
||||
fname = fname.substring(1);
|
||||
}
|
||||
File targ = new File(WebServer.root, fname);
|
||||
if (targ.isDirectory()) {
|
||||
File ind = new File(targ, "index.html");
|
||||
if (ind.exists()) {
|
||||
targ = ind;
|
||||
}
|
||||
}
|
||||
boolean OK = printHeaders(targ, ps);
|
||||
if (doingGet) {
|
||||
if (OK) {
|
||||
sendFile(targ, ps);
|
||||
} else {
|
||||
send404(targ, ps);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} finally {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean printHeaders(ZipEntry targ, PrintStream ps) throws IOException {
|
||||
boolean ret = false;
|
||||
int rCode = 0;
|
||||
if (targ == null) {
|
||||
rCode = HTTP_NOT_FOUND;
|
||||
ps.print("HTTP/1.0 " + HTTP_NOT_FOUND + " Not Found");
|
||||
ps.write(EOL);
|
||||
ret = false;
|
||||
} else {
|
||||
rCode = HTTP_OK;
|
||||
ps.print("HTTP/1.0 " + HTTP_OK + " OK");
|
||||
ps.write(EOL);
|
||||
ret = true;
|
||||
}
|
||||
if (targ != null) {
|
||||
WebServer.log("From " +s.getInetAddress().getHostAddress()+": GET " + targ.getName()+" --> "+rCode);
|
||||
}
|
||||
ps.print("Server: Processing Documentation Server");
|
||||
ps.write(EOL);
|
||||
ps.print("Date: " + (new Date()));
|
||||
ps.write(EOL);
|
||||
if (ret) {
|
||||
if (!targ.isDirectory()) {
|
||||
ps.print("Content-length: " + targ.getSize());
|
||||
ps.write(EOL);
|
||||
ps.print("Last Modified: " + new Date(targ.getTime()));
|
||||
ps.write(EOL);
|
||||
String name = targ.getName();
|
||||
int ind = name.lastIndexOf('.');
|
||||
String ct = null;
|
||||
if (ind > 0) {
|
||||
ct = (String) map.get(name.substring(ind));
|
||||
}
|
||||
if (ct == null) {
|
||||
//System.err.println("unknown content type " + name.substring(ind));
|
||||
ct = "application/x-unknown-content-type";
|
||||
}
|
||||
ps.print("Content-type: " + ct);
|
||||
ps.write(EOL);
|
||||
} else {
|
||||
ps.print("Content-type: text/html");
|
||||
ps.write(EOL);
|
||||
}
|
||||
}
|
||||
ps.write(EOL); // adding another newline here [fry]
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
boolean printHeaders(File targ, PrintStream ps) throws IOException {
|
||||
boolean ret = false;
|
||||
int rCode = 0;
|
||||
if (!targ.exists()) {
|
||||
rCode = HTTP_NOT_FOUND;
|
||||
ps.print("HTTP/1.0 " + HTTP_NOT_FOUND + " Not Found");
|
||||
ps.write(EOL);
|
||||
ret = false;
|
||||
} else {
|
||||
rCode = HTTP_OK;
|
||||
ps.print("HTTP/1.0 " + HTTP_OK+" OK");
|
||||
ps.write(EOL);
|
||||
ret = true;
|
||||
}
|
||||
WebServer.log("From " +s.getInetAddress().getHostAddress()+": GET " + targ.getAbsolutePath()+"-->"+rCode);
|
||||
ps.print("Server: Simple java");
|
||||
ps.write(EOL);
|
||||
ps.print("Date: " + (new Date()));
|
||||
ps.write(EOL);
|
||||
if (ret) {
|
||||
if (!targ.isDirectory()) {
|
||||
ps.print("Content-length: " + targ.length());
|
||||
ps.write(EOL);
|
||||
ps.print("Last Modified: " + new Date(targ.lastModified()));
|
||||
ps.write(EOL);
|
||||
String name = targ.getName();
|
||||
int ind = name.lastIndexOf('.');
|
||||
String ct = null;
|
||||
if (ind > 0) {
|
||||
ct = (String) map.get(name.substring(ind));
|
||||
}
|
||||
if (ct == null) {
|
||||
ct = "unknown/unknown";
|
||||
}
|
||||
ps.print("Content-type: " + ct);
|
||||
ps.write(EOL);
|
||||
} else {
|
||||
ps.print("Content-type: text/html");
|
||||
ps.write(EOL);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void send404(PrintStream ps) throws IOException {
|
||||
ps.write(EOL);
|
||||
ps.write(EOL);
|
||||
ps.print("<html><body><h1>404 Not Found</h1>"+
|
||||
"The requested resource was not found.</body></html>");
|
||||
ps.write(EOL);
|
||||
ps.write(EOL);
|
||||
}
|
||||
|
||||
|
||||
void sendFile(File targ, PrintStream ps) throws IOException {
|
||||
InputStream is = null;
|
||||
ps.write(EOL);
|
||||
if (targ.isDirectory()) {
|
||||
listDirectory(targ, ps);
|
||||
return;
|
||||
} else {
|
||||
is = new FileInputStream(targ.getAbsolutePath());
|
||||
}
|
||||
sendFile(is, ps);
|
||||
}
|
||||
|
||||
|
||||
void sendFile(InputStream is, PrintStream ps) throws IOException {
|
||||
try {
|
||||
int n;
|
||||
while ((n = is.read(buf)) > 0) {
|
||||
ps.write(buf, 0, n);
|
||||
}
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
/* mapping of file extensions to content-types */
|
||||
static java.util.Hashtable map = new java.util.Hashtable();
|
||||
|
||||
static {
|
||||
fillMap();
|
||||
}
|
||||
static void setSuffix(String k, String v) {
|
||||
map.put(k, v);
|
||||
}
|
||||
|
||||
static void fillMap() {
|
||||
setSuffix("", "content/unknown");
|
||||
|
||||
setSuffix(".uu", "application/octet-stream");
|
||||
setSuffix(".exe", "application/octet-stream");
|
||||
setSuffix(".ps", "application/postscript");
|
||||
setSuffix(".zip", "application/zip");
|
||||
setSuffix(".sh", "application/x-shar");
|
||||
setSuffix(".tar", "application/x-tar");
|
||||
setSuffix(".snd", "audio/basic");
|
||||
setSuffix(".au", "audio/basic");
|
||||
setSuffix(".wav", "audio/x-wav");
|
||||
|
||||
setSuffix(".gif", "image/gif");
|
||||
setSuffix(".jpg", "image/jpeg");
|
||||
setSuffix(".jpeg", "image/jpeg");
|
||||
|
||||
setSuffix(".htm", "text/html");
|
||||
setSuffix(".html", "text/html");
|
||||
setSuffix(".css", "text/css");
|
||||
setSuffix(".java", "text/javascript");
|
||||
|
||||
setSuffix(".txt", "text/plain");
|
||||
setSuffix(".java", "text/plain");
|
||||
|
||||
setSuffix(".c", "text/plain");
|
||||
setSuffix(".cc", "text/plain");
|
||||
setSuffix(".c++", "text/plain");
|
||||
setSuffix(".h", "text/plain");
|
||||
setSuffix(".pl", "text/plain");
|
||||
}
|
||||
|
||||
void listDirectory(File dir, PrintStream ps) throws IOException {
|
||||
ps.println("<TITLE>Directory listing</TITLE><P>\n");
|
||||
ps.println("<A HREF=\"..\">Parent Directory</A><BR>\n");
|
||||
String[] list = dir.list();
|
||||
for (int i = 0; list != null && i < list.length; i++) {
|
||||
File f = new File(dir, list[i]);
|
||||
if (f.isDirectory()) {
|
||||
ps.println("<A HREF=\""+list[i]+"/\">"+list[i]+"/</A><BR>");
|
||||
} else {
|
||||
ps.println("<A HREF=\""+list[i]+"\">"+list[i]+"</A><BR");
|
||||
}
|
||||
}
|
||||
ps.println("<P><HR><BR><I>" + (new Date()) + "</I>");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
interface HttpConstants {
|
||||
/** 2XX: generally "OK" */
|
||||
public static final int HTTP_OK = 200;
|
||||
public static final int HTTP_CREATED = 201;
|
||||
public static final int HTTP_ACCEPTED = 202;
|
||||
public static final int HTTP_NOT_AUTHORITATIVE = 203;
|
||||
public static final int HTTP_NO_CONTENT = 204;
|
||||
public static final int HTTP_RESET = 205;
|
||||
public static final int HTTP_PARTIAL = 206;
|
||||
|
||||
/** 3XX: relocation/redirect */
|
||||
public static final int HTTP_MULT_CHOICE = 300;
|
||||
public static final int HTTP_MOVED_PERM = 301;
|
||||
public static final int HTTP_MOVED_TEMP = 302;
|
||||
public static final int HTTP_SEE_OTHER = 303;
|
||||
public static final int HTTP_NOT_MODIFIED = 304;
|
||||
public static final int HTTP_USE_PROXY = 305;
|
||||
|
||||
/** 4XX: client error */
|
||||
public static final int HTTP_BAD_REQUEST = 400;
|
||||
public static final int HTTP_UNAUTHORIZED = 401;
|
||||
public static final int HTTP_PAYMENT_REQUIRED = 402;
|
||||
public static final int HTTP_FORBIDDEN = 403;
|
||||
public static final int HTTP_NOT_FOUND = 404;
|
||||
public static final int HTTP_BAD_METHOD = 405;
|
||||
public static final int HTTP_NOT_ACCEPTABLE = 406;
|
||||
public static final int HTTP_PROXY_AUTH = 407;
|
||||
public static final int HTTP_CLIENT_TIMEOUT = 408;
|
||||
public static final int HTTP_CONFLICT = 409;
|
||||
public static final int HTTP_GONE = 410;
|
||||
public static final int HTTP_LENGTH_REQUIRED = 411;
|
||||
public static final int HTTP_PRECON_FAILED = 412;
|
||||
public static final int HTTP_ENTITY_TOO_LARGE = 413;
|
||||
public static final int HTTP_REQ_TOO_LONG = 414;
|
||||
public static final int HTTP_UNSUPPORTED_TYPE = 415;
|
||||
|
||||
/** 5XX: server error */
|
||||
public static final int HTTP_SERVER_ERROR = 500;
|
||||
public static final int HTTP_INTERNAL_ERROR = 501;
|
||||
public static final int HTTP_BAD_GATEWAY = 502;
|
||||
public static final int HTTP_UNAVAILABLE = 503;
|
||||
public static final int HTTP_GATEWAY_TIMEOUT = 504;
|
||||
public static final int HTTP_VERSION = 505;
|
||||
}
|
828
app/src/processing/app/debug/Compiler.java
Normal file
828
app/src/processing/app/debug/Compiler.java
Normal file
@ -0,0 +1,828 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Sketch;
|
||||
import processing.app.SketchCode;
|
||||
import processing.core.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
|
||||
import org.eclipse.jdt.core.compiler.CompilationProgress;
|
||||
|
||||
|
||||
public class Compiler {
|
||||
|
||||
public Compiler() { }
|
||||
|
||||
/**
|
||||
* Compile with ECJ.
|
||||
*
|
||||
* @param sketch Sketch object to be compiled.
|
||||
* @param buildPath Where the temporary files live and will be built from.
|
||||
* @return true if successful.
|
||||
* @throws RunnerException Only if there's a problem. Only then.
|
||||
*/
|
||||
public boolean compile(Sketch sketch,
|
||||
String buildPath,
|
||||
String primaryClassName) throws RunnerException {
|
||||
// This will be filled in if anyone gets angry
|
||||
RunnerException exception = null;
|
||||
boolean success = false;
|
||||
|
||||
String baseCommand[] = new String[] {
|
||||
"-Xemacs",
|
||||
//"-noExit", // not necessary for ecj
|
||||
"-source", "1.5",
|
||||
"-target", "1.5",
|
||||
"-classpath", sketch.getClassPath(),
|
||||
"-nowarn", // we're not currently interested in warnings (works in ecj)
|
||||
"-d", buildPath // output the classes in the buildPath
|
||||
};
|
||||
//PApplet.println(baseCommand);
|
||||
|
||||
// make list of code files that need to be compiled
|
||||
// (some files are skipped if they contain no class)
|
||||
String[] sourceFiles = new String[sketch.getCodeCount()];
|
||||
int sourceCount = 0;
|
||||
sourceFiles[sourceCount++] =
|
||||
new File(buildPath, primaryClassName + ".java").getAbsolutePath();
|
||||
|
||||
for (SketchCode code : sketch.getCode()) {
|
||||
if (code.isExtension("java")) {
|
||||
String path = new File(buildPath, code.getFileName()).getAbsolutePath();
|
||||
sourceFiles[sourceCount++] = path;
|
||||
}
|
||||
}
|
||||
String[] command = new String[baseCommand.length + sourceCount];
|
||||
System.arraycopy(baseCommand, 0, command, 0, baseCommand.length);
|
||||
// append each of the files to the command string
|
||||
System.arraycopy(sourceFiles, 0, command, baseCommand.length, sourceCount);
|
||||
|
||||
//PApplet.println(command);
|
||||
|
||||
try {
|
||||
// Load errors into a local StringBuffer
|
||||
final StringBuffer errorBuffer = new StringBuffer();
|
||||
|
||||
// Create single method dummy writer class to slurp errors from javac
|
||||
Writer internalWriter = new Writer() {
|
||||
public void write(char[] buf, int off, int len) {
|
||||
errorBuffer.append(buf, off, len);
|
||||
}
|
||||
|
||||
public void flush() { }
|
||||
|
||||
public void close() { }
|
||||
};
|
||||
// Wrap as a PrintWriter since that's what compile() wants
|
||||
PrintWriter writer = new PrintWriter(internalWriter);
|
||||
|
||||
//result = com.sun.tools.javac.Main.compile(command, writer);
|
||||
|
||||
CompilationProgress progress = null;
|
||||
PrintWriter outWriter = new PrintWriter(System.out);
|
||||
success = BatchCompiler.compile(command, outWriter, writer, progress);
|
||||
// Close out the stream for good measure
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new StringReader(errorBuffer.toString()));
|
||||
//System.err.println(errorBuffer.toString());
|
||||
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
//System.out.println("got line " + line); // debug
|
||||
|
||||
// get first line, which contains file name, line number,
|
||||
// and at least the first line of the error message
|
||||
String errorFormat = "([\\w\\d_]+.java):(\\d+):\\s*(.*):\\s*(.*)\\s*";
|
||||
String[] pieces = PApplet.match(line, errorFormat);
|
||||
//PApplet.println(pieces);
|
||||
|
||||
// if it's something unexpected, die and print the mess to the console
|
||||
if (pieces == null) {
|
||||
exception = new RunnerException("Cannot parse error text: " + line);
|
||||
exception.hideStackTrace();
|
||||
// Send out the rest of the error message to the console.
|
||||
System.err.println(line);
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.err.println(line);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// translate the java filename and line number into a un-preprocessed
|
||||
// location inside a source file or tab in the environment.
|
||||
String dotJavaFilename = pieces[1];
|
||||
// Line numbers are 1-indexed from javac
|
||||
int dotJavaLineIndex = PApplet.parseInt(pieces[2]) - 1;
|
||||
String errorMessage = pieces[4];
|
||||
|
||||
int codeIndex = 0; //-1;
|
||||
int codeLine = -1;
|
||||
|
||||
// first check to see if it's a .java file
|
||||
for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
SketchCode code = sketch.getCode(i);
|
||||
if (code.isExtension("java")) {
|
||||
if (dotJavaFilename.equals(code.getFileName())) {
|
||||
codeIndex = i;
|
||||
codeLine = dotJavaLineIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it's not a .java file, codeIndex will still be 0
|
||||
if (codeIndex == 0) { // main class, figure out which tab
|
||||
//for (int i = 1; i < sketch.getCodeCount(); i++) {
|
||||
for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
SketchCode code = sketch.getCode(i);
|
||||
|
||||
if (code.isExtension("pde")) {
|
||||
if (code.getPreprocOffset() <= dotJavaLineIndex) {
|
||||
codeIndex = i;
|
||||
//System.out.println("i'm thinkin file " + i);
|
||||
codeLine = dotJavaLineIndex - code.getPreprocOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (codeLine != -1) {
|
||||
//codeLine = dotJavaLineIndex - sketch.getCode(codeIndex).getPreprocOffset();
|
||||
//}
|
||||
}
|
||||
//System.out.println("code line now " + codeLine);
|
||||
exception = new RunnerException(errorMessage, codeIndex, codeLine, -1, false);
|
||||
|
||||
// for a test case once message parsing is implemented,
|
||||
// use new Font(...) since that wasn't getting picked up properly.
|
||||
|
||||
/*
|
||||
if (errorMessage.equals("cannot find symbol")) {
|
||||
handleCannotFindSymbol(reader, exception);
|
||||
|
||||
} else if (errorMessage.indexOf("is already defined") != -1) {
|
||||
reader.readLine(); // repeats the line of code w/ error
|
||||
int codeColumn = caretColumn(reader.readLine());
|
||||
exception = new RunnerException(errorMessage,
|
||||
codeIndex, codeLine, codeColumn);
|
||||
|
||||
} else if (errorMessage.startsWith("package") &&
|
||||
errorMessage.endsWith("does not exist")) {
|
||||
// Because imports are stripped out and re-added to the 0th line of
|
||||
// the preprocessed code, codeLine will always be wrong for imports.
|
||||
exception = new RunnerException("P" + errorMessage.substring(1) +
|
||||
". You might be missing a library.");
|
||||
} else {
|
||||
exception = new RunnerException(errorMessage);
|
||||
}
|
||||
*/
|
||||
if (errorMessage.startsWith("The import ") &&
|
||||
errorMessage.endsWith("cannot be resolved")) {
|
||||
// The import poo cannot be resolved
|
||||
//import poo.shoe.blah.*;
|
||||
String what = errorMessage.substring("The import ".length());
|
||||
what = what.substring(0, what.indexOf(' '));
|
||||
System.err.println("Note that release 1.0, libraries must be " +
|
||||
"installed in a folder named 'libraries' " +
|
||||
"inside the 'sketchbook' folder.");
|
||||
exception.setMessage("The package " +
|
||||
"\u201C" + what + "\u201D" +
|
||||
" does not exist. " +
|
||||
"You might be missing a library.");
|
||||
|
||||
// Actually create the folder and open it for the user
|
||||
File sketchbookLibraries = Base.getSketchbookLibrariesFolder();
|
||||
if (!sketchbookLibraries.exists()) {
|
||||
if (sketchbookLibraries.mkdirs()) {
|
||||
Base.openFolder(sketchbookLibraries);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (errorMessage.endsWith("cannot be resolved to a type")) {
|
||||
// xxx cannot be resolved to a type
|
||||
//xxx c;
|
||||
|
||||
String what = errorMessage.substring(0, errorMessage.indexOf(' '));
|
||||
|
||||
if (what.equals("BFont") ||
|
||||
what.equals("BGraphics") ||
|
||||
what.equals("BImage")) {
|
||||
handleCrustyCode(exception);
|
||||
|
||||
} else {
|
||||
exception.setMessage("Cannot find a class or type " +
|
||||
"named \u201C" + what + "\u201D");
|
||||
}
|
||||
|
||||
} else if (errorMessage.endsWith("cannot be resolved")) {
|
||||
// xxx cannot be resolved
|
||||
//println(xxx);
|
||||
|
||||
String what = errorMessage.substring(0, errorMessage.indexOf(' '));
|
||||
|
||||
if (what.equals("LINE_LOOP") ||
|
||||
what.equals("LINE_STRIP") ||
|
||||
what.equals("framerate")) {
|
||||
handleCrustyCode(exception);
|
||||
|
||||
} else {
|
||||
exception.setMessage("Cannot find anything " +
|
||||
"named \u201C" + what + "\u201D");
|
||||
}
|
||||
|
||||
} else if (errorMessage.startsWith("Duplicate")) {
|
||||
// "Duplicate nested type xxx"
|
||||
// "Duplicate local variable xxx"
|
||||
|
||||
} else {
|
||||
String[] parts = null;
|
||||
|
||||
// The method xxx(String) is undefined for the type Temporary_XXXX_XXXX
|
||||
//xxx("blah");
|
||||
// The method xxx(String, int) is undefined for the type Temporary_XXXX_XXXX
|
||||
//xxx("blah", 34);
|
||||
// The method xxx(String, int) is undefined for the type PApplet
|
||||
//PApplet.sub("ding");
|
||||
String undefined =
|
||||
"The method (\\S+\\(.*\\)) is undefined for the type (.*)";
|
||||
parts = PApplet.match(errorMessage, undefined);
|
||||
if (parts != null) {
|
||||
if (parts[1].equals("framerate(int)") ||
|
||||
parts[1].equals("push()")) {
|
||||
handleCrustyCode(exception);
|
||||
} else {
|
||||
String mess = "The function " + parts[1] + " does not exist.";
|
||||
exception.setMessage(mess);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exception != null) {
|
||||
// The stack trace just shows that this happened inside the compiler,
|
||||
// which is a red herring. Don't ever show it for compiler stuff.
|
||||
exception.hideStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
String bigSigh = "Error while compiling. (" + e.getMessage() + ")";
|
||||
exception = new RunnerException(bigSigh);
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
// In case there was something else.
|
||||
if (exception != null) throw exception;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fire up 'ole javac based on <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/javac.html#proginterface">this interface</a>.
|
||||
*
|
||||
* @param sketch Sketch object to be compiled.
|
||||
* @param buildPath Where the temporary files live and will be built from.
|
||||
* @return
|
||||
* @throws RunnerException Only if there's a problem. Only then.
|
||||
*/
|
||||
// public boolean compileJavac(Sketch sketch,
|
||||
// String buildPath) throws RunnerException {
|
||||
// // This will be filled in if anyone gets angry
|
||||
// RunnerException exception = null;
|
||||
//
|
||||
// String baseCommand[] = new String[] {
|
||||
// "-source", "1.5",
|
||||
// "-target", "1.5",
|
||||
// "-classpath", sketch.getClassPath(),
|
||||
// "-nowarn", // we're not currently interested in warnings (ignored?)
|
||||
// "-d", buildPath // output the classes in the buildPath
|
||||
// };
|
||||
// //PApplet.println(baseCommand);
|
||||
//
|
||||
// // make list of code files that need to be compiled
|
||||
// // (some files are skipped if they contain no class)
|
||||
// String[] preprocNames = new String[sketch.getCodeCount()];
|
||||
// int preprocCount = 0;
|
||||
// for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
// if (sketch.getCode(i).preprocName != null) {
|
||||
// preprocNames[preprocCount++] = sketch.getCode(i).preprocName;
|
||||
// }
|
||||
// }
|
||||
// String[] command = new String[baseCommand.length + preprocCount];
|
||||
// System.arraycopy(baseCommand, 0, command, 0, baseCommand.length);
|
||||
// // append each of the files to the command string
|
||||
// for (int i = 0; i < preprocCount; i++) {
|
||||
// command[baseCommand.length + i] =
|
||||
// buildPath + File.separator + preprocNames[i];
|
||||
// }
|
||||
// //PApplet.println(command);
|
||||
//
|
||||
// int result = -1; // needs to be set bad by default, in case hits IOE below
|
||||
//
|
||||
// try {
|
||||
// // Load errors into a local StringBuffer
|
||||
// final StringBuffer errorBuffer = new StringBuffer();
|
||||
//
|
||||
// // Create single method dummy writer class to slurp errors from javac
|
||||
// Writer internalWriter = new Writer() {
|
||||
// public void write(char[] buf, int off, int len) {
|
||||
// errorBuffer.append(buf, off, len);
|
||||
// }
|
||||
//
|
||||
// public void flush() { }
|
||||
//
|
||||
// public void close() { }
|
||||
// };
|
||||
// // Wrap as a PrintWriter since that's what compile() wants
|
||||
// PrintWriter writer = new PrintWriter(internalWriter);
|
||||
//
|
||||
// result = com.sun.tools.javac.Main.compile(command, writer);
|
||||
//
|
||||
// // Close out the stream for good measure
|
||||
// writer.flush();
|
||||
// writer.close();
|
||||
//
|
||||
//// BufferedReader reader =
|
||||
//// new BufferedReader(new StringReader(errorBuffer.toString()));
|
||||
// //System.err.println(errorBuffer.toString());
|
||||
//
|
||||
//// String m = errorBuffer.toString();
|
||||
// //ParsePosition mp = new ParsePosition(0);
|
||||
//
|
||||
//// while (mp.getIndex() < m.length()) { // reading messages
|
||||
// String line = null;
|
||||
// int lineIndex = 0;
|
||||
// String[] lines = PApplet.split(errorBuffer.toString(), '\n');
|
||||
// int lineCount = lines.length;
|
||||
// while (lineIndex < lineCount) {
|
||||
// //while ((line = reader.readLine()) != null) {
|
||||
// //System.out.println("got line " + line); // debug
|
||||
//
|
||||
// /*
|
||||
//compiler.misc.count.error=\
|
||||
// {0} error
|
||||
//compiler.misc.count.error.plural=\
|
||||
// {0} errors
|
||||
//compiler.misc.count.warn=\
|
||||
// {0} warning
|
||||
//compiler.misc.count.warn.plural=\
|
||||
// {0} warnings
|
||||
// */
|
||||
// // Check to see if this is the last line.
|
||||
//// if ((PApplet.match(line, "\\d+ error[s]?") != null) ||
|
||||
//// (PApplet.match(line, "\\d+ warning[s]?") != null)) {
|
||||
//// break;
|
||||
//// }
|
||||
// if (isCompilerMatch(line, "compiler.misc.count.error") ||
|
||||
// isCompilerMatch(line, "compiler.misc.count.error.plural") ||
|
||||
// isCompilerMatch(line, "compiler.misc.count.warn") ||
|
||||
// isCompilerMatch(line, "compiler.misc.count.warn.plural")) {
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // Hide these because people are getting confused
|
||||
// // http://dev.processing.org/bugs/show_bug.cgi?id=817
|
||||
// // com/sun/tools/javac/resources/compiler.properties
|
||||
// //if (line.startsWith("Note: ")) {
|
||||
// String compilerNote = compilerResources.getString("compiler.note.note");
|
||||
// MessageFormat noteFormat = new MessageFormat(compilerNote + " {0}");
|
||||
// Object[] noteFound;
|
||||
// try {
|
||||
// noteFound = noteFormat.parse(line);
|
||||
// if (noteFound != null) {
|
||||
// System.out.println("gefunden " + noteFound[0]);
|
||||
//
|
||||
// /*
|
||||
// // if you mention serialVersionUID one more time, i'm kickin' you out
|
||||
// if (line.indexOf("serialVersionUID") != -1) continue;
|
||||
// // {0} uses unchecked or unsafe operations.
|
||||
// // Some input files use unchecked or unsafe operations.
|
||||
// if (line.indexOf("or unsafe operations") != -1) continue;
|
||||
// // {0} uses or overrides a deprecated API.
|
||||
// // Some input files use or override a deprecated API.
|
||||
// if (line.indexOf("or override") != -1) continue;
|
||||
// // Recompile with -Xlint:deprecation for details.
|
||||
// // Recompile with -Xlint:unchecked for details.
|
||||
// if (line.indexOf("Recompile with -Xlint:") != -1) continue;
|
||||
// System.err.println(line);
|
||||
// */
|
||||
// continue;
|
||||
// }
|
||||
// } catch (ParseException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// // get first line, which contains file name, line number,
|
||||
// // and at least the first line of the error message
|
||||
// String errorFormat = "([\\w\\d_]+.java):(\\d+):\\s*(.*)\\s*";
|
||||
// String[] pieces = PApplet.match(line, errorFormat);
|
||||
//
|
||||
// // if it's something unexpected, die and print the mess to the console
|
||||
// if (pieces == null) {
|
||||
// exception = new RunnerException("Cannot parse error text: " + line);
|
||||
// exception.hideStackTrace();
|
||||
// // Send out the rest of the error message to the console.
|
||||
// System.err.println(line);
|
||||
// //while ((line = reader.readLine()) != null) {
|
||||
// for (int i = lineIndex; i < lineCount; i++) {
|
||||
// System.err.println(lines[i]);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// // translate the java filename and line number into a un-preprocessed
|
||||
// // location inside a source file or tab in the environment.
|
||||
// String dotJavaFilename = pieces[0];
|
||||
// // Line numbers are 1-indexed from javac
|
||||
// int dotJavaLineIndex = PApplet.parseInt(pieces[1]) - 1;
|
||||
// String errorMessage = pieces[2];
|
||||
//
|
||||
// int codeIndex = -1;
|
||||
// int codeLine = -1;
|
||||
// for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
// String name = sketch.getCode(i).preprocName;
|
||||
// if ((name != null) && dotJavaFilename.equals(name)) {
|
||||
// codeIndex = i;
|
||||
// }
|
||||
// }
|
||||
// //System.out.println("code index/line are " + codeIndex + " " + codeLine);
|
||||
// //System.out.println("java line number " + dotJavaLineIndex + " from " + dotJavaFilename);
|
||||
//
|
||||
// if (codeIndex == 0) { // main class, figure out which tab
|
||||
// for (int i = 1; i < sketch.getCodeCount(); i++) {
|
||||
// SketchCode code = sketch.getCode(i);
|
||||
//
|
||||
// if (code.flavor == Sketch.PDE) {
|
||||
// if (code.preprocOffset <= dotJavaLineIndex) {
|
||||
// codeIndex = i;
|
||||
// //System.out.println("i'm thinkin file " + i);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// //System.out.println("preproc offset is " + sketch.getCode(codeIndex).preprocOffset);
|
||||
// codeLine = dotJavaLineIndex - sketch.getCode(codeIndex).preprocOffset;
|
||||
// //System.out.println("code line now " + codeLine);
|
||||
// exception = new RunnerException(errorMessage, codeIndex, codeLine, -1, false);
|
||||
//
|
||||
// // for a test case once message parsing is implemented,
|
||||
// // use new Font(...) since that wasn't getting picked up properly.
|
||||
//
|
||||
// if (errorMessage.equals("cannot find symbol")) {
|
||||
// handleCannotFindSymbol(reader, exception);
|
||||
//
|
||||
// } else if (errorMessage.indexOf("is already defined") != -1) {
|
||||
// reader.readLine(); // repeats the line of code w/ error
|
||||
// int codeColumn = caretColumn(reader.readLine());
|
||||
// exception = new RunnerException(errorMessage,
|
||||
// codeIndex, codeLine, codeColumn);
|
||||
//
|
||||
// } else if (errorMessage.startsWith("package") &&
|
||||
// errorMessage.endsWith("does not exist")) {
|
||||
// // Because imports are stripped out and re-added to the 0th line of
|
||||
// // the preprocessed code, codeLine will always be wrong for imports.
|
||||
// exception = new RunnerException("P" + errorMessage.substring(1) +
|
||||
// ". You might be missing a library.");
|
||||
// } else {
|
||||
// exception = new RunnerException(errorMessage);
|
||||
// }
|
||||
// if (exception != null) {
|
||||
// // The stack trace just shows that this happened inside the compiler,
|
||||
// // which is a red herring. Don't ever show it for compiler stuff.
|
||||
// exception.hideStackTrace();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// String bigSigh = "Error while compiling. (" + e.getMessage() + ")";
|
||||
// exception = new RunnerException(bigSigh);
|
||||
// e.printStackTrace();
|
||||
// result = 1;
|
||||
// }
|
||||
// // In case there was something else.
|
||||
// if (exception != null) throw exception;
|
||||
//
|
||||
// // Success means that 'result' is set to zero
|
||||
// return (result == 0);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// boolean isCompilerMatch(String line, String format) {
|
||||
// return compilerMatch(line, format) != null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Object[] compilerMatch(String line, String name) {
|
||||
// String format = compilerResources.getString(name);
|
||||
// MessageFormat mf = new MessageFormat(format);
|
||||
// Object[] matches = null;
|
||||
// try {
|
||||
// matches = mf.parse(line);
|
||||
// } catch (ParseException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return matches;
|
||||
// }
|
||||
|
||||
|
||||
// boolean isCompilerMatch(String line, ParsePosition pos, String format) {
|
||||
// return compilerMatch(line, pos, format) != null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Object[] compilerMatch(String line, ParsePosition pos, String name) {
|
||||
// String format = compilerResources.getString(name);
|
||||
// MessageFormat mf = new MessageFormat(format);
|
||||
// Object[] matches = mf.parse(line, pos);
|
||||
// return matches;
|
||||
// }
|
||||
|
||||
|
||||
// Tell-tale signs of old code copied and pasted from the web.
|
||||
// Detect classes BFont, BGraphics, BImage; methods framerate, push;
|
||||
// and variables LINE_LOOP and LINE_STRIP.
|
||||
// static HashMap crusties = new HashMap();
|
||||
// static {
|
||||
// crusties.put("BFont", new Object());
|
||||
// crusties.put("BGraphics", new Object());
|
||||
// crusties.put("BImage", new Object());
|
||||
// crusties.put("framerate", new Object());
|
||||
// crusties.put("push", new Object());
|
||||
// crusties.put("LINE_LOOP", new Object());
|
||||
// crusties.put("LINE_STRIP", new Object());
|
||||
// }
|
||||
|
||||
|
||||
// void handleCannotFindSymbol(BufferedReader reader,
|
||||
// RunnerException rex) throws IOException {
|
||||
// String symbolLine = reader.readLine();
|
||||
// String locationLine = reader.readLine();
|
||||
// /*String codeLine =*/ reader.readLine();
|
||||
// String caretLine = reader.readLine();
|
||||
// rex.setCodeColumn(caretColumn(caretLine));
|
||||
//
|
||||
// String[] pieces =
|
||||
// PApplet.match(symbolLine, "symbol\\s*:\\s*(\\w+)\\s+(.*)");
|
||||
// if (pieces != null) {
|
||||
// if (pieces[0].equals("class") ||
|
||||
// pieces[0].equals("variable")) {
|
||||
// rex.setMessage("Cannot find a " + pieces[0] + " " +
|
||||
// "named \u201C" + pieces[1] + "\u201D");
|
||||
// if (crusties.get(pieces[1]) != null) {
|
||||
// handleCrustyCode(rex);
|
||||
// }
|
||||
//
|
||||
// } else if (pieces[0].equals("method")) {
|
||||
// int leftParen = pieces[1].indexOf("(");
|
||||
// int rightParen = pieces[1].indexOf(")");
|
||||
//
|
||||
// String methodName = pieces[1].substring(0, leftParen);
|
||||
// String methodParams = pieces[1].substring(leftParen + 1, rightParen);
|
||||
//
|
||||
// String message =
|
||||
// "Cannot find a function named \u201C" + methodName + "\u201D";
|
||||
// if (methodParams.length() > 0) {
|
||||
// if (methodParams.indexOf(',') != -1) {
|
||||
// message += " with parameters ";
|
||||
// } else {
|
||||
// message += " with parameter ";
|
||||
// }
|
||||
// message += methodParams;
|
||||
// }
|
||||
//
|
||||
// String locationClass = "location: class ";
|
||||
// if (locationLine.startsWith(locationClass) &&
|
||||
// // don't include the class name when it's a temp class
|
||||
// locationLine.indexOf("Temporary_") == -1) {
|
||||
// String className = locationLine.substring(locationClass.length());
|
||||
// // If no dot exists, -1 + 1 is 0, so this will have no effect.
|
||||
// className = className.substring(className.lastIndexOf('.') + 1);
|
||||
// int bracket = className.indexOf('[');
|
||||
// if (bracket == -1) {
|
||||
// message += " in class " + className;
|
||||
// } else {
|
||||
// className = className.substring(0, bracket);
|
||||
// message += " for an array of " + className + " objects";
|
||||
// }
|
||||
// }
|
||||
// message += ".";
|
||||
// rex.setMessage(message);
|
||||
//
|
||||
// // On second thought, make sure this isn't just some alpha/beta code
|
||||
// if (crusties.get(methodName) != null) {
|
||||
// handleCrustyCode(rex);
|
||||
// }
|
||||
//
|
||||
// } else {
|
||||
// System.out.println(symbolLine);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
void handleCrustyCode(RunnerException rex) {
|
||||
rex.setMessage("This code needs to be updated, " +
|
||||
"please read the \u201Cchanges\u201D reference.");
|
||||
Base.showReference("changes.html");
|
||||
}
|
||||
|
||||
|
||||
protected int caretColumn(String caretLine) {
|
||||
return caretLine.indexOf("^");
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Given a folder, return a list of absolute paths to all jar or zip files
|
||||
* inside that folder, separated by pathSeparatorChar.
|
||||
*
|
||||
* This will prepend a colon (or whatever the path separator is)
|
||||
* so that it can be directly appended to another path string.
|
||||
*
|
||||
* As of 0136, this will no longer add the root folder as well.
|
||||
*
|
||||
* This function doesn't bother checking to see if there are any .class
|
||||
* files in the folder or within a subfolder.
|
||||
*/
|
||||
static public String contentsToClassPath(File folder) {
|
||||
if (folder == null) return "";
|
||||
|
||||
StringBuffer abuffer = new StringBuffer();
|
||||
String sep = System.getProperty("path.separator");
|
||||
|
||||
try {
|
||||
String path = folder.getCanonicalPath();
|
||||
|
||||
// disabled as of 0136
|
||||
// add the folder itself in case any unzipped files
|
||||
// abuffer.append(sep);
|
||||
// abuffer.append(path);
|
||||
//
|
||||
// When getting the name of this folder, make sure it has a slash
|
||||
// after it, so that the names of sub-items can be added.
|
||||
if (!path.endsWith(File.separator)) {
|
||||
path += File.separator;
|
||||
}
|
||||
|
||||
String list[] = folder.list();
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
// Skip . and ._ files. Prior to 0125p3, .jar files that had
|
||||
// OS X AppleDouble files associated would cause trouble.
|
||||
if (list[i].startsWith(".")) continue;
|
||||
|
||||
if (list[i].toLowerCase().endsWith(".jar") ||
|
||||
list[i].toLowerCase().endsWith(".zip")) {
|
||||
abuffer.append(sep);
|
||||
abuffer.append(path);
|
||||
abuffer.append(list[i]);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(); // this would be odd
|
||||
}
|
||||
//System.out.println("included path is " + abuffer.toString());
|
||||
//packageListFromClassPath(abuffer.toString()); // WHY?
|
||||
return abuffer.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A classpath, separated by the path separator, will contain
|
||||
* a series of .jar/.zip files or directories containing .class
|
||||
* files, or containing subdirectories that have .class files.
|
||||
*
|
||||
* @param path the input classpath
|
||||
* @return array of possible package names
|
||||
*/
|
||||
static public String[] packageListFromClassPath(String path) {
|
||||
Hashtable table = new Hashtable();
|
||||
String pieces[] =
|
||||
PApplet.split(path, File.pathSeparatorChar);
|
||||
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
//System.out.println("checking piece '" + pieces[i] + "'");
|
||||
if (pieces[i].length() == 0) continue;
|
||||
|
||||
if (pieces[i].toLowerCase().endsWith(".jar") ||
|
||||
pieces[i].toLowerCase().endsWith(".zip")) {
|
||||
//System.out.println("checking " + pieces[i]);
|
||||
packageListFromZip(pieces[i], table);
|
||||
|
||||
} else { // it's another type of file or directory
|
||||
File dir = new File(pieces[i]);
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
packageListFromFolder(dir, null, table);
|
||||
//importCount = magicImportsRecursive(dir, null,
|
||||
// table);
|
||||
//imports, importCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
int tableCount = table.size();
|
||||
String output[] = new String[tableCount];
|
||||
int index = 0;
|
||||
Enumeration e = table.keys();
|
||||
while (e.hasMoreElements()) {
|
||||
output[index++] = ((String) e.nextElement()).replace('/', '.');
|
||||
}
|
||||
//System.arraycopy(imports, 0, output, 0, importCount);
|
||||
//PApplet.printarr(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
static private void packageListFromZip(String filename, Hashtable table) {
|
||||
try {
|
||||
ZipFile file = new ZipFile(filename);
|
||||
Enumeration entries = file.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
String name = entry.getName();
|
||||
|
||||
if (name.endsWith(".class")) {
|
||||
int slash = name.lastIndexOf('/');
|
||||
if (slash == -1) continue;
|
||||
|
||||
String pname = name.substring(0, slash);
|
||||
if (table.get(pname) == null) {
|
||||
table.put(pname, new Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")");
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make list of package names by traversing a directory hierarchy.
|
||||
* Each time a class is found in a folder, add its containing set
|
||||
* of folders to the package list. If another folder is found,
|
||||
* walk down into that folder and continue.
|
||||
*/
|
||||
static private void packageListFromFolder(File dir, String sofar,
|
||||
Hashtable table) {
|
||||
//String imports[],
|
||||
//int importCount) {
|
||||
//System.err.println("checking dir '" + dir + "'");
|
||||
boolean foundClass = false;
|
||||
String files[] = dir.list();
|
||||
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].equals(".") || files[i].equals("..")) continue;
|
||||
|
||||
File sub = new File(dir, files[i]);
|
||||
if (sub.isDirectory()) {
|
||||
String nowfar =
|
||||
(sofar == null) ? files[i] : (sofar + "." + files[i]);
|
||||
packageListFromFolder(sub, nowfar, table);
|
||||
//System.out.println(nowfar);
|
||||
//imports[importCount++] = nowfar;
|
||||
//importCount = magicImportsRecursive(sub, nowfar,
|
||||
// imports, importCount);
|
||||
} else if (!foundClass) { // if no classes found in this folder yet
|
||||
if (files[i].endsWith(".class")) {
|
||||
//System.out.println("unique class: " + files[i] + " for " + sofar);
|
||||
table.put(sofar, new Object());
|
||||
foundClass = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
424
app/src/processing/app/debug/EventThread.java
Normal file
424
app/src/processing/app/debug/EventThread.java
Normal file
@ -0,0 +1,424 @@
|
||||
/*
|
||||
* @(#)EventThread.java 1.4 03/01/23
|
||||
*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||
* modify and redistribute this software in source and binary code form,
|
||||
* provided that i) this copyright notice and license appear on all copies of
|
||||
* the software; and ii) Licensee does not utilize the software in a manner
|
||||
* which is disparaging to Sun.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* This software is not designed or intended for use in on-line control of
|
||||
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||
* the design, construction, operation or maintenance of any nuclear
|
||||
* facility. Licensee represents and warrants that it will not use or
|
||||
* redistribute the Software for such purposes.
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.jdi.Field;
|
||||
import com.sun.jdi.IncompatibleThreadStateException;
|
||||
import com.sun.jdi.ThreadReference;
|
||||
import com.sun.jdi.VMDisconnectedException;
|
||||
import com.sun.jdi.Value;
|
||||
import com.sun.jdi.VirtualMachine;
|
||||
import com.sun.jdi.event.ClassPrepareEvent;
|
||||
import com.sun.jdi.event.Event;
|
||||
import com.sun.jdi.event.EventIterator;
|
||||
import com.sun.jdi.event.EventQueue;
|
||||
import com.sun.jdi.event.EventSet;
|
||||
import com.sun.jdi.event.ExceptionEvent;
|
||||
import com.sun.jdi.event.MethodEntryEvent;
|
||||
import com.sun.jdi.event.MethodExitEvent;
|
||||
import com.sun.jdi.event.ModificationWatchpointEvent;
|
||||
import com.sun.jdi.event.StepEvent;
|
||||
import com.sun.jdi.event.ThreadDeathEvent;
|
||||
import com.sun.jdi.event.VMDeathEvent;
|
||||
import com.sun.jdi.event.VMDisconnectEvent;
|
||||
import com.sun.jdi.event.VMStartEvent;
|
||||
import com.sun.jdi.request.EventRequest;
|
||||
import com.sun.jdi.request.EventRequestManager;
|
||||
import com.sun.jdi.request.ExceptionRequest;
|
||||
import com.sun.jdi.request.ModificationWatchpointRequest;
|
||||
import com.sun.jdi.request.StepRequest;
|
||||
|
||||
/**
|
||||
* This class processes incoming JDI events and displays them
|
||||
*
|
||||
* @version @(#) EventThread.java 1.4 03/01/23 23:33:38
|
||||
* @author Robert Field
|
||||
*/
|
||||
public class EventThread extends Thread {
|
||||
|
||||
private final Runner parent;
|
||||
private final VirtualMachine vm; // Running VM
|
||||
private final String[] excludes; // Packages to exclude
|
||||
private final PrintWriter writer; // Where output goes
|
||||
|
||||
static String nextBaseIndent = ""; // Starting indent for next thread
|
||||
|
||||
private boolean connected = true; // Connected to VM
|
||||
private boolean vmDied = true; // VMDeath occurred
|
||||
|
||||
// Maps ThreadReference to ThreadTrace instances
|
||||
private Map traceMap = new HashMap();
|
||||
|
||||
EventThread(Runner parent, VirtualMachine vm, String[] excludes, PrintWriter writer) {
|
||||
super("event-handler");
|
||||
this.parent = parent;
|
||||
this.vm = vm;
|
||||
this.excludes = excludes;
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the event handling thread.
|
||||
* As long as we are connected, get event sets off
|
||||
* the queue and dispatch the events within them.
|
||||
*/
|
||||
public void run() {
|
||||
EventQueue queue = vm.eventQueue();
|
||||
while (connected) {
|
||||
try {
|
||||
EventSet eventSet = queue.remove();
|
||||
EventIterator it = eventSet.eventIterator();
|
||||
while (it.hasNext()) {
|
||||
handleEvent(it.nextEvent());
|
||||
}
|
||||
eventSet.resume();
|
||||
} catch (InterruptedException exc) {
|
||||
// Ignore
|
||||
} catch (VMDisconnectedException discExc) {
|
||||
handleDisconnectedException();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the desired event requests, and enable
|
||||
* them so that we will get events.
|
||||
* @param excludes Class patterns for which we don't want events
|
||||
* @param watchFields Do we want to watch assignments to fields
|
||||
*/
|
||||
void setEventRequests(boolean watchFields) {
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
|
||||
// VMDeathRequest deathReq = mgr.createVMDeathRequest();
|
||||
// deathReq.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
// deathReq.enable();
|
||||
|
||||
// want all exceptions
|
||||
ExceptionRequest excReq = mgr.createExceptionRequest(null, false, true);
|
||||
//ExceptionRequest excReq = mgr.createExceptionRequest(null, true, true);
|
||||
// suspend so we can step
|
||||
excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
excReq.enable();
|
||||
|
||||
/*
|
||||
MethodEntryRequest menr = mgr.createMethodEntryRequest();
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
menr.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
menr.setSuspendPolicy(EventRequest.SUSPEND_NONE);
|
||||
menr.enable();
|
||||
|
||||
MethodExitRequest mexr = mgr.createMethodExitRequest();
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
mexr.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
mexr.setSuspendPolicy(EventRequest.SUSPEND_NONE);
|
||||
mexr.enable();
|
||||
|
||||
ThreadDeathRequest tdr = mgr.createThreadDeathRequest();
|
||||
// Make sure we sync on thread death
|
||||
tdr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
tdr.enable();
|
||||
*/
|
||||
|
||||
// turn on field watching (waaay slow)
|
||||
/*
|
||||
// if (watchFields) {
|
||||
ClassPrepareRequest cpr = mgr.createClassPrepareRequest();
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
cpr.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
cpr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
cpr.enable();
|
||||
// }
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* This class keeps context on events in one thread.
|
||||
* In this implementation, context is the indentation prefix.
|
||||
*/
|
||||
class ThreadTrace {
|
||||
final ThreadReference thread;
|
||||
final String baseIndent;
|
||||
static final String threadDelta = " ";
|
||||
StringBuffer indent;
|
||||
|
||||
ThreadTrace(ThreadReference thread) {
|
||||
this.thread = thread;
|
||||
this.baseIndent = nextBaseIndent;
|
||||
indent = new StringBuffer(baseIndent);
|
||||
nextBaseIndent += threadDelta;
|
||||
println("====== " + thread.name() + " ======");
|
||||
}
|
||||
|
||||
private void println(String str) {
|
||||
if (writer != null) {
|
||||
writer.print(indent);
|
||||
writer.println(str);
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void methodEntryEvent(MethodEntryEvent event) {
|
||||
println(event.method().name() + " -- "
|
||||
+ event.method().declaringType().name());
|
||||
indent.append("| ");
|
||||
}
|
||||
|
||||
void methodExitEvent(MethodExitEvent event) {
|
||||
indent.setLength(indent.length()-2);
|
||||
}
|
||||
|
||||
void fieldWatchEvent(ModificationWatchpointEvent event) {
|
||||
Field field = event.field();
|
||||
Value value = event.valueToBe();
|
||||
println(" " + field.name() + " = " + value);
|
||||
}
|
||||
|
||||
void exceptionEvent(ExceptionEvent event) {
|
||||
println("Exception: " + event.exception() +
|
||||
" catch: " + event.catchLocation());
|
||||
// System.out.println("Exception: " + event.exception() +
|
||||
// " catch: " + event.catchLocation());
|
||||
|
||||
// Step to the catch
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
StepRequest req = mgr.createStepRequest(thread,
|
||||
StepRequest.STEP_MIN,
|
||||
StepRequest.STEP_INTO);
|
||||
req.addCountFilter(1); // next step only
|
||||
req.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
req.enable();
|
||||
}
|
||||
|
||||
// Step to exception catch
|
||||
void stepEvent(StepEvent event) {
|
||||
// Adjust call depth
|
||||
int cnt = 0;
|
||||
indent = new StringBuffer(baseIndent);
|
||||
try {
|
||||
cnt = thread.frameCount();
|
||||
} catch (IncompatibleThreadStateException exc) {
|
||||
}
|
||||
while (cnt-- > 0) {
|
||||
indent.append("| ");
|
||||
}
|
||||
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
mgr.deleteEventRequest(event.request());
|
||||
}
|
||||
|
||||
void threadDeathEvent(ThreadDeathEvent event) {
|
||||
indent = new StringBuffer(baseIndent);
|
||||
println("====== " + thread.name() + " end ======");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ThreadTrace instance for the specified thread,
|
||||
* creating one if needed.
|
||||
*/
|
||||
ThreadTrace threadTrace(ThreadReference thread) {
|
||||
ThreadTrace trace = (ThreadTrace)traceMap.get(thread);
|
||||
if (trace == null) {
|
||||
trace = new ThreadTrace(thread);
|
||||
traceMap.put(thread, trace);
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch incoming events
|
||||
*/
|
||||
private void handleEvent(Event event) {
|
||||
if (event instanceof ExceptionEvent) {
|
||||
exceptionEvent((ExceptionEvent)event);
|
||||
} else if (event instanceof ModificationWatchpointEvent) {
|
||||
fieldWatchEvent((ModificationWatchpointEvent)event);
|
||||
} else if (event instanceof MethodEntryEvent) {
|
||||
methodEntryEvent((MethodEntryEvent)event);
|
||||
} else if (event instanceof MethodExitEvent) {
|
||||
methodExitEvent((MethodExitEvent)event);
|
||||
} else if (event instanceof StepEvent) {
|
||||
stepEvent((StepEvent)event);
|
||||
} else if (event instanceof ThreadDeathEvent) {
|
||||
threadDeathEvent((ThreadDeathEvent)event);
|
||||
} else if (event instanceof ClassPrepareEvent) {
|
||||
classPrepareEvent((ClassPrepareEvent)event);
|
||||
} else if (event instanceof VMStartEvent) {
|
||||
vmStartEvent((VMStartEvent)event);
|
||||
} else if (event instanceof VMDeathEvent) {
|
||||
vmDeathEvent((VMDeathEvent)event);
|
||||
} else if (event instanceof VMDisconnectEvent) {
|
||||
vmDisconnectEvent((VMDisconnectEvent)event);
|
||||
} else {
|
||||
throw new Error("Unexpected event type");
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* A VMDisconnectedException has happened while dealing with
|
||||
* another event. We need to flush the event queue, dealing only
|
||||
* with exit events (VMDeath, VMDisconnect) so that we terminate
|
||||
* correctly.
|
||||
*/
|
||||
synchronized void handleDisconnectedException() {
|
||||
EventQueue queue = vm.eventQueue();
|
||||
while (connected) {
|
||||
try {
|
||||
EventSet eventSet = queue.remove();
|
||||
EventIterator iter = eventSet.eventIterator();
|
||||
while (iter.hasNext()) {
|
||||
Event event = iter.nextEvent();
|
||||
if (event instanceof VMDeathEvent) {
|
||||
vmDeathEvent((VMDeathEvent)event);
|
||||
} else if (event instanceof VMDisconnectEvent) {
|
||||
vmDisconnectEvent((VMDisconnectEvent)event);
|
||||
}
|
||||
}
|
||||
eventSet.resume(); // Resume the VM
|
||||
} catch (InterruptedException exc) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void vmStartEvent(VMStartEvent event) {
|
||||
if (writer != null) writer.println("-- VM Started --");
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void methodEntryEvent(MethodEntryEvent event) {
|
||||
threadTrace(event.thread()).methodEntryEvent(event);
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void methodExitEvent(MethodExitEvent event) {
|
||||
threadTrace(event.thread()).methodExitEvent(event);
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void stepEvent(StepEvent event) {
|
||||
threadTrace(event.thread()).stepEvent(event);
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void fieldWatchEvent(ModificationWatchpointEvent event) {
|
||||
threadTrace(event.thread()).fieldWatchEvent(event);
|
||||
}
|
||||
|
||||
void threadDeathEvent(ThreadDeathEvent event) {
|
||||
ThreadTrace trace = (ThreadTrace)traceMap.get(event.thread());
|
||||
if (trace != null) { // only want threads we care about
|
||||
trace.threadDeathEvent(event); // Forward event
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A new class has been loaded.
|
||||
* Set watchpoints on each of its fields
|
||||
*/
|
||||
private void classPrepareEvent(ClassPrepareEvent event) {
|
||||
// System.out.println(event);
|
||||
// List list = event.referenceType().methodsByName("stop");
|
||||
// Object o = list.get(0);
|
||||
// System.out.println("stop methods = " + list);
|
||||
// System.out.println(o.getClass());
|
||||
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
List fields = event.referenceType().visibleFields();
|
||||
for (Iterator it = fields.iterator(); it.hasNext(); ) {
|
||||
Field field = (Field)it.next();
|
||||
ModificationWatchpointRequest req =
|
||||
mgr.createModificationWatchpointRequest(field);
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
req.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
|
||||
req.enable();
|
||||
}
|
||||
}
|
||||
|
||||
private void exceptionEvent(ExceptionEvent event) {
|
||||
// ObjectReference or = event.exception();
|
||||
// System.out.println("exceptionEvent() fired " + or);
|
||||
// System.out.println("catch location " + event.catchLocation());
|
||||
|
||||
parent.exception(event);
|
||||
|
||||
/*
|
||||
ObjectReference or = event.exception();
|
||||
ThreadReference thread = event.thread();
|
||||
ThreadTrace trace = (ThreadTrace)traceMap.get(thread);
|
||||
if (trace != null) { // only want threads we care about
|
||||
trace.exceptionEvent(event); // Forward event
|
||||
}
|
||||
try {
|
||||
List frames = thread.frames();
|
||||
for (Object item : frames) {
|
||||
System.out.println("got " + item);
|
||||
}
|
||||
//System.out.println(frames);
|
||||
} catch (IncompatibleThreadStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public void vmDeathEvent(VMDeathEvent event) {
|
||||
//System.err.println("vm is dead! dead!");
|
||||
vmDied = true;
|
||||
if (writer != null) {
|
||||
writer.println("-- The application exited --");
|
||||
}
|
||||
}
|
||||
|
||||
public void vmDisconnectEvent(VMDisconnectEvent event) {
|
||||
connected = false;
|
||||
if (!vmDied) {
|
||||
if (writer != null) {
|
||||
writer.println("-- The application has been disconnected --");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
app/src/processing/app/debug/MessageConsumer.java
Normal file
42
app/src/processing/app/debug/MessageConsumer.java
Normal file
@ -0,0 +1,42 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for dealing with parser/compiler output.
|
||||
* <P>
|
||||
* Different instances of MessageStream need to do different things with
|
||||
* messages. In particular, a stream instance used for parsing output from
|
||||
* the compiler compiler has to interpret its messages differently than one
|
||||
* parsing output from the runtime.
|
||||
* <P>
|
||||
* Classes which consume messages and do something with them
|
||||
* should implement this interface.
|
||||
*/
|
||||
public interface MessageConsumer {
|
||||
|
||||
public void message(String s);
|
||||
|
||||
}
|
87
app/src/processing/app/debug/MessageSiphon.java
Normal file
87
app/src/processing/app/debug/MessageSiphon.java
Normal file
@ -0,0 +1,87 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Slurps up messages from compiler.
|
||||
*/
|
||||
class MessageSiphon implements Runnable {
|
||||
BufferedReader streamReader;
|
||||
Thread thread;
|
||||
MessageConsumer consumer;
|
||||
|
||||
|
||||
public MessageSiphon(InputStream stream, MessageConsumer consumer) {
|
||||
this.streamReader = new BufferedReader(new InputStreamReader(stream));
|
||||
this.consumer = consumer;
|
||||
|
||||
thread = new Thread(this);
|
||||
// don't set priority too low, otherwise exceptions won't
|
||||
// bubble up in time (i.e. compile errors have a weird delay)
|
||||
//thread.setPriority(Thread.MIN_PRIORITY);
|
||||
thread.setPriority(Thread.MAX_PRIORITY-1);
|
||||
//thread.start();
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// process data until we hit EOF; this will happily block
|
||||
// (effectively sleeping the thread) until new data comes in.
|
||||
// when the program is finally done, null will come through.
|
||||
//
|
||||
String currentLine;
|
||||
while ((currentLine = streamReader.readLine()) != null) {
|
||||
// \n is added again because readLine() strips it out
|
||||
//EditorConsole.systemOut.println("messaging in");
|
||||
consumer.message(currentLine + "\n");
|
||||
//EditorConsole.systemOut.println("messaging out");
|
||||
}
|
||||
//EditorConsole.systemOut.println("messaging thread done");
|
||||
thread = null;
|
||||
|
||||
} catch (NullPointerException npe) {
|
||||
// Fairly common exception during shutdown
|
||||
thread = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
// On Linux and sometimes on Mac OS X, a "bad file descriptor"
|
||||
// message comes up when closing an applet that's run externally.
|
||||
// That message just gets supressed here..
|
||||
String mess = e.getMessage();
|
||||
if ((mess != null) &&
|
||||
(mess.indexOf("Bad file descriptor") != -1)) {
|
||||
//if (e.getMessage().indexOf("Bad file descriptor") == -1) {
|
||||
//System.err.println("MessageSiphon err " + e);
|
||||
//e.printStackTrace();
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
}
|
62
app/src/processing/app/debug/MessageStream.java
Normal file
62
app/src/processing/app/debug/MessageStream.java
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* OutputStream to handle stdout/stderr messages.
|
||||
* <P>
|
||||
* This is used by Editor, System.err is set to
|
||||
* new PrintStream(new MessageStream()).
|
||||
* It's also used by Compiler.
|
||||
*/
|
||||
class MessageStream extends OutputStream {
|
||||
|
||||
MessageConsumer messageConsumer;
|
||||
|
||||
public MessageStream(MessageConsumer messageConsumer) {
|
||||
this.messageConsumer = messageConsumer;
|
||||
}
|
||||
|
||||
public void close() { }
|
||||
|
||||
public void flush() { }
|
||||
|
||||
public void write(byte b[]) {
|
||||
// this never seems to get called
|
||||
System.out.println("leech1: " + new String(b));
|
||||
}
|
||||
|
||||
public void write(byte b[], int offset, int length) {
|
||||
//System.out.println("leech2: " + new String(b));
|
||||
this.messageConsumer.message(new String(b, offset, length));
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
// this never seems to get called
|
||||
System.out.println("leech3: '" + ((char)b) + "'");
|
||||
}
|
||||
}
|
1039
app/src/processing/app/debug/Runner.java
Normal file
1039
app/src/processing/app/debug/Runner.java
Normal file
File diff suppressed because it is too large
Load Diff
147
app/src/processing/app/debug/RunnerException.java
Normal file
147
app/src/processing/app/debug/RunnerException.java
Normal file
@ -0,0 +1,147 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
|
||||
/**
|
||||
* An exception with a line number attached that occurs
|
||||
* during either compile time or run time.
|
||||
*/
|
||||
public class RunnerException extends Exception /*RuntimeException*/ {
|
||||
protected String message;
|
||||
protected int codeIndex;
|
||||
protected int codeLine;
|
||||
protected int codeColumn;
|
||||
protected boolean showStackTrace;
|
||||
|
||||
|
||||
public RunnerException(String message) {
|
||||
this(message, -1, -1, -1, true);
|
||||
}
|
||||
|
||||
|
||||
public RunnerException(String message, int file, int line, int column) {
|
||||
this(message, file, line, column, true);
|
||||
}
|
||||
|
||||
|
||||
public RunnerException(String message, int file, int line, int column,
|
||||
boolean showStackTrace) {
|
||||
this.message = message;
|
||||
this.codeIndex = file;
|
||||
this.codeLine = line;
|
||||
this.codeColumn = column;
|
||||
this.showStackTrace = showStackTrace;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override getMessage() in Throwable, so that I can set
|
||||
* the message text outside the constructor.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public int getCodeIndex() {
|
||||
return codeIndex;
|
||||
}
|
||||
|
||||
|
||||
public void setCodeIndex(int index) {
|
||||
codeIndex = index;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasCodeIndex() {
|
||||
return codeIndex != -1;
|
||||
}
|
||||
|
||||
|
||||
public int getCodeLine() {
|
||||
return codeLine;
|
||||
}
|
||||
|
||||
|
||||
public void setCodeLine(int line) {
|
||||
this.codeLine = line;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasCodeLine() {
|
||||
return codeLine != -1;
|
||||
}
|
||||
|
||||
|
||||
public void setCodeColumn(int column) {
|
||||
this.codeColumn = column;
|
||||
}
|
||||
|
||||
|
||||
public int getCodeColumn() {
|
||||
return codeColumn;
|
||||
}
|
||||
|
||||
|
||||
public void showStackTrace() {
|
||||
showStackTrace = true;
|
||||
}
|
||||
|
||||
|
||||
public void hideStackTrace() {
|
||||
showStackTrace = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Nix the java.lang crap out of an exception message
|
||||
* because it scares the children.
|
||||
* <P>
|
||||
* This function must be static to be used with super()
|
||||
* in each of the constructors above.
|
||||
*/
|
||||
/*
|
||||
static public final String massage(String msg) {
|
||||
if (msg.indexOf("java.lang.") == 0) {
|
||||
//int dot = msg.lastIndexOf('.');
|
||||
msg = msg.substring("java.lang.".length());
|
||||
}
|
||||
return msg;
|
||||
//return (dot == -1) ? msg : msg.substring(dot+1);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void printStackTrace() {
|
||||
if (showStackTrace) {
|
||||
super.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
31
app/src/processing/app/debug/RunnerListener.java
Normal file
31
app/src/processing/app/debug/RunnerListener.java
Normal file
@ -0,0 +1,31 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
|
||||
public interface RunnerListener {
|
||||
|
||||
public void statusError(String message);
|
||||
|
||||
public void statusError(Exception exception);
|
||||
}
|
84
app/src/processing/app/debug/StreamRedirectThread.java
Normal file
84
app/src/processing/app/debug/StreamRedirectThread.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* @(#)StreamRedirectThread.java 1.4 03/01/23
|
||||
*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||
* modify and redistribute this software in source and binary code form,
|
||||
* provided that i) this copyright notice and license appear on all copies of
|
||||
* the software; and ii) Licensee does not utilize the software in a manner
|
||||
* which is disparaging to Sun.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* This software is not designed or intended for use in on-line control of
|
||||
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||
* the design, construction, operation or maintenance of any nuclear
|
||||
* facility. Licensee represents and warrants that it will not use or
|
||||
* redistribute the Software for such purposes.
|
||||
*/
|
||||
package processing.app.debug;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* StreamRedirectThread is a thread which copies it's input to
|
||||
* it's output and terminates when it completes.
|
||||
*
|
||||
* @version @(#) StreamRedirectThread.java 1.4 03/01/23 23:33:38
|
||||
* @author Robert Field
|
||||
*/
|
||||
public class StreamRedirectThread extends Thread {
|
||||
|
||||
private final Reader in;
|
||||
private final Writer out;
|
||||
|
||||
private static final int BUFFER_SIZE = 2048;
|
||||
|
||||
/**
|
||||
* Set up for copy.
|
||||
* @param name Name of the thread
|
||||
* @param in Stream to copy from
|
||||
* @param out Stream to copy to
|
||||
*/
|
||||
public StreamRedirectThread(String name, InputStream in, OutputStream out) {
|
||||
super(name);
|
||||
this.in = new InputStreamReader(in);
|
||||
this.out = new OutputStreamWriter(out);
|
||||
setPriority(Thread.MAX_PRIORITY-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
char[] cbuf = new char[BUFFER_SIZE];
|
||||
int count;
|
||||
//System.out.println("opening streamredirectthread");
|
||||
while ((count = in.read(cbuf, 0, BUFFER_SIZE)) >= 0) {
|
||||
out.write(cbuf, 0, count);
|
||||
// had to add the flush() here.. maybe shouldn't be using writer? [fry]
|
||||
out.flush();
|
||||
}
|
||||
//System.out.println("exiting streamredirectthread");
|
||||
out.flush();
|
||||
} catch(IOException exc) {
|
||||
System.err.println("Child I/O Transfer - " + exc);
|
||||
}
|
||||
}
|
||||
}
|
106
app/src/processing/app/linux/Platform.java
Normal file
106
app/src/processing/app/linux/Platform.java
Normal file
@ -0,0 +1,106 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.linux;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import processing.app.Preferences;
|
||||
|
||||
|
||||
/**
|
||||
* Used by Base for platform-specific tweaking, for instance finding the
|
||||
* sketchbook location using the Windows registry, or OS X event handling.
|
||||
*/
|
||||
public class Platform extends processing.app.Platform {
|
||||
|
||||
// TODO Need to be smarter here since KDE people ain't gonna like that GTK.
|
||||
// It may even throw a weird exception at 'em for their trouble.
|
||||
public void setLookAndFeel() throws Exception {
|
||||
// Linux is by default even uglier than metal (Motif?).
|
||||
// Actually, i'm using native menus, so they're even uglier
|
||||
// and Motif-looking (Lesstif?). Ick. Need to fix this.
|
||||
//String lfname = UIManager.getCrossPlatformLookAndFeelClassName();
|
||||
//UIManager.setLookAndFeel(lfname);
|
||||
|
||||
// For 0120, trying out the gtk+ look and feel as the default.
|
||||
// This is available in Java 1.4.2 and later, and it can't possibly
|
||||
// be any worse than Metal. (Ocean might also work, but that's for
|
||||
// Java 1.5, and we aren't going there yet)
|
||||
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
|
||||
}
|
||||
|
||||
|
||||
public void openURL(String url) throws Exception {
|
||||
if (openFolderAvailable()) {
|
||||
String launcher = Preferences.get("launcher");
|
||||
if (launcher != null) {
|
||||
Runtime.getRuntime().exec(new String[] { launcher, url });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean openFolderAvailable() {
|
||||
if (Preferences.get("launcher") != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Attempt to use gnome-open
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(new String[] { "gnome-open" });
|
||||
/*int result =*/ p.waitFor();
|
||||
// Not installed will throw an IOException (JDK 1.4.2, Ubuntu 7.04)
|
||||
Preferences.set("launcher", "gnome-open");
|
||||
return true;
|
||||
} catch (Exception e) { }
|
||||
|
||||
// Attempt with kde-open
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(new String[] { "kde-open" });
|
||||
/*int result =*/ p.waitFor();
|
||||
Preferences.set("launcher", "kde-open");
|
||||
return true;
|
||||
} catch (Exception e) { }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void openFolder(File file) throws Exception {
|
||||
if (openFolderAvailable()) {
|
||||
String lunch = Preferences.get("launcher");
|
||||
try {
|
||||
String[] params = new String[] { lunch, file.getAbsolutePath() };
|
||||
//processing.core.PApplet.println(params);
|
||||
/*Process p =*/ Runtime.getRuntime().exec(params);
|
||||
/*int result =*/ //p.waitFor();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
System.out.println("not available");
|
||||
}
|
||||
}
|
||||
}
|
184
app/src/processing/app/macosx/Platform.java
Normal file
184
app/src/processing/app/macosx/Platform.java
Normal file
@ -0,0 +1,184 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.macosx;
|
||||
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.apple.eio.FileManager;
|
||||
|
||||
import processing.app.Base;
|
||||
|
||||
|
||||
/**
|
||||
* Platform handler for Mac OS X.
|
||||
*/
|
||||
public class Platform extends processing.app.Platform {
|
||||
|
||||
public void setLookAndFeel() throws Exception {
|
||||
// Use the Quaqua L & F on OS X to make JFileChooser less awful
|
||||
UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
|
||||
// undo quaqua trying to fix the margins, since we've already
|
||||
// hacked that in, bit by bit, over the years
|
||||
UIManager.put("Component.visualMargin", new Insets(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
|
||||
public void init(Base base) {
|
||||
ThinkDifferent.init(base);
|
||||
/*
|
||||
try {
|
||||
String name = "processing.app.macosx.ThinkDifferent";
|
||||
Class osxAdapter = ClassLoader.getSystemClassLoader().loadClass(name);
|
||||
|
||||
Class[] defArgs = { Base.class };
|
||||
Method registerMethod = osxAdapter.getDeclaredMethod("register", defArgs);
|
||||
if (registerMethod != null) {
|
||||
Object[] args = { this };
|
||||
registerMethod.invoke(osxAdapter, args);
|
||||
}
|
||||
} catch (NoClassDefFoundError e) {
|
||||
// This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
|
||||
// because OSXAdapter extends ApplicationAdapter in its def
|
||||
System.err.println("This version of Mac OS X does not support the Apple EAWT." +
|
||||
"Application Menu handling has been disabled (" + e + ")");
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
// This shouldn't be reached; if there's a problem with the OSXAdapter
|
||||
// we should get the above NoClassDefFoundError first.
|
||||
System.err.println("This version of Mac OS X does not support the Apple EAWT. " +
|
||||
"Application Menu handling has been disabled (" + e + ")");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Exception while loading BaseOSX:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public File getSettingsFolder() throws Exception {
|
||||
return new File(getLibraryFolder(), "Processing");
|
||||
}
|
||||
|
||||
|
||||
public File getDefaultSketchbookFolder() throws Exception {
|
||||
return new File(getDocumentsFolder(), "Processing");
|
||||
/*
|
||||
// looking for /Users/blah/Documents/Processing
|
||||
try {
|
||||
Class clazz = Class.forName("processing.app.BaseMacOS");
|
||||
Method m = clazz.getMethod("getDocumentsFolder", new Class[] { });
|
||||
String documentsPath = (String) m.invoke(null, new Object[] { });
|
||||
sketchbookFolder = new File(documentsPath, "Processing");
|
||||
|
||||
} catch (Exception e) {
|
||||
sketchbookFolder = promptSketchbookLocation();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public void openURL(String url) throws Exception {
|
||||
if (!url.startsWith("http://")) {
|
||||
// Assume this is a file instead, and just open it.
|
||||
// Extension of http://dev.processing.org/bugs/show_bug.cgi?id=1010
|
||||
processing.core.PApplet.open(url);
|
||||
|
||||
/*
|
||||
// prepend file:// on this guy since it's a file
|
||||
url = "file://" + url;
|
||||
|
||||
// replace spaces with %20 for the file url
|
||||
// otherwise the mac doesn't like to open it
|
||||
// can't just use URLEncoder, since that makes slashes into
|
||||
// %2F characters, which is no good. some might say "useless"
|
||||
if (url.indexOf(' ') != -1) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
char c[] = url.toCharArray();
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if (c[i] == ' ') {
|
||||
sb.append("%20");
|
||||
} else {
|
||||
sb.append(c[i]);
|
||||
}
|
||||
}
|
||||
url = sb.toString();
|
||||
}
|
||||
*/
|
||||
}
|
||||
com.apple.eio.FileManager.openURL(url);
|
||||
}
|
||||
|
||||
|
||||
public boolean openFolderAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void openFolder(File file) throws Exception {
|
||||
//openURL(file.getAbsolutePath()); // handles char replacement, etc
|
||||
processing.core.PApplet.open(file.getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// Some of these are supposedly constants in com.apple.eio.FileManager,
|
||||
// however they don't seem to link properly from Eclipse.
|
||||
|
||||
static final int kDocumentsFolderType =
|
||||
('d' << 24) | ('o' << 16) | ('c' << 8) | 's';
|
||||
//static final int kPreferencesFolderType =
|
||||
// ('p' << 24) | ('r' << 16) | ('e' << 8) | 'f';
|
||||
static final int kDomainLibraryFolderType =
|
||||
('d' << 24) | ('l' << 16) | ('i' << 8) | 'b';
|
||||
static final short kUserDomain = -32763;
|
||||
|
||||
|
||||
// apple java extensions documentation
|
||||
// http://developer.apple.com/documentation/Java/Reference/1.5.0
|
||||
// /appledoc/api/com/apple/eio/FileManager.html
|
||||
|
||||
// carbon folder constants
|
||||
// http://developer.apple.com/documentation/Carbon/Reference
|
||||
// /Folder_Manager/folder_manager_ref/constant_6.html#/
|
||||
// /apple_ref/doc/uid/TP30000238/C006889
|
||||
|
||||
// additional information found int the local file:
|
||||
// /System/Library/Frameworks/CoreServices.framework
|
||||
// /Versions/Current/Frameworks/CarbonCore.framework/Headers/
|
||||
|
||||
|
||||
protected String getLibraryFolder() throws FileNotFoundException {
|
||||
return FileManager.findFolder(kUserDomain, kDomainLibraryFolderType);
|
||||
}
|
||||
|
||||
|
||||
protected String getDocumentsFolder() throws FileNotFoundException {
|
||||
return FileManager.findFolder(kUserDomain, kDocumentsFolderType);
|
||||
}
|
||||
}
|
126
app/src/processing/app/macosx/ThinkDifferent.java
Normal file
126
app/src/processing/app/macosx/ThinkDifferent.java
Normal file
@ -0,0 +1,126 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2007 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.macosx;
|
||||
|
||||
import processing.app.Base;
|
||||
|
||||
import com.apple.eawt.*;
|
||||
|
||||
|
||||
/**
|
||||
* Deal with issues related to thinking different. This handles the basic
|
||||
* Mac OS X menu commands (and apple events) for open, about, prefs, etc.
|
||||
*
|
||||
* Based on OSXAdapter.java from Apple DTS.
|
||||
*
|
||||
* As of 0140, this code need not be built on platforms other than OS X,
|
||||
* because of the new platform structure which isolates through reflection.
|
||||
*/
|
||||
public class ThinkDifferent implements ApplicationListener {
|
||||
|
||||
// pseudo-singleton model; no point in making multiple instances
|
||||
// of the EAWT application or our adapter
|
||||
private static ThinkDifferent adapter;
|
||||
// http://developer.apple.com/documentation/Java/Reference/1.4.2/appledoc/api/com/apple/eawt/Application.html
|
||||
private static Application application;
|
||||
|
||||
// reference to the app where the existing quit, about, prefs code is
|
||||
private Base base;
|
||||
|
||||
|
||||
static protected void init(Base base) {
|
||||
if (application == null) {
|
||||
application = new com.apple.eawt.Application();
|
||||
}
|
||||
if (adapter == null) {
|
||||
adapter = new ThinkDifferent(base);
|
||||
}
|
||||
application.addApplicationListener(adapter);
|
||||
application.setEnabledAboutMenu(true);
|
||||
application.setEnabledPreferencesMenu(true);
|
||||
}
|
||||
|
||||
|
||||
public ThinkDifferent(Base base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
|
||||
// implemented handler methods. These are basically hooks into existing
|
||||
// functionality from the main app, as if it came over from another platform.
|
||||
public void handleAbout(ApplicationEvent ae) {
|
||||
if (base != null) {
|
||||
ae.setHandled(true);
|
||||
base.handleAbout();
|
||||
} else {
|
||||
throw new IllegalStateException("handleAbout: Base instance detached from listener");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void handlePreferences(ApplicationEvent ae) {
|
||||
if (base != null) {
|
||||
base.handlePrefs();
|
||||
ae.setHandled(true);
|
||||
} else {
|
||||
throw new IllegalStateException("handlePreferences: Base instance detached from listener");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void handleOpenApplication(ApplicationEvent ae) {
|
||||
}
|
||||
|
||||
|
||||
public void handleOpenFile(ApplicationEvent ae) {
|
||||
String filename = ae.getFilename();
|
||||
base.handleOpen(filename);
|
||||
ae.setHandled(true);
|
||||
}
|
||||
|
||||
|
||||
public void handlePrintFile(ApplicationEvent ae) {
|
||||
// TODO implement os x print handler here (open app, call handlePrint, quit)
|
||||
}
|
||||
|
||||
|
||||
public void handleQuit(ApplicationEvent ae) {
|
||||
if (base != null) {
|
||||
/*
|
||||
/ You MUST setHandled(false) if you want to delay or cancel the quit.
|
||||
/ This is important for cross-platform development -- have a universal quit
|
||||
/ routine that chooses whether or not to quit, so the functionality is identical
|
||||
/ on all platforms. This example simply cancels the AppleEvent-based quit and
|
||||
/ defers to that universal method.
|
||||
*/
|
||||
boolean result = base.handleQuit();
|
||||
ae.setHandled(result);
|
||||
} else {
|
||||
throw new IllegalStateException("handleQuit: Base instance detached from listener");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void handleReOpenApplication(ApplicationEvent arg0) {
|
||||
}
|
||||
}
|
9
app/src/processing/app/preproc/.cvsignore
Normal file
9
app/src/processing/app/preproc/.cvsignore
Normal file
@ -0,0 +1,9 @@
|
||||
*Lexer.java
|
||||
*Recognizer.java
|
||||
*TokenTypes.java
|
||||
*TokenTypes.txt
|
||||
*TreeParser.java
|
||||
*TreeParserTokenTypes.java
|
||||
*TreeParserTokenTypes.txt
|
||||
expanded*.g
|
||||
|
936
app/src/processing/app/preproc/PdeEmitter.java
Normal file
936
app/src/processing/app/preproc/PdeEmitter.java
Normal file
@ -0,0 +1,936 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
package processing.app.preproc;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.app.debug.RunnerException;
|
||||
|
||||
|
||||
/* Based on original code copyright (c) 2003 Andy Tripp <atripp@comcast.net>.
|
||||
* shipped under GPL with permission.
|
||||
*/
|
||||
|
||||
//import antlr.*;
|
||||
import antlr.collections.*;
|
||||
//import antlr.collections.impl.*;
|
||||
import java.io.*;
|
||||
//import java.util.*;
|
||||
|
||||
/**
|
||||
* PDEEmitter: A class that can take an ANTLR Java AST and produce
|
||||
* reasonably formatted Java code from it. To use it, create a
|
||||
* PDEEmitter object, call setOut() if you want to print to something
|
||||
* other than System.out, and then call print(), passing the
|
||||
* AST. Typically, the AST node that you pass would be the root of a
|
||||
* tree - the ROOT_ID node that represents a Java file.
|
||||
*/
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PdeEmitter implements PdeTokenTypes
|
||||
{
|
||||
private PrintStream out = System.out;
|
||||
private PrintStream debug = System.err;
|
||||
//private static int ALL = -1;
|
||||
private java.util.Stack stack = new java.util.Stack();
|
||||
private static String[] tokenNames;
|
||||
private final static int ROOT_ID = 0;
|
||||
static {
|
||||
setupTokenNames();
|
||||
}
|
||||
|
||||
/*
|
||||
private static Hashtable publicMethods;
|
||||
private static final String publicMethodList[] = {
|
||||
"setup", "draw", //"loop",
|
||||
"mousePressed", "mouseReleased", "mouseClicked",
|
||||
"mouseEntered", "mouseExited",
|
||||
"mouseMoved", "mouseDragged",
|
||||
"keyPressed", "keyReleased", "keyTyped"
|
||||
};
|
||||
|
||||
static {
|
||||
publicMethods = new Hashtable();
|
||||
for (int i = 0; i < publicMethodList.length; i++) {
|
||||
publicMethods.put(publicMethodList[i], new Object());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Map each AST token type to a String
|
||||
private static void setupTokenNames() {
|
||||
tokenNames = new String[200];
|
||||
for (int i=0; i<tokenNames.length; i++) {
|
||||
tokenNames[i] = "ERROR:" + i;
|
||||
}
|
||||
|
||||
tokenNames[POST_INC]="++";
|
||||
tokenNames[POST_DEC]="--";
|
||||
tokenNames[UNARY_MINUS]="-";
|
||||
tokenNames[UNARY_PLUS]="+";
|
||||
tokenNames[STAR]="*";
|
||||
tokenNames[ASSIGN]="=";
|
||||
tokenNames[PLUS_ASSIGN]="+=";
|
||||
tokenNames[MINUS_ASSIGN]="-=";
|
||||
tokenNames[STAR_ASSIGN]="*=";
|
||||
tokenNames[DIV_ASSIGN]="/=";
|
||||
tokenNames[MOD_ASSIGN]="%=";
|
||||
tokenNames[SR_ASSIGN]=">>=";
|
||||
tokenNames[BSR_ASSIGN]=">>>=";
|
||||
tokenNames[SL_ASSIGN]="<<=";
|
||||
tokenNames[BAND_ASSIGN]="&=";
|
||||
tokenNames[BXOR_ASSIGN]="^=";
|
||||
tokenNames[BOR_ASSIGN]="|=";
|
||||
tokenNames[QUESTION]="?";
|
||||
tokenNames[LOR]="||";
|
||||
tokenNames[LAND]="&&";
|
||||
tokenNames[BOR]="|";
|
||||
tokenNames[BXOR]="^";
|
||||
tokenNames[BAND]="&";
|
||||
tokenNames[NOT_EQUAL]="!=";
|
||||
tokenNames[EQUAL]="==";
|
||||
tokenNames[LT]="<";
|
||||
tokenNames[GT]=">";
|
||||
tokenNames[LE]="<=";
|
||||
tokenNames[GE]=">=";
|
||||
tokenNames[SL]="<<";
|
||||
tokenNames[SR]=">>";
|
||||
tokenNames[BSR]=">>>";
|
||||
tokenNames[PLUS]="+";
|
||||
tokenNames[MINUS]="-";
|
||||
tokenNames[DIV]="/";
|
||||
tokenNames[MOD]="%";
|
||||
tokenNames[INC]="++";
|
||||
tokenNames[DEC]="--";
|
||||
tokenNames[BNOT]="~";
|
||||
tokenNames[LNOT]="!";
|
||||
tokenNames[FINAL]="final";
|
||||
tokenNames[ABSTRACT]="abstract";
|
||||
tokenNames[LITERAL_package]="package";
|
||||
tokenNames[LITERAL_import]="import";
|
||||
tokenNames[LITERAL_void]="void";
|
||||
tokenNames[LITERAL_boolean]="boolean";
|
||||
tokenNames[LITERAL_byte]="byte";
|
||||
tokenNames[LITERAL_char]="char";
|
||||
tokenNames[LITERAL_short]="short";
|
||||
tokenNames[LITERAL_int]="int";
|
||||
tokenNames[LITERAL_float]="float";
|
||||
tokenNames[LITERAL_long]="long";
|
||||
tokenNames[LITERAL_double]="double";
|
||||
tokenNames[LITERAL_private]="private";
|
||||
tokenNames[LITERAL_public]="public";
|
||||
tokenNames[LITERAL_protected]="protected";
|
||||
tokenNames[LITERAL_static]="static";
|
||||
tokenNames[LITERAL_transient]="transient";
|
||||
tokenNames[LITERAL_native]="native";
|
||||
tokenNames[LITERAL_threadsafe]="threadsafe";
|
||||
tokenNames[LITERAL_synchronized]="synchronized";
|
||||
tokenNames[LITERAL_volatile]="volatile";
|
||||
tokenNames[LITERAL_class]="class";
|
||||
tokenNames[LITERAL_extends]="extends";
|
||||
tokenNames[LITERAL_interface]="interface";
|
||||
tokenNames[LITERAL_implements]="implements";
|
||||
tokenNames[LITERAL_throws]="throws";
|
||||
tokenNames[LITERAL_if]="if";
|
||||
tokenNames[LITERAL_else]="else";
|
||||
tokenNames[LITERAL_for]="for";
|
||||
tokenNames[LITERAL_while]="while";
|
||||
tokenNames[LITERAL_do]="do";
|
||||
tokenNames[LITERAL_break]="break";
|
||||
tokenNames[LITERAL_continue]="continue";
|
||||
tokenNames[LITERAL_return]="return";
|
||||
tokenNames[LITERAL_switch]="switch";
|
||||
tokenNames[LITERAL_throw]="throw";
|
||||
tokenNames[LITERAL_case]="case";
|
||||
tokenNames[LITERAL_default]="default";
|
||||
tokenNames[LITERAL_try]="try";
|
||||
tokenNames[LITERAL_finally]="finally";
|
||||
tokenNames[LITERAL_catch]="catch";
|
||||
tokenNames[LITERAL_instanceof]="instanceof";
|
||||
tokenNames[LITERAL_this]="this";
|
||||
tokenNames[LITERAL_super]="super";
|
||||
tokenNames[LITERAL_true]="true";
|
||||
tokenNames[LITERAL_false]="false";
|
||||
tokenNames[LITERAL_null]="null";
|
||||
tokenNames[LITERAL_new]="new";
|
||||
tokenNames[LITERAL_color]="int"; // PDE specific alias
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a PrintStream to print to. System.out is the default.
|
||||
* @param out the PrintStream to print to
|
||||
*/
|
||||
public void setOut(PrintStream out) {
|
||||
this.out = out;
|
||||
}
|
||||
private String name(AST ast) {
|
||||
return tokenNames[ast.getType()];
|
||||
}
|
||||
private String name(int type) {
|
||||
return tokenNames[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a child of the given AST that has the given type
|
||||
* @returns a child AST of the given type. If it can't find a child of the
|
||||
* given type, return null.
|
||||
*/
|
||||
private AST getChild(AST ast, int childType) {
|
||||
AST child = ast.getFirstChild();
|
||||
while (child != null) {
|
||||
if (child.getType() == childType) {
|
||||
// debug.println("getChild: found:" + name(ast));
|
||||
return child;
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the list of hidden tokens linked to after the AST node passed in.
|
||||
* Most hidden tokens are dumped from this function.
|
||||
*/
|
||||
private void dumpHiddenAfter(AST ast) {
|
||||
dumpHiddenTokens(((antlr.CommonASTWithHiddenTokens)ast).getHiddenAfter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the list of hidden tokens linked to before the AST node passed in.
|
||||
* The only time hidden tokens need to be dumped with this function is when
|
||||
* dealing parts of the tree where automatic tree construction was
|
||||
* turned off with the ! operator in the grammar file and the nodes were
|
||||
* manually constructed in such a way that the usual tokens don't have the
|
||||
* necessary hiddenAfter links.
|
||||
*/
|
||||
private void dumpHiddenBefore(AST ast) {
|
||||
|
||||
antlr.CommonHiddenStreamToken
|
||||
child = null,
|
||||
parent = ((antlr.CommonASTWithHiddenTokens)ast).getHiddenBefore();
|
||||
|
||||
// if there aren't any hidden tokens here, quietly return
|
||||
//
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// traverse back to the head of the list of tokens before this node
|
||||
do {
|
||||
child = parent;
|
||||
parent = child.getHiddenBefore();
|
||||
} while (parent != null);
|
||||
|
||||
// dump that list
|
||||
dumpHiddenTokens(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the list of hidden tokens linked to from the token passed in.
|
||||
*/
|
||||
private void dumpHiddenTokens(antlr.CommonHiddenStreamToken t) {
|
||||
for ( ; t != null ; t=PdePreprocessor.filter.getHiddenAfter(t) ) {
|
||||
out.print(t.getText());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the children of the given AST
|
||||
* @param ast The AST to print
|
||||
* @returns true iff anything was printed
|
||||
*/
|
||||
private boolean printChildren(AST ast) throws RunnerException {
|
||||
boolean ret = false;
|
||||
AST child = ast.getFirstChild();
|
||||
while (child != null) {
|
||||
ret = true;
|
||||
print(child);
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether an AST has any children or not.
|
||||
* @return true iff the AST has at least one child
|
||||
*/
|
||||
private boolean hasChildren(AST ast) {
|
||||
return (ast.getFirstChild() != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the best node in the subtree for printing. This really means
|
||||
* the next node which could potentially have hiddenBefore data. It's
|
||||
* usually the first printable leaf, but not always.
|
||||
*
|
||||
* @param includeThisNode Should this node be included in the search?
|
||||
* If false, only descendants are searched.
|
||||
*
|
||||
* @return the first printable leaf node in an AST
|
||||
*/
|
||||
private AST getBestPrintableNode(AST ast, boolean includeThisNode) {
|
||||
AST child;
|
||||
|
||||
if (includeThisNode) {
|
||||
child = ast;
|
||||
} else {
|
||||
child = ast.getFirstChild();
|
||||
}
|
||||
|
||||
if (child != null) {
|
||||
|
||||
switch (child.getType()) {
|
||||
|
||||
// the following node types are printing nodes that print before
|
||||
// any children, but then also recurse over children. So they
|
||||
// may have hiddenBefore chains that need to be printed first. Many
|
||||
// statements and all unary expression types qualify. Return these
|
||||
// nodes directly
|
||||
case CLASS_DEF:
|
||||
case LITERAL_if:
|
||||
case LITERAL_for:
|
||||
case LITERAL_while:
|
||||
case LITERAL_do:
|
||||
case LITERAL_break:
|
||||
case LITERAL_continue:
|
||||
case LITERAL_return:
|
||||
case LITERAL_switch:
|
||||
case LITERAL_try:
|
||||
case LITERAL_throw:
|
||||
case LITERAL_synchronized:
|
||||
case LITERAL_assert:
|
||||
case BNOT:
|
||||
case LNOT:
|
||||
case INC:
|
||||
case DEC:
|
||||
case UNARY_MINUS:
|
||||
case UNARY_PLUS:
|
||||
return child;
|
||||
|
||||
// Some non-terminal node types (at the moment, I only know of
|
||||
// MODIFIERS, but there may be other such types), can be
|
||||
// leaves in the tree but not have any children. If this is
|
||||
// such a node, move on to the next sibling.
|
||||
case MODIFIERS:
|
||||
if (child.getFirstChild() == null ) {
|
||||
return getBestPrintableNode(child.getNextSibling(), false);
|
||||
}
|
||||
// new jikes doesn't like fallthrough, so just duplicated here:
|
||||
return getBestPrintableNode(child, false);
|
||||
|
||||
default:
|
||||
return getBestPrintableNode(child, false);
|
||||
}
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a binary operator
|
||||
*/
|
||||
private void printBinaryOperator(AST ast) throws RunnerException {
|
||||
print(ast.getFirstChild());
|
||||
out.print(name(ast));
|
||||
dumpHiddenAfter(ast);
|
||||
print(ast.getFirstChild().getNextSibling());
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the given AST. Call this function to print your PDE code.
|
||||
*
|
||||
* It works by making recursive calls to print children.
|
||||
* So the code below is one big "switch" statement on the passed AST type.
|
||||
*/
|
||||
public void print (AST ast) throws RunnerException {
|
||||
if (ast == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AST parent = null;
|
||||
if (!stack.isEmpty()) {
|
||||
parent = (AST) stack.peek();
|
||||
}
|
||||
stack.push(ast);
|
||||
|
||||
AST child1 = ast.getFirstChild();
|
||||
AST child2 = null;
|
||||
AST child3 = null;
|
||||
if (child1 != null) {
|
||||
child2 = child1.getNextSibling();
|
||||
if (child2 != null) {
|
||||
child3 = child2.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
switch(ast.getType()) {
|
||||
// The top of the tree looks like this:
|
||||
// ROOT_ID "Whatever.java"
|
||||
// package
|
||||
// imports
|
||||
// class definition
|
||||
case ROOT_ID:
|
||||
dumpHiddenTokens(PdePreprocessor.filter.getInitialHiddenToken());
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
// supporting a "package" statement in a PDE program has
|
||||
// a bunch of issues with it that need to dealt in the compilation
|
||||
// code too, so this isn't actually tested.
|
||||
case PACKAGE_DEF:
|
||||
out.print("package");
|
||||
dumpHiddenAfter(ast);
|
||||
print(ast.getFirstChild());
|
||||
break;
|
||||
|
||||
// IMPORT has exactly one child
|
||||
case IMPORT:
|
||||
out.print("import");
|
||||
dumpHiddenAfter(ast);
|
||||
print(ast.getFirstChild());
|
||||
break;
|
||||
|
||||
case CLASS_DEF:
|
||||
case INTERFACE_DEF:
|
||||
print(getChild(ast, MODIFIERS));
|
||||
if (ast.getType() == CLASS_DEF) {
|
||||
out.print("class");
|
||||
} else {
|
||||
out.print("interface");
|
||||
}
|
||||
dumpHiddenBefore(getChild(ast, IDENT));
|
||||
print(getChild(ast, IDENT));
|
||||
print(getChild(ast, EXTENDS_CLAUSE));
|
||||
print(getChild(ast, IMPLEMENTS_CLAUSE));
|
||||
print(getChild(ast, OBJBLOCK));
|
||||
break;
|
||||
|
||||
case EXTENDS_CLAUSE:
|
||||
if (hasChildren(ast)) {
|
||||
out.print("extends");
|
||||
dumpHiddenBefore(getBestPrintableNode(ast, false));
|
||||
printChildren(ast);
|
||||
}
|
||||
break;
|
||||
|
||||
case IMPLEMENTS_CLAUSE:
|
||||
if (hasChildren(ast)) {
|
||||
out.print("implements");
|
||||
dumpHiddenBefore(getBestPrintableNode(ast, false));
|
||||
printChildren(ast);
|
||||
}
|
||||
break;
|
||||
|
||||
// DOT always has exactly two children.
|
||||
case DOT:
|
||||
print(child1);
|
||||
out.print(".");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child2);
|
||||
break;
|
||||
|
||||
case MODIFIERS:
|
||||
case OBJBLOCK:
|
||||
case CTOR_DEF:
|
||||
//case METHOD_DEF:
|
||||
case PARAMETERS:
|
||||
case PARAMETER_DEF:
|
||||
case VARIABLE_DEF:
|
||||
case TYPE:
|
||||
case SLIST:
|
||||
case ELIST:
|
||||
case ARRAY_DECLARATOR:
|
||||
case TYPECAST:
|
||||
case EXPR:
|
||||
case ARRAY_INIT:
|
||||
case FOR_INIT:
|
||||
case FOR_CONDITION:
|
||||
case FOR_ITERATOR:
|
||||
case METHOD_CALL:
|
||||
case INSTANCE_INIT:
|
||||
case INDEX_OP:
|
||||
case SUPER_CTOR_CALL:
|
||||
case CTOR_CALL:
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case METHOD_DEF:
|
||||
// kids seem to be: MODIFIERS TYPE setup PARAMETERS
|
||||
//AST parent = (AST) stack.peek();
|
||||
AST modifiersChild = ast.getFirstChild();
|
||||
AST typeChild = modifiersChild.getNextSibling();
|
||||
AST methodNameChild = typeChild.getNextSibling();
|
||||
AST parametersChild = methodNameChild.getNextSibling();
|
||||
|
||||
// to output, use print(child) on each of the four
|
||||
|
||||
String methodName = methodNameChild.getText();
|
||||
if (methodName.equals("main")) {
|
||||
PdePreprocessor.foundMain = true;
|
||||
}
|
||||
|
||||
/*
|
||||
// 1. figure out if this is setup, draw, or loop
|
||||
String methodName = methodNameChild.getText();
|
||||
if (publicMethods.get(methodName) != null) {
|
||||
// make sure this feller is public
|
||||
boolean foundPublic = false;
|
||||
AST child = modifiersChild.getFirstChild();
|
||||
while (child != null) {
|
||||
if (child.getText().equals("public")) {
|
||||
foundPublic = true;
|
||||
child = null;
|
||||
} else {
|
||||
//out.print("." + child.getText() + ".");
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
if (!foundPublic) {
|
||||
out.print("public ");
|
||||
}
|
||||
*/
|
||||
|
||||
// if this method doesn't have a specifier, make it public
|
||||
// (useful for setup/keyPressed/etc)
|
||||
boolean foundSpecifier = false;
|
||||
AST child = modifiersChild.getFirstChild();
|
||||
while (child != null) {
|
||||
String childText = child.getText();
|
||||
if (childText.equals("public") ||
|
||||
childText.equals("protected") ||
|
||||
childText.equals("private")) {
|
||||
foundSpecifier = true;
|
||||
child = null;
|
||||
} else {
|
||||
//out.print("." + child.getText() + ".");
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
if (!foundSpecifier) {
|
||||
out.print("public ");
|
||||
}
|
||||
printChildren(ast); // everything is fine
|
||||
break;
|
||||
|
||||
// if we have two children, it's of the form "a=0"
|
||||
// if just one child, it's of the form "=0" (where the
|
||||
// lhs is above this AST).
|
||||
case ASSIGN:
|
||||
if (child2 != null) {
|
||||
print(child1);
|
||||
out.print("=");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child2);
|
||||
}
|
||||
else {
|
||||
out.print("=");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1);
|
||||
}
|
||||
break;
|
||||
|
||||
// binary operators:
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case NOT_EQUAL:
|
||||
case EQUAL:
|
||||
case LT:
|
||||
case GT:
|
||||
case LE:
|
||||
case GE:
|
||||
case LOR:
|
||||
case LAND:
|
||||
case BOR:
|
||||
case BXOR:
|
||||
case BAND:
|
||||
case SL:
|
||||
case SR:
|
||||
case BSR:
|
||||
case LITERAL_instanceof:
|
||||
case PLUS_ASSIGN:
|
||||
case MINUS_ASSIGN:
|
||||
case STAR_ASSIGN:
|
||||
case DIV_ASSIGN:
|
||||
case MOD_ASSIGN:
|
||||
case SR_ASSIGN:
|
||||
case BSR_ASSIGN:
|
||||
case SL_ASSIGN:
|
||||
case BAND_ASSIGN:
|
||||
case BXOR_ASSIGN:
|
||||
case BOR_ASSIGN:
|
||||
printBinaryOperator(ast);
|
||||
break;
|
||||
|
||||
|
||||
case LITERAL_for:
|
||||
out.print(name(ast));
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case POST_INC:
|
||||
case POST_DEC:
|
||||
print(child1);
|
||||
out.print(name(ast));
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
// unary operators:
|
||||
case BNOT:
|
||||
case LNOT:
|
||||
case INC:
|
||||
case DEC:
|
||||
case UNARY_MINUS:
|
||||
case UNARY_PLUS:
|
||||
out.print(name(ast));
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1);
|
||||
break;
|
||||
|
||||
case LITERAL_new:
|
||||
out.print("new");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1);
|
||||
print(child2);
|
||||
// "new String[] {...}": the stuff in {} is child3
|
||||
if (child3 != null) {
|
||||
print(child3);
|
||||
}
|
||||
break;
|
||||
|
||||
case LITERAL_return:
|
||||
out.print("return");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1);
|
||||
break;
|
||||
|
||||
case STATIC_INIT:
|
||||
out.print("static");
|
||||
dumpHiddenBefore(getBestPrintableNode(ast, false));
|
||||
print(child1);
|
||||
break;
|
||||
|
||||
case LITERAL_switch:
|
||||
out.print("switch");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case CASE_GROUP:
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_case:
|
||||
out.print("case");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_default:
|
||||
out.print("default");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case NUM_INT:
|
||||
case CHAR_LITERAL:
|
||||
case STRING_LITERAL:
|
||||
case NUM_FLOAT:
|
||||
case NUM_LONG:
|
||||
out.print(ast.getText());
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_synchronized: // 0137 to fix bug #136
|
||||
out.print(name(ast));
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_private:
|
||||
case LITERAL_public:
|
||||
case LITERAL_protected:
|
||||
case LITERAL_static:
|
||||
case LITERAL_transient:
|
||||
case LITERAL_native:
|
||||
case LITERAL_threadsafe:
|
||||
//case LITERAL_synchronized: // 0137 to fix bug #136
|
||||
case LITERAL_volatile:
|
||||
case FINAL:
|
||||
case ABSTRACT:
|
||||
case LITERAL_package:
|
||||
case LITERAL_void:
|
||||
case LITERAL_boolean:
|
||||
case LITERAL_byte:
|
||||
case LITERAL_char:
|
||||
case LITERAL_short:
|
||||
case LITERAL_int:
|
||||
case LITERAL_float:
|
||||
case LITERAL_long:
|
||||
case LITERAL_double:
|
||||
case LITERAL_true:
|
||||
case LITERAL_false:
|
||||
case LITERAL_null:
|
||||
case SEMI:
|
||||
case LITERAL_this:
|
||||
case LITERAL_super:
|
||||
case LITERAL_continue:
|
||||
case LITERAL_break:
|
||||
out.print(name(ast));
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
case EMPTY_STAT:
|
||||
case EMPTY_FIELD:
|
||||
break;
|
||||
|
||||
// yuck: Distinguish between "import x.y.*" and "x = 1 * 3"
|
||||
case STAR:
|
||||
if (hasChildren(ast)) { // the binary mult. operator
|
||||
printBinaryOperator(ast);
|
||||
}
|
||||
else { // the special "*" in import:
|
||||
out.print("*");
|
||||
dumpHiddenAfter(ast);
|
||||
}
|
||||
break;
|
||||
|
||||
case LITERAL_throws:
|
||||
out.print("throws");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_if:
|
||||
out.print("if");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1); // the "if" condition: an EXPR
|
||||
print(child2); // the "then" clause is an SLIST
|
||||
if (child3 != null) {
|
||||
out.print("else");
|
||||
dumpHiddenBefore(getBestPrintableNode(child3, true));
|
||||
print(child3); // optional "else" clause: an SLIST
|
||||
}
|
||||
break;
|
||||
|
||||
case LITERAL_while:
|
||||
out.print("while");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_do:
|
||||
out.print("do");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1); // an SLIST
|
||||
out.print("while");
|
||||
dumpHiddenBefore(getBestPrintableNode(child2, false));
|
||||
print(child2); // an EXPR
|
||||
break;
|
||||
|
||||
case LITERAL_try:
|
||||
out.print("try");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_catch:
|
||||
out.print("catch");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
// the first child is the "try" and the second is the SLIST
|
||||
case LITERAL_finally:
|
||||
out.print("finally");
|
||||
dumpHiddenAfter(ast);
|
||||
printChildren(ast);
|
||||
break;
|
||||
|
||||
case LITERAL_throw:
|
||||
out.print("throw");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child1);
|
||||
break;
|
||||
|
||||
// the dreaded trinary operator
|
||||
case QUESTION:
|
||||
print(child1);
|
||||
out.print("?");
|
||||
dumpHiddenAfter(ast);
|
||||
print(child2);
|
||||
print(child3);
|
||||
break;
|
||||
|
||||
// pde specific or modified tokens start here
|
||||
|
||||
// Image -> BImage, Font -> BFont as appropriate
|
||||
case IDENT:
|
||||
/*
|
||||
if (ast.getText().equals("Image") &&
|
||||
Preferences.getBoolean("preproc.substitute_image")) { //, true)) {
|
||||
out.print("BImage");
|
||||
} else if (ast.getText().equals("Font") &&
|
||||
Preferences.getBoolean("preproc.substitute_font")) { //, true)) {
|
||||
out.print("BFont");
|
||||
} else {
|
||||
*/
|
||||
out.print(ast.getText());
|
||||
//}
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
// the color datatype is just an alias for int
|
||||
case LITERAL_color:
|
||||
out.print("int");
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
case WEBCOLOR_LITERAL:
|
||||
if (ast.getText().length() != 6) {
|
||||
System.err.println("Internal error: incorrect length of webcolor " +
|
||||
"literal should have been detected sooner.");
|
||||
break;
|
||||
}
|
||||
out.print("0xff" + ast.getText());
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
// allow for stuff like int(43.2).
|
||||
case CONSTRUCTOR_CAST:
|
||||
|
||||
AST nonTerminalTypeNode = child1;
|
||||
AST terminalTypeNode = child1.getFirstChild();
|
||||
AST exprToCast = child2;
|
||||
|
||||
/*
|
||||
// if this is a string type, add .valueOf()
|
||||
if (nonTerminalTypeNode.getType() == PdeRecognizer.TYPE &&
|
||||
terminalTypeNode.getText().equals("String")) {
|
||||
|
||||
out.print(terminalTypeNode.getText() + ".valueOf");
|
||||
dumpHiddenAfter(terminalTypeNode);
|
||||
print(exprToCast);
|
||||
|
||||
// if the expresion to be cast is a string literal, try and parse it.
|
||||
//
|
||||
// ideally, we'd be able to do this for all expressions with a
|
||||
// string type, not just string literals. however, the parser
|
||||
// doesn't currently track expression type, and for full
|
||||
// functionality, we'd need to do semantic analysis to handle
|
||||
// imports so that we could know the return types of method calls.
|
||||
//
|
||||
} else if (exprToCast.getFirstChild().getType() == STRING_LITERAL ) {
|
||||
|
||||
switch (terminalTypeNode.getType()) {
|
||||
|
||||
case PdeRecognizer.LITERAL_byte:
|
||||
out.print("Byte.parseByte");
|
||||
dumpHiddenAfter(terminalTypeNode);
|
||||
print(exprToCast);
|
||||
break;
|
||||
|
||||
case PdeRecognizer.LITERAL_double:
|
||||
out.print("(new Double");
|
||||
dumpHiddenAfter(terminalTypeNode);
|
||||
out.print(exprToCast.getFirstChild().getText() + ").doubleValue()");
|
||||
dumpHiddenAfter(exprToCast.getFirstChild());
|
||||
break;
|
||||
|
||||
case PdeRecognizer.LITERAL_float:
|
||||
out.print("(new Float");
|
||||
dumpHiddenAfter(terminalTypeNode);
|
||||
out.print(exprToCast.getFirstChild().getText() + ").floatValue()");
|
||||
dumpHiddenAfter(exprToCast.getFirstChild());
|
||||
break;
|
||||
|
||||
case PdeRecognizer.LITERAL_int:
|
||||
case PdeRecognizer.LITERAL_color:
|
||||
out.print("Integer.parseInt");
|
||||
dumpHiddenAfter(terminalTypeNode);
|
||||
print(exprToCast);
|
||||
break;
|
||||
|
||||
case PdeRecognizer.LITERAL_long:
|
||||
out.print("Long.parseLong");
|
||||
break;
|
||||
|
||||
case PdeRecognizer.LITERAL_short:
|
||||
out.print("Short.parseShort");
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RunnerException(Compiler.SUPER_BADNESS);
|
||||
}
|
||||
|
||||
// for builtin types, use regular casting syntax
|
||||
} else {
|
||||
*/
|
||||
|
||||
// result of below is (int)(4.0
|
||||
//out.print("(");
|
||||
//out.print(terminalTypeNode.getText() + ")"); // typename
|
||||
//dumpHiddenAfter(terminalTypeNode);
|
||||
//print(exprToCast);
|
||||
//}
|
||||
|
||||
//out.print("(");
|
||||
String pooType = terminalTypeNode.getText();
|
||||
out.print("PApplet.parse" +
|
||||
Character.toUpperCase(pooType.charAt(0)) +
|
||||
pooType.substring(1));
|
||||
dumpHiddenAfter(terminalTypeNode); // the left paren
|
||||
print(exprToCast);
|
||||
//out.print("x)");
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// making floating point literals default to floats, not doubles
|
||||
case NUM_DOUBLE:
|
||||
out.print(ast.getText());
|
||||
if (Preferences.getBoolean("preproc.substitute_floats")) { //, true) ) {
|
||||
out.print("f");
|
||||
}
|
||||
dumpHiddenAfter(ast);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
debug.println("Invalid type:" + ast.getType());
|
||||
break;
|
||||
|
||||
|
||||
/* The following are tokens, but I don't think JavaRecognizer
|
||||
ever produces an AST with one of these types:
|
||||
case COMMA:
|
||||
case LITERAL_implements:
|
||||
case LITERAL_class:
|
||||
case LITERAL_extends:
|
||||
case EOF:
|
||||
case NULL_TREE_LOOKAHEAD:
|
||||
case BLOCK:
|
||||
case LABELED_STAT: // refuse to implement on moral grounds :)
|
||||
case LITERAL_import:
|
||||
case LBRACK:
|
||||
case RBRACK:
|
||||
case LCURLY:
|
||||
case RCURLY:
|
||||
case LPAREN:
|
||||
case RPAREN:
|
||||
case LITERAL_else: // else is a child of "if" AST
|
||||
case COLON: // part of the trinary operator
|
||||
case WS: // whitespace
|
||||
case ESC:
|
||||
case HEX_DIGIT:
|
||||
case VOCAB:
|
||||
|
||||
case EXPONENT: // exponents and float suffixes are left in the NUM_FLOAT
|
||||
case FLOAT_SUFFIX
|
||||
*/
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
}
|
||||
}
|
511
app/src/processing/app/preproc/PdePreprocessor.java
Normal file
511
app/src/processing/app/preproc/PdePreprocessor.java
Normal file
@ -0,0 +1,511 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
PdePreprocessor - wrapper for default ANTLR-generated parser
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
ANTLR-generated parser and several supporting classes written
|
||||
by Dan Mosedale via funding from the Interaction Institute IVREA.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.preproc;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import antlr.*;
|
||||
import antlr.collections.*;
|
||||
|
||||
|
||||
/**
|
||||
* Class that orchestrates preprocessing p5 syntax into straight Java.
|
||||
* <P/>
|
||||
* <B>Current Preprocessor Subsitutions:</B>
|
||||
* <UL>
|
||||
* <LI>any function not specified as being protected or private will
|
||||
* be made 'public'. this means that <TT>void setup()</TT> becomes
|
||||
* <TT>public void setup()</TT>. This is important to note when
|
||||
* coding with core.jar outside of the PDE.
|
||||
* <LI><TT>compiler.substitute_floats</TT> (currently "substitute_f")
|
||||
* treat doubles as floats, i.e. 12.3 becomes 12.3f so that people
|
||||
* don't have to add f after their numbers all the time since it's
|
||||
* confusing for beginners.
|
||||
* <LI><TT>compiler.enhanced_casting</TT> byte(), char(), int(), float()
|
||||
* works for casting. this is basic in the current implementation, but
|
||||
* should be expanded as described above. color() works similarly to int(),
|
||||
* however there is also a *function* called color(r, g, b) in p5.
|
||||
* <LI><TT>compiler.color_datatype</TT> 'color' is aliased to 'int'
|
||||
* as a datatype to represent ARGB packed into a single int, commonly
|
||||
* used in p5 for pixels[] and other color operations. this is just a
|
||||
* search/replace type thing, and it can be used interchangeably with int.
|
||||
* <LI><TT>compiler.web_colors</TT> (currently "inline_web_colors")
|
||||
* color c = #cc0080; should unpack to 0xffcc0080 (the ff at the top is
|
||||
* so that the color is opaque), which is just an int.
|
||||
* </UL>
|
||||
* <B>Other preprocessor functionality</B>
|
||||
* <UL>
|
||||
* <LI>detects what 'mode' the program is in: static (no function
|
||||
* brackets at all, just assumes everything is in draw), active
|
||||
* (setup plus draw or loop), and java mode (full java support).
|
||||
* http://processing.org/reference/environment/
|
||||
* </UL>
|
||||
* <P/>
|
||||
* The PDE Preprocessor is based on the Java Grammar that comes with
|
||||
* ANTLR 2.7.2. Moving it forward to a new version of the grammar
|
||||
* shouldn't be too difficult.
|
||||
* <P/>
|
||||
* Here's some info about the various files in this directory:
|
||||
* <P/>
|
||||
* <TT>java.g:</TT> this is the ANTLR grammar for Java 1.3/1.4 from the
|
||||
* ANTLR distribution. It is in the public domain. The only change to
|
||||
* this file from the original this file is the uncommenting of the
|
||||
* clauses required to support assert().
|
||||
* <P/>
|
||||
* <TT>java.tree.g:</TT> this describes the Abstract Syntax Tree (AST)
|
||||
* generated by java.g. It is only here as a reference for coders hacking
|
||||
* on the preprocessor, it is not built or used at all. Note that pde.g
|
||||
* overrides some of the java.g rules so that in PDE ASTs, there are a
|
||||
* few minor differences. Also in the public domain.
|
||||
* <P/>
|
||||
* <TT>pde.g:</TT> this is the grammar and lexer for the PDE language
|
||||
* itself. It subclasses the java.g grammar and lexer. There are a couple
|
||||
* of overrides to java.g that I hope to convince the ANTLR folks to fold
|
||||
* back into their grammar, but most of this file is highly specific to
|
||||
* PDE itself.
|
||||
* <TT>PdeEmitter.java:</TT> this class traverses the AST generated by
|
||||
* the PDE Recognizer, and emits it as Java code, doing any necessary
|
||||
* transformations along the way. It is based on JavaEmitter.java,
|
||||
* available from antlr.org, written by Andy Tripp <atripp@comcast.net>,
|
||||
* who has given permission for it to be distributed under the GPL.
|
||||
* <P/>
|
||||
* <TT>ExtendedCommonASTWithHiddenTokens.java:</TT> this adds a necessary
|
||||
* initialize() method, as well as a number of methods to allow for XML
|
||||
* serialization of the parse tree in a such a way that the hidden tokens
|
||||
* are visible. Much of the code is taken from the original
|
||||
* CommonASTWithHiddenTokens class. I hope to convince the ANTLR folks
|
||||
* to fold these changes back into that class so that this file will be
|
||||
* unnecessary.
|
||||
* <P/>
|
||||
* <TT>TokenStreamCopyingHiddenTokenFilter.java:</TT> this class provides
|
||||
* TokenStreamHiddenTokenFilters with the concept of tokens which can be
|
||||
* copied so that they are seen by both the hidden token stream as well
|
||||
* as the parser itself. This is useful when one wants to use an
|
||||
* existing parser (like the Java parser included with ANTLR) that throws
|
||||
* away some tokens to create a parse tree which can be used to spit out
|
||||
* a copy of the code with only minor modifications. Partially derived
|
||||
* from ANTLR code. I hope to convince the ANTLR folks to fold this
|
||||
* functionality back into ANTLR proper as well.
|
||||
* <P/>
|
||||
* <TT>whitespace_test.pde:</TT> a torture test to ensure that the
|
||||
* preprocessor is correctly preserving whitespace, comments, and other
|
||||
* hidden tokens correctly. See the comments in the code for details about
|
||||
* how to run the test.
|
||||
* <P/>
|
||||
* All other files in this directory are generated at build time by ANTLR
|
||||
* itself. The ANTLR manual goes into a fair amount of detail about the
|
||||
* what each type of file is for.
|
||||
* <P/>
|
||||
*/
|
||||
public class PdePreprocessor {
|
||||
|
||||
String[] defaultImports;
|
||||
|
||||
// these ones have the .* at the end, since a class name might be at the end
|
||||
// instead of .* which would make trouble other classes using this can lop
|
||||
// off the . and anything after it to produce a package name consistently.
|
||||
//public String extraImports[];
|
||||
ArrayList<String> programImports;
|
||||
|
||||
// imports just from the code folder, treated differently
|
||||
// than the others, since the imports are auto-generated.
|
||||
ArrayList<String> codeFolderImports;
|
||||
|
||||
static public final int STATIC = 0; // formerly BEGINNER
|
||||
static public final int ACTIVE = 1; // formerly INTERMEDIATE
|
||||
static public final int JAVA = 2; // formerly ADVANCED
|
||||
|
||||
// static to make it easier for the antlr preproc to get at it
|
||||
static public int programType;
|
||||
static public boolean foundMain;
|
||||
|
||||
String indent;
|
||||
|
||||
PrintStream stream;
|
||||
Reader programReader;
|
||||
String buildPath;
|
||||
String name;
|
||||
|
||||
// used for calling the ASTFactory to get the root node
|
||||
private static final int ROOT_ID = 0;
|
||||
|
||||
/**
|
||||
* Used by PdeEmitter.dumpHiddenTokens()
|
||||
*/
|
||||
public static TokenStreamCopyingHiddenTokenFilter filter;
|
||||
|
||||
static String advClassName = "";
|
||||
|
||||
|
||||
/**
|
||||
* Setup a new preprocessor.
|
||||
*/
|
||||
public PdePreprocessor() { }
|
||||
|
||||
|
||||
public int writePrefix(String program, String buildPath,
|
||||
String name, String codeFolderPackages[]) throws FileNotFoundException {
|
||||
this.buildPath = buildPath;
|
||||
this.name = name;
|
||||
|
||||
int tabSize = Preferences.getInteger("editor.tabs.size");
|
||||
char[] indentChars = new char[tabSize];
|
||||
Arrays.fill(indentChars, ' ');
|
||||
indent = new String(indentChars);
|
||||
|
||||
// need to reset whether or not this has a main()
|
||||
foundMain = false;
|
||||
|
||||
// if the program ends with no CR or LF an OutOfMemoryError will happen.
|
||||
// not gonna track down the bug now, so here's a hack for it:
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=5
|
||||
program += "\n";
|
||||
|
||||
// if the program ends with an unterminated multi-line comment,
|
||||
// an OutOfMemoryError or NullPointerException will happen.
|
||||
// again, not gonna bother tracking this down, but here's a hack.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=16
|
||||
Sketch.scrubComments(program);
|
||||
// this returns the scrubbed version, but more important for this
|
||||
// function, it'll check to see if there are errors with the comments.
|
||||
|
||||
if (Preferences.getBoolean("preproc.substitute_unicode")) {
|
||||
// check for non-ascii chars (these will be/must be in unicode format)
|
||||
char p[] = program.toCharArray();
|
||||
int unicodeCount = 0;
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (p[i] > 127) unicodeCount++;
|
||||
}
|
||||
// if non-ascii chars are in there, convert to unicode escapes
|
||||
if (unicodeCount != 0) {
|
||||
// add unicodeCount * 5.. replacing each unicode char
|
||||
// with six digit uXXXX sequence (xxxx is in hex)
|
||||
// (except for nbsp chars which will be a replaced with a space)
|
||||
int index = 0;
|
||||
char p2[] = new char[p.length + unicodeCount*5];
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (p[i] < 128) {
|
||||
p2[index++] = p[i];
|
||||
|
||||
} else if (p[i] == 160) { // unicode for non-breaking space
|
||||
p2[index++] = ' ';
|
||||
|
||||
} else {
|
||||
int c = p[i];
|
||||
p2[index++] = '\\';
|
||||
p2[index++] = 'u';
|
||||
char str[] = Integer.toHexString(c).toCharArray();
|
||||
// add leading zeros, so that the length is 4
|
||||
//for (int i = 0; i < 4 - str.length; i++) p2[index++] = '0';
|
||||
for (int m = 0; m < 4 - str.length; m++) p2[index++] = '0';
|
||||
System.arraycopy(str, 0, p2, index, str.length);
|
||||
index += str.length;
|
||||
}
|
||||
}
|
||||
program = new String(p2, 0, index);
|
||||
}
|
||||
}
|
||||
|
||||
// These may change in-between (if the prefs panel adds this option)
|
||||
// so grab them here on construction.
|
||||
String prefsLine = Preferences.get("preproc.imports");
|
||||
defaultImports = PApplet.splitTokens(prefsLine, ", ");
|
||||
|
||||
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
|
||||
String importRegexp = "(?:^|;)\\s*(import\\s+)(\\S+)(\\s*;)";
|
||||
programImports = new ArrayList<String>();
|
||||
|
||||
do {
|
||||
String[] pieces = PApplet.match(program, importRegexp);
|
||||
// Stop the loop if we've removed all the importy lines
|
||||
if (pieces == null) break;
|
||||
|
||||
String piece = pieces[1] + pieces[2] + pieces[3];
|
||||
int len = piece.length(); // how much to trim out
|
||||
|
||||
programImports.add(pieces[2]); // the package name
|
||||
int idx = program.indexOf(piece);
|
||||
// just remove altogether?
|
||||
program = program.substring(0, idx) + program.substring(idx + len);
|
||||
|
||||
} while (true);
|
||||
|
||||
codeFolderImports = new ArrayList<String>();
|
||||
if (codeFolderPackages != null) {
|
||||
for (String item : codeFolderPackages) {
|
||||
codeFolderImports.add(item + ".*");
|
||||
}
|
||||
}
|
||||
// do this after the program gets re-combobulated
|
||||
this.programReader = new StringReader(program);
|
||||
|
||||
File streamFile = new File(buildPath, name + ".java");
|
||||
stream = new PrintStream(new FileOutputStream(streamFile));
|
||||
int importsLength = writeImports(stream);
|
||||
|
||||
// return the length of the imports plus the extra lines for declarations
|
||||
return importsLength + 2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* preprocesses a pde file and write out a java file
|
||||
* @return the classname of the exported Java
|
||||
*/
|
||||
//public String write(String program, String buildPath, String name,
|
||||
// String extraImports[]) throws java.lang.Exception {
|
||||
public String write() throws java.lang.Exception {
|
||||
// create a lexer with the stream reader, and tell it to handle
|
||||
// hidden tokens (eg whitespace, comments) since we want to pass these
|
||||
// through so that the line numbers when the compiler reports errors
|
||||
// match those that will be highlighted in the PDE IDE
|
||||
//
|
||||
PdeLexer lexer = new PdeLexer(programReader);
|
||||
lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken");
|
||||
|
||||
// create the filter for hidden tokens and specify which tokens to
|
||||
// hide and which to copy to the hidden text
|
||||
//
|
||||
filter = new TokenStreamCopyingHiddenTokenFilter(lexer);
|
||||
filter.hide(PdeRecognizer.SL_COMMENT);
|
||||
filter.hide(PdeRecognizer.ML_COMMENT);
|
||||
filter.hide(PdeRecognizer.WS);
|
||||
filter.copy(PdeRecognizer.SEMI);
|
||||
filter.copy(PdeRecognizer.LPAREN);
|
||||
filter.copy(PdeRecognizer.RPAREN);
|
||||
filter.copy(PdeRecognizer.LCURLY);
|
||||
filter.copy(PdeRecognizer.RCURLY);
|
||||
filter.copy(PdeRecognizer.COMMA);
|
||||
filter.copy(PdeRecognizer.RBRACK);
|
||||
filter.copy(PdeRecognizer.LBRACK);
|
||||
filter.copy(PdeRecognizer.COLON);
|
||||
|
||||
// create a parser and set what sort of AST should be generated
|
||||
//
|
||||
PdeRecognizer parser = new PdeRecognizer(filter);
|
||||
|
||||
// use our extended AST class
|
||||
//
|
||||
parser.setASTNodeClass("antlr.ExtendedCommonASTWithHiddenTokens");
|
||||
|
||||
// start parsing at the compilationUnit non-terminal
|
||||
//
|
||||
parser.pdeProgram();
|
||||
|
||||
// set up the AST for traversal by PdeEmitter
|
||||
//
|
||||
ASTFactory factory = new ASTFactory();
|
||||
AST parserAST = parser.getAST();
|
||||
AST rootNode = factory.create(ROOT_ID, "AST ROOT");
|
||||
rootNode.setFirstChild(parserAST);
|
||||
|
||||
// unclear if this actually works, but it's worth a shot
|
||||
//
|
||||
//((CommonAST)parserAST).setVerboseStringConversion(
|
||||
// true, parser.getTokenNames());
|
||||
// (made to use the static version because of jikes 1.22 warning)
|
||||
CommonAST.setVerboseStringConversion(true, parser.getTokenNames());
|
||||
|
||||
// if this is an advanced program, the classname is already defined.
|
||||
//
|
||||
if (programType == JAVA) {
|
||||
name = getFirstClassName(parserAST);
|
||||
}
|
||||
|
||||
// if 'null' was passed in for the name, but this isn't
|
||||
// a 'java' mode class, then there's a problem, so punt.
|
||||
//
|
||||
if (name == null) return null;
|
||||
|
||||
// output the code
|
||||
//
|
||||
PdeEmitter emitter = new PdeEmitter();
|
||||
//writeHeader(stream, extraImports, name);
|
||||
writeDeclaration(stream, name);
|
||||
|
||||
emitter.setOut(stream);
|
||||
emitter.print(rootNode);
|
||||
|
||||
writeFooter(stream, name);
|
||||
stream.close();
|
||||
|
||||
// if desired, serialize the parse tree to an XML file. can
|
||||
// be viewed usefully with Mozilla or IE
|
||||
|
||||
if (Preferences.getBoolean("preproc.output_parse_tree")) {
|
||||
writeParseTree("parseTree.xml", parserAST);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
protected void writeParseTree(String filename, AST ast) {
|
||||
try {
|
||||
PrintStream stream = new PrintStream(new FileOutputStream(filename));
|
||||
stream.println("<?xml version=\"1.0\"?>");
|
||||
stream.println("<document>");
|
||||
OutputStreamWriter writer = new OutputStreamWriter(stream);
|
||||
if (ast != null) {
|
||||
((CommonAST) ast).xmlSerialize(writer);
|
||||
}
|
||||
writer.flush();
|
||||
stream.println("</document>");
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int writeImports(PrintStream out) {
|
||||
out.println("import processing.core.*; ");
|
||||
out.println("import processing.xml.*; ");
|
||||
out.println();
|
||||
int count = 3;
|
||||
|
||||
if (programImports.size() != 0) {
|
||||
for (String item : programImports) {
|
||||
out.println("import " + item + "; ");
|
||||
}
|
||||
out.println();
|
||||
count += programImports.size() + 1;
|
||||
}
|
||||
|
||||
if (codeFolderImports.size() != 0) {
|
||||
for (String item : codeFolderImports) {
|
||||
out.println("import " + item + "; ");
|
||||
}
|
||||
out.println();
|
||||
count += codeFolderImports.size() + 1;
|
||||
}
|
||||
|
||||
for (String item : defaultImports) {
|
||||
out.println("import " + item + ".*; ");
|
||||
}
|
||||
out.println();
|
||||
count += defaultImports.length + 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write any required header material (eg imports, class decl stuff)
|
||||
*
|
||||
* @param out PrintStream to write it to.
|
||||
* @param exporting Is this being exported from PDE?
|
||||
* @param name Name of the class being created.
|
||||
*/
|
||||
void writeDeclaration(PrintStream out, String className) {
|
||||
|
||||
String indent = " ";
|
||||
|
||||
if (programType == JAVA) {
|
||||
// Print two blank lines so that the offset doesn't change
|
||||
out.println();
|
||||
out.println();
|
||||
|
||||
} else if (programType == ACTIVE) {
|
||||
// Print an extra blank line so the offset is identical to the others
|
||||
out.println("public class " + className + " extends PApplet {");
|
||||
out.println();
|
||||
|
||||
} else if (programType == STATIC) {
|
||||
out.println("public class " + className + " extends PApplet {");
|
||||
out.print(indent + "public void setup() {");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write any necessary closing text.
|
||||
*
|
||||
* @param out PrintStream to write it to.
|
||||
*/
|
||||
void writeFooter(PrintStream out, String className) {
|
||||
|
||||
if (programType == STATIC) {
|
||||
// close off draw() definition
|
||||
out.println(indent + "noLoop();");
|
||||
out.println("} ");
|
||||
}
|
||||
|
||||
if ((programType == STATIC) || (programType == ACTIVE)) {
|
||||
if (!PdePreprocessor.foundMain) {
|
||||
out.println(indent + "static public void main(String args[]) {");
|
||||
out.print(indent + indent + "PApplet.main(new String[] { ");
|
||||
|
||||
if (Preferences.getBoolean("export.application.fullscreen")) {
|
||||
out.print("\"" + PApplet.ARGS_PRESENT + "\", ");
|
||||
|
||||
String farbe = Preferences.get("run.present.bgcolor");
|
||||
out.print("\"" + PApplet.ARGS_BGCOLOR + "=" + farbe + "\", ");
|
||||
|
||||
if (Preferences.getBoolean("export.application.stop")) {
|
||||
farbe = Preferences.get("run.present.stop.color");
|
||||
out.print("\"" + PApplet.ARGS_STOP_COLOR + "=" + farbe + "\", ");
|
||||
} else {
|
||||
out.print("\"" + PApplet.ARGS_HIDE_STOP + "\", ");
|
||||
}
|
||||
} else {
|
||||
String farbe = Preferences.get("run.window.bgcolor");
|
||||
out.print("\"" + PApplet.ARGS_BGCOLOR + "=" + farbe + "\", ");
|
||||
}
|
||||
out.println("\"" + className + "\" });");
|
||||
out.println(indent + "}");
|
||||
}
|
||||
|
||||
// close off the class definition
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<String> getExtraImports() {
|
||||
return programImports;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the first CLASS_DEF node in the tree, and return the name of the
|
||||
* class in question.
|
||||
*
|
||||
* TODO [dmose] right now, we're using a little hack to the grammar to get
|
||||
* this info. In fact, we should be descending the AST passed in.
|
||||
*/
|
||||
String getFirstClassName(AST ast) {
|
||||
|
||||
String t = advClassName;
|
||||
advClassName = "";
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
11
app/src/processing/app/preproc/clean.sh
Executable file
11
app/src/processing/app/preproc/clean.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f *Lexer.java
|
||||
rm -f *Recognizer.java
|
||||
rm -f *TokenTypes.java
|
||||
rm -f *TokenTypes.txt
|
||||
rm -f *TreeParser.java
|
||||
rm -f *TreeParserTokenTypes.java
|
||||
rm -f *TreeParserTokenTypes.txt
|
||||
rm -f expanded*.g
|
||||
|
3
app/src/processing/app/preproc/make.sh
Executable file
3
app/src/processing/app/preproc/make.sh
Executable file
@ -0,0 +1,3 @@
|
||||
java -cp ../../build/macosx/work/lib/antlr.jar antlr.Tool java.g
|
||||
# now build the pde stuff that extends the java classes
|
||||
java -cp ../../build/macosx/work/lib/antlr.jar antlr.Tool -glib java.g pde.g
|
304
app/src/processing/app/preproc/pde.g
Normal file
304
app/src/processing/app/preproc/pde.g
Normal file
@ -0,0 +1,304 @@
|
||||
/* -*- mode: antlr; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
header {
|
||||
package processing.app.preproc;
|
||||
|
||||
import processing.app.*;
|
||||
}
|
||||
|
||||
class PdeRecognizer extends JavaRecognizer;
|
||||
|
||||
options {
|
||||
importVocab = Java;
|
||||
exportVocab = PdePartial;
|
||||
|
||||
codeGenMakeSwitchThreshold=10; // this is set high for debugging
|
||||
codeGenBitsetTestThreshold=10; // this is set high for debugging
|
||||
|
||||
// developers may to want to set this to true for better
|
||||
// debugging messages, however, doing so disables highlighting errors
|
||||
// in the editor.
|
||||
defaultErrorHandler = false; //true;
|
||||
}
|
||||
|
||||
tokens {
|
||||
CONSTRUCTOR_CAST; EMPTY_FIELD;
|
||||
}
|
||||
|
||||
pdeProgram
|
||||
// only java mode programs will have their own public classes or
|
||||
// imports (and they must have at least one)
|
||||
: ( "public" "class" | "import" ) => javaProgram
|
||||
{ PdePreprocessor.programType = PdePreprocessor.JAVA; }
|
||||
|
||||
// the syntactic predicate here looks for any minimal (thus
|
||||
// the non-greedy qualifier) number of fields, followed by
|
||||
// the tokens that represent the definition of loop() or
|
||||
// some other member function. java mode programs may have such
|
||||
// definitions, but they won't reach this point, having already been
|
||||
// selected in the previous alternative. static mode programs
|
||||
// don't have member functions.
|
||||
//
|
||||
| ( ( options {greedy=false;}: possiblyEmptyField)* "void" IDENT LPAREN )
|
||||
=> activeProgram
|
||||
{ PdePreprocessor.programType = PdePreprocessor.ACTIVE; }
|
||||
|
||||
| staticProgram
|
||||
{ PdePreprocessor.programType = PdePreprocessor.STATIC; }
|
||||
;
|
||||
|
||||
// advanced mode is really just a normal java file
|
||||
javaProgram
|
||||
: compilationUnit
|
||||
;
|
||||
|
||||
activeProgram
|
||||
: (possiblyEmptyField)+
|
||||
;
|
||||
|
||||
staticProgram
|
||||
: (statement)*
|
||||
;
|
||||
|
||||
// copy of the java.g rule with WEBCOLOR_LITERAL added
|
||||
constant
|
||||
: NUM_INT
|
||||
| CHAR_LITERAL
|
||||
| STRING_LITERAL
|
||||
| NUM_FLOAT
|
||||
| NUM_LONG
|
||||
| NUM_DOUBLE
|
||||
| webcolor_literal
|
||||
;
|
||||
|
||||
// of the form #cc008f in PDE
|
||||
webcolor_literal
|
||||
: w:WEBCOLOR_LITERAL
|
||||
{ Preferences.getBoolean("preproc.web_colors") &&
|
||||
w.getText().length() == 6 }? // must be exactly 6 hex digits
|
||||
;
|
||||
|
||||
// copy of the java.g builtInType rule
|
||||
builtInConsCastType
|
||||
: "void"
|
||||
| "boolean"
|
||||
| "byte"
|
||||
| "char"
|
||||
| "short"
|
||||
| "int"
|
||||
| "float"
|
||||
| "long"
|
||||
| "double"
|
||||
;
|
||||
|
||||
// our types include the java types and "color". this is separated into two
|
||||
// rules so that constructor casts can just use the original typelist, since
|
||||
// we don't want to support the color type as a constructor cast.
|
||||
//
|
||||
builtInType
|
||||
: builtInConsCastType
|
||||
| "color" // aliased to an int in PDE
|
||||
{ Preferences.getBoolean("preproc.color_datatype") }?
|
||||
;
|
||||
|
||||
// constructor style casts.
|
||||
constructorCast!
|
||||
: t:consCastTypeSpec[true]
|
||||
LPAREN!
|
||||
e:expression
|
||||
RPAREN!
|
||||
// if this is a string literal, make sure the type we're trying to cast
|
||||
// to is one of the supported ones
|
||||
//
|
||||
{ #e.getType() != STRING_LITERAL ||
|
||||
( #t.getType() == LITERAL_byte ||
|
||||
#t.getType() == LITERAL_double ||
|
||||
#t.getType() == LITERAL_float ||
|
||||
#t.getType() == LITERAL_int ||
|
||||
#t.getType() == LITERAL_long ||
|
||||
#t.getType() == LITERAL_short ) }?
|
||||
// create the node
|
||||
//
|
||||
{#constructorCast = #(#[CONSTRUCTOR_CAST,"CONSTRUCTOR_CAST"], t, e);}
|
||||
;
|
||||
|
||||
// A list of types that be used as the destination type in a constructor-style
|
||||
// cast. Ideally, this would include all class types, not just "String".
|
||||
// Unfortunately, it's not possible to tell whether Foo(5) is supposed to be
|
||||
// a method call or a constructor cast without have a table of all valid
|
||||
// types or methods, which requires semantic analysis (eg processing of import
|
||||
// statements). So we accept the set of built-in types plus "String".
|
||||
//
|
||||
consCastTypeSpec[boolean addImagNode]
|
||||
// : stringTypeSpec[addImagNode]
|
||||
// | builtInConsCastTypeSpec[addImagNode]
|
||||
: builtInConsCastTypeSpec[addImagNode]
|
||||
// trying to remove String() cast [fry]
|
||||
;
|
||||
|
||||
//stringTypeSpec[boolean addImagNode]
|
||||
// : id:IDENT { #id.getText().equals("String") }?
|
||||
// {
|
||||
// if ( addImagNode ) {
|
||||
// #stringTypeSpec = #(#[TYPE,"TYPE"],
|
||||
// #stringTypeSpec);
|
||||
// }
|
||||
// }
|
||||
// ;
|
||||
|
||||
builtInConsCastTypeSpec[boolean addImagNode]
|
||||
: builtInConsCastType
|
||||
{
|
||||
if ( addImagNode ) {
|
||||
#builtInConsCastTypeSpec = #(#[TYPE,"TYPE"],
|
||||
#builtInConsCastTypeSpec);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
// Since "color" tokens are lexed as LITERAL_color now, we need to have a rule
|
||||
// that can generate a method call from an expression that starts with this
|
||||
// token
|
||||
//
|
||||
colorMethodCall
|
||||
: c:"color" {#c.setType(IDENT);} // this would default to LITERAL_color
|
||||
lp:LPAREN^ {#lp.setType(METHOD_CALL);}
|
||||
argList
|
||||
RPAREN!
|
||||
;
|
||||
|
||||
// copy of the java.g rule with added constructorCast and colorMethodCall
|
||||
// alternatives
|
||||
primaryExpression
|
||||
: (consCastTypeSpec[false] LPAREN) => constructorCast
|
||||
{ Preferences.getBoolean("preproc.enhanced_casting") }?
|
||||
| identPrimary ( options {greedy=true;} : DOT^ "class" )?
|
||||
| constant
|
||||
| "true"
|
||||
| "false"
|
||||
| "null"
|
||||
| newExpression
|
||||
| "this"
|
||||
| "super"
|
||||
| LPAREN! assignmentExpression RPAREN!
|
||||
| colorMethodCall
|
||||
// look for int.class and int[].class
|
||||
| builtInType
|
||||
( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
|
||||
DOT^ "class"
|
||||
;
|
||||
|
||||
// the below variable rule hacks are needed so that it's possible for the
|
||||
// emitter to correctly output variable declarations of the form "float a, b"
|
||||
// from the AST. This means that our AST has a somewhat different form in
|
||||
// these rules than the java one does, and this new form may have its own
|
||||
// semantic issues. But it seems to fix the comma declaration issues.
|
||||
//
|
||||
variableDefinitions![AST mods, AST t]
|
||||
: vd:variableDeclarator[getASTFactory().dupTree(mods),
|
||||
getASTFactory().dupTree(t)]
|
||||
{#variableDefinitions = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods,
|
||||
t, vd);}
|
||||
;
|
||||
variableDeclarator[AST mods, AST t]
|
||||
: ( id:IDENT (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
|
||||
v:varInitializer (COMMA!)? )+
|
||||
;
|
||||
|
||||
// java.g builds syntax trees with an inconsistent structure. override one of
|
||||
// the rules there to fix this.
|
||||
//
|
||||
explicitConstructorInvocation!
|
||||
: t:"this" LPAREN a1:argList RPAREN SEMI
|
||||
{#explicitConstructorInvocation = #(#[CTOR_CALL, "CTOR_CALL"],
|
||||
#t, #a1);}
|
||||
| s:"super" LPAREN a2:argList RPAREN SEMI
|
||||
{#explicitConstructorInvocation = #(#[SUPER_CTOR_CALL,
|
||||
"SUPER_CTOR_CALL"],
|
||||
#s, #a2);}
|
||||
;
|
||||
|
||||
// quick-n-dirty hack to the get the advanced class name. we should
|
||||
// really be getting it from the AST and not forking this rule from
|
||||
// the java.g copy at all. Since this is a recursive descent parser, we get
|
||||
// the last class name in the file so that we don't end up with the classname
|
||||
// of an inner class. If there is more than one "outer" class in a file,
|
||||
// this heuristic will fail.
|
||||
//
|
||||
classDefinition![AST modifiers]
|
||||
: "class" i:IDENT
|
||||
// it _might_ have a superclass...
|
||||
sc:superClassClause
|
||||
// it might implement some interfaces...
|
||||
ic:implementsClause
|
||||
// now parse the body of the class
|
||||
cb:classBlock
|
||||
{#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
|
||||
modifiers,i,sc,ic,cb);
|
||||
PdePreprocessor.advClassName = i.getText();}
|
||||
;
|
||||
|
||||
possiblyEmptyField
|
||||
: field
|
||||
| s:SEMI {#s.setType(EMPTY_FIELD);}
|
||||
;
|
||||
|
||||
class PdeLexer extends JavaLexer;
|
||||
|
||||
options {
|
||||
importVocab=PdePartial;
|
||||
exportVocab=Pde;
|
||||
}
|
||||
|
||||
// We need to preserve whitespace and commentary instead of ignoring
|
||||
// like the supergrammar does. Otherwise Jikes won't be able to give
|
||||
// us error messages that point to the equivalent PDE code.
|
||||
|
||||
// WS, SL_COMMENT, ML_COMMENT are copies of the original productions,
|
||||
// but with the SKIP assigment removed.
|
||||
|
||||
WS : ( ' '
|
||||
| '\t'
|
||||
| '\f'
|
||||
// handle newlines
|
||||
| ( options {generateAmbigWarnings=false;}
|
||||
: "\r\n" // Evil DOS
|
||||
| '\r' // Macintosh
|
||||
| '\n' // Unix (the right way)
|
||||
)
|
||||
{ newline(); }
|
||||
)+
|
||||
;
|
||||
|
||||
// Single-line comments
|
||||
SL_COMMENT
|
||||
: "//"
|
||||
(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
|
||||
{newline();}
|
||||
;
|
||||
|
||||
// multiple-line comments
|
||||
ML_COMMENT
|
||||
: "/*"
|
||||
( /* '\r' '\n' can be matched in one alternative or by matching
|
||||
'\r' in one iteration and '\n' in another. I am trying to
|
||||
handle any flavor of newline that comes in, but the language
|
||||
that allows both "\r\n" and "\r" and "\n" to all be valid
|
||||
newline is ambiguous. Consequently, the resulting grammar
|
||||
must be ambiguous. I'm shutting this warning off.
|
||||
*/
|
||||
options {
|
||||
generateAmbigWarnings=false;
|
||||
}
|
||||
:
|
||||
{ LA(2)!='/' }? '*'
|
||||
| '\r' '\n' {newline();}
|
||||
| '\r' {newline();}
|
||||
| '\n' {newline();}
|
||||
| ~('*'|'\n'|'\r')
|
||||
)*
|
||||
"*/"
|
||||
;
|
||||
|
||||
WEBCOLOR_LITERAL
|
||||
: '#'! (HEX_DIGIT)+
|
||||
;
|
150
app/src/processing/app/preproc/whitespace_test.pde
Normal file
150
app/src/processing/app/preproc/whitespace_test.pde
Normal file
@ -0,0 +1,150 @@
|
||||
// this is a whitespace and other invisible token torture test for the ANTLR-based
|
||||
// preprocessor. edit pde.properties and set "editor.save_build_files" to true.
|
||||
// then, build this in processing. next, use
|
||||
//
|
||||
// diff -u --strip-trailing-cr \
|
||||
// work/sketchbook/default/whitespace_test/whitespace_test.pde \
|
||||
// work/lib/build/MyDemo.java
|
||||
//
|
||||
// to compare the files before and after preprocessing. There should not be
|
||||
// any differences.
|
||||
|
||||
import // comment test
|
||||
java.io.*;
|
||||
|
||||
// comment 1
|
||||
public class // post-class comment
|
||||
|
||||
// comment2
|
||||
|
||||
MyDemo extends BApplet implements // foo
|
||||
java.lang. // bar
|
||||
Cloneable {
|
||||
|
||||
//argh
|
||||
|
||||
public // foo
|
||||
String // bar
|
||||
fff = /*rheet */ "stuff";
|
||||
|
||||
static /*a*/ {
|
||||
/*foo*/
|
||||
/*bar*/
|
||||
six = 6;
|
||||
} /* b*/
|
||||
|
||||
static /*a*/ final /*b*/ int six;
|
||||
|
||||
void setup()
|
||||
{
|
||||
size(200, 200);
|
||||
background(255);
|
||||
|
||||
this . fff = /* ook */ (String)/*foo*/"yo";
|
||||
rectMode(CENTER_DIAMETER); // comment 1a
|
||||
noStroke();
|
||||
fill(255, 204, 0);
|
||||
|
||||
int q = /*a*/ - /*b*/ 1;
|
||||
|
||||
boolean c = /*a*/ ! /*b*/ true;
|
||||
}
|
||||
|
||||
int foo() /*a*/ throws /*b*/ java.lang.Exception /*c*/
|
||||
{
|
||||
int b = 7;
|
||||
switch /*a*/ ( /*b*/ b /*c*/ ) {
|
||||
case /*d*/ 1 /*e*/: /*f*/
|
||||
int c=9;
|
||||
/*g*/
|
||||
break; /*h*/
|
||||
default /*i*/ :
|
||||
int d=9;
|
||||
break;
|
||||
}
|
||||
|
||||
try { /* qq */
|
||||
loop(); /* rr */
|
||||
} catch /*ss*/ (java.lang.Exception ex) /*tt*/ {
|
||||
b = 8; /*tut*/
|
||||
throw /*utu*/ ex;
|
||||
} /*uu*/ finally /*vv*/ {
|
||||
b = 9;
|
||||
} /*ww*/
|
||||
|
||||
b /*aaa*/ = /*bbb*/ true /*ccc*/ ? /*ddd*/ 0 /*eee*/
|
||||
: /* fff*/ 1 /*ggg*/;
|
||||
return /*a*/ 5 /*b*/;
|
||||
}
|
||||
|
||||
// comment 2
|
||||
void loop()
|
||||
{
|
||||
|
||||
int arr1 /* VVV */ [ /* XXX */] /*YYY*/ ;
|
||||
int[] arr2 = { /*a*/ 2, 3 /*b*/ } /*c*/ ;
|
||||
|
||||
for /*a*/ (/*b*/ int j=0 /*c*/; /*d*/ j<2/*e*/ ; /*f*/ j++ /*g*/)
|
||||
/*h*/
|
||||
arr2[1] = 6;
|
||||
|
||||
/*foo*/
|
||||
;
|
||||
/*bar*/
|
||||
rect(width-mouseX, height-mouseY, 50, 50);
|
||||
rect(mouseX, mouseY, 50, 50);
|
||||
|
||||
if (/*a*/ arr2[1] == 6/*b*/) {
|
||||
/*c*/
|
||||
int d=7;
|
||||
} /*d*/else /*e*/{
|
||||
int e=8;
|
||||
/*f*/
|
||||
}
|
||||
|
||||
int f;
|
||||
if (/*aa*/ arr2[1] ==6 /*bb*/ )
|
||||
/*cc*/
|
||||
f=8; /*dd*/
|
||||
else /*ee*/
|
||||
f=10; /*ff*/
|
||||
|
||||
while ( /*aaa*/ f < 15) /*bbb*/ {
|
||||
f ++;
|
||||
} /*ggg*/
|
||||
|
||||
do /* aaaa */ {
|
||||
f++;
|
||||
} /*bbbb*/ while /*cccc*/ ( /*a*/ - /*b*/ 20 > f) /*dddd*/;
|
||||
|
||||
f = 2 * 3 + 4;
|
||||
|
||||
f = ( 2 * 3 ) + 4 + /*aa*/ -/*bb*/1;
|
||||
|
||||
f = 2 * ( 3 + 4 ) ;
|
||||
|
||||
fff = /*a*/ new /*b*/ String(/*c*/"foo"/*d*/) /*e*/;
|
||||
|
||||
int arr3[] = /*a*/ new /*b*/ int/*c*/[/*d*/] /*e*/ {1/*f*/,2};
|
||||
int arr4[][] = new /*a*/int/*b*/[1][2]/*c*/;
|
||||
|
||||
}
|
||||
|
||||
class Shoe
|
||||
{
|
||||
Shoe(String brand)
|
||||
{
|
||||
println(brand);
|
||||
}
|
||||
}
|
||||
|
||||
class NikeAir extends Shoe
|
||||
{
|
||||
NikeAir()
|
||||
{
|
||||
/*a*/ super /*b*/ ( /*c*/ "Nike" /*d*/ ) /*e*/ ;
|
||||
|
||||
/*aa*/ ( /*bb*/ new /*cc*/ MyDemo /*dd*/ (/*ee*/)/*ff*/)/*gg*/./*hh*/super/*ii*/(/*jj*/5/*kk*/);
|
||||
}
|
||||
}
|
||||
}
|
274
app/src/processing/app/syntax/CTokenMarker.java
Normal file
274
app/src/processing/app/syntax/CTokenMarker.java
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* CTokenMarker.java - C token marker
|
||||
* Copyright (C) 1998, 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.text.Segment;
|
||||
|
||||
/**
|
||||
* C token marker.
|
||||
*
|
||||
* @author Slava Pestov
|
||||
* @version $Id: CTokenMarker.java 1268 2005-04-09 02:30:37Z benfry $
|
||||
*/
|
||||
public class CTokenMarker extends TokenMarker
|
||||
{
|
||||
public CTokenMarker()
|
||||
{
|
||||
this(true,getKeywords());
|
||||
}
|
||||
|
||||
public CTokenMarker(boolean cpp, KeywordMap keywords)
|
||||
{
|
||||
this.cpp = cpp;
|
||||
this.keywords = keywords;
|
||||
}
|
||||
|
||||
public byte markTokensImpl(byte token, Segment line, int lineIndex)
|
||||
{
|
||||
char[] array = line.array;
|
||||
int offset = line.offset;
|
||||
lastOffset = offset;
|
||||
lastKeyword = offset;
|
||||
int mlength = line.count + offset;
|
||||
boolean backslash = false;
|
||||
|
||||
loop: for(int i = offset; i < mlength; i++)
|
||||
{
|
||||
int i1 = (i+1);
|
||||
|
||||
char c = array[i];
|
||||
if(c == '\\')
|
||||
{
|
||||
backslash = !backslash;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(token)
|
||||
{
|
||||
case Token.NULL:
|
||||
switch(c)
|
||||
{
|
||||
case '#':
|
||||
if(backslash)
|
||||
backslash = false;
|
||||
else if(cpp)
|
||||
{
|
||||
if(doKeyword(line,i,c))
|
||||
break;
|
||||
addToken(i - lastOffset,token);
|
||||
addToken(mlength - i,Token.KEYWORD2);
|
||||
lastOffset = lastKeyword = mlength;
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
doKeyword(line,i,c);
|
||||
if(backslash)
|
||||
backslash = false;
|
||||
else
|
||||
{
|
||||
addToken(i - lastOffset,token);
|
||||
token = Token.LITERAL1;
|
||||
lastOffset = lastKeyword = i;
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
doKeyword(line,i,c);
|
||||
if(backslash)
|
||||
backslash = false;
|
||||
else
|
||||
{
|
||||
addToken(i - lastOffset,token);
|
||||
token = Token.LITERAL2;
|
||||
lastOffset = lastKeyword = i;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
if(lastKeyword == offset)
|
||||
{
|
||||
if(doKeyword(line,i,c))
|
||||
break;
|
||||
backslash = false;
|
||||
addToken(i1 - lastOffset,Token.LABEL);
|
||||
lastOffset = lastKeyword = i1;
|
||||
}
|
||||
else if(doKeyword(line,i,c))
|
||||
break;
|
||||
break;
|
||||
case '/':
|
||||
backslash = false;
|
||||
doKeyword(line,i,c);
|
||||
if(mlength - i > 1)
|
||||
{
|
||||
switch(array[i1])
|
||||
{
|
||||
case '*':
|
||||
addToken(i - lastOffset,token);
|
||||
lastOffset = lastKeyword = i;
|
||||
if(mlength - i > 2 && array[i+2] == '*')
|
||||
token = Token.COMMENT2;
|
||||
else
|
||||
token = Token.COMMENT1;
|
||||
break;
|
||||
case '/':
|
||||
addToken(i - lastOffset,token);
|
||||
addToken(mlength - i,Token.COMMENT1);
|
||||
lastOffset = lastKeyword = mlength;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
backslash = false;
|
||||
if(!Character.isLetterOrDigit(c)
|
||||
&& c != '_')
|
||||
doKeyword(line,i,c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Token.COMMENT1:
|
||||
case Token.COMMENT2:
|
||||
backslash = false;
|
||||
if(c == '*' && mlength - i > 1)
|
||||
{
|
||||
if(array[i1] == '/')
|
||||
{
|
||||
i++;
|
||||
addToken((i+1) - lastOffset,token);
|
||||
token = Token.NULL;
|
||||
lastOffset = lastKeyword = i+1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Token.LITERAL1:
|
||||
if(backslash)
|
||||
backslash = false;
|
||||
else if(c == '"')
|
||||
{
|
||||
addToken(i1 - lastOffset,token);
|
||||
token = Token.NULL;
|
||||
lastOffset = lastKeyword = i1;
|
||||
}
|
||||
break;
|
||||
case Token.LITERAL2:
|
||||
if(backslash)
|
||||
backslash = false;
|
||||
else if(c == '\'')
|
||||
{
|
||||
addToken(i1 - lastOffset,Token.LITERAL1);
|
||||
token = Token.NULL;
|
||||
lastOffset = lastKeyword = i1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Invalid state: "
|
||||
+ token);
|
||||
}
|
||||
}
|
||||
|
||||
if(token == Token.NULL)
|
||||
doKeyword(line,mlength,'\0');
|
||||
|
||||
switch(token)
|
||||
{
|
||||
case Token.LITERAL1:
|
||||
case Token.LITERAL2:
|
||||
addToken(mlength - lastOffset,Token.INVALID);
|
||||
token = Token.NULL;
|
||||
break;
|
||||
case Token.KEYWORD2:
|
||||
addToken(mlength - lastOffset,token);
|
||||
if (!backslash) token = Token.NULL;
|
||||
addToken(mlength - lastOffset,token);
|
||||
break;
|
||||
default:
|
||||
addToken(mlength - lastOffset,token);
|
||||
break;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public static KeywordMap getKeywords()
|
||||
{
|
||||
if(cKeywords == null)
|
||||
{
|
||||
cKeywords = new KeywordMap(false);
|
||||
cKeywords.add("char",Token.KEYWORD3);
|
||||
cKeywords.add("double",Token.KEYWORD3);
|
||||
cKeywords.add("enum",Token.KEYWORD3);
|
||||
cKeywords.add("float",Token.KEYWORD3);
|
||||
cKeywords.add("int",Token.KEYWORD3);
|
||||
cKeywords.add("long",Token.KEYWORD3);
|
||||
cKeywords.add("short",Token.KEYWORD3);
|
||||
cKeywords.add("signed",Token.KEYWORD3);
|
||||
cKeywords.add("struct",Token.KEYWORD3);
|
||||
cKeywords.add("typedef",Token.KEYWORD3);
|
||||
cKeywords.add("union",Token.KEYWORD3);
|
||||
cKeywords.add("unsigned",Token.KEYWORD3);
|
||||
cKeywords.add("void",Token.KEYWORD3);
|
||||
cKeywords.add("auto",Token.KEYWORD1);
|
||||
cKeywords.add("const",Token.KEYWORD1);
|
||||
cKeywords.add("extern",Token.KEYWORD1);
|
||||
cKeywords.add("register",Token.KEYWORD1);
|
||||
cKeywords.add("static",Token.KEYWORD1);
|
||||
cKeywords.add("volatile",Token.KEYWORD1);
|
||||
cKeywords.add("break",Token.KEYWORD1);
|
||||
cKeywords.add("case",Token.KEYWORD1);
|
||||
cKeywords.add("continue",Token.KEYWORD1);
|
||||
cKeywords.add("default",Token.KEYWORD1);
|
||||
cKeywords.add("do",Token.KEYWORD1);
|
||||
cKeywords.add("else",Token.KEYWORD1);
|
||||
cKeywords.add("for",Token.KEYWORD1);
|
||||
cKeywords.add("goto",Token.KEYWORD1);
|
||||
cKeywords.add("if",Token.KEYWORD1);
|
||||
cKeywords.add("return",Token.KEYWORD1);
|
||||
cKeywords.add("sizeof",Token.KEYWORD1);
|
||||
cKeywords.add("switch",Token.KEYWORD1);
|
||||
cKeywords.add("while",Token.KEYWORD1);
|
||||
cKeywords.add("asm",Token.KEYWORD2);
|
||||
cKeywords.add("asmlinkage",Token.KEYWORD2);
|
||||
cKeywords.add("far",Token.KEYWORD2);
|
||||
cKeywords.add("huge",Token.KEYWORD2);
|
||||
cKeywords.add("inline",Token.KEYWORD2);
|
||||
cKeywords.add("near",Token.KEYWORD2);
|
||||
cKeywords.add("pascal",Token.KEYWORD2);
|
||||
cKeywords.add("true",Token.LITERAL2);
|
||||
cKeywords.add("false",Token.LITERAL2);
|
||||
cKeywords.add("NULL",Token.LITERAL2);
|
||||
}
|
||||
return cKeywords;
|
||||
}
|
||||
|
||||
// private members
|
||||
private static KeywordMap cKeywords;
|
||||
|
||||
private boolean cpp;
|
||||
private KeywordMap keywords;
|
||||
private int lastOffset;
|
||||
private int lastKeyword;
|
||||
|
||||
private boolean doKeyword(Segment line, int i, char c)
|
||||
{
|
||||
int i1 = i+1;
|
||||
|
||||
int len = i - lastKeyword;
|
||||
byte id = keywords.lookup(line,lastKeyword,len);
|
||||
if(id != Token.NULL)
|
||||
{
|
||||
if(lastKeyword != lastOffset)
|
||||
addToken(lastKeyword - lastOffset,Token.NULL);
|
||||
addToken(len,id);
|
||||
lastOffset = i;
|
||||
}
|
||||
lastKeyword = i1;
|
||||
return false;
|
||||
}
|
||||
}
|
374
app/src/processing/app/syntax/DefaultInputHandler.java
Normal file
374
app/src/processing/app/syntax/DefaultInputHandler.java
Normal file
@ -0,0 +1,374 @@
|
||||
/*
|
||||
* DefaultInputHandler.java - Default implementation of an input handler
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.KeyStroke;
|
||||
import java.awt.event.*;
|
||||
import java.awt.Toolkit;
|
||||
import java.util.Hashtable;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* The default input handler. It maps sequences of keystrokes into actions
|
||||
* and inserts key typed events into the text area.
|
||||
* @author Slava Pestov
|
||||
* @version $Id: DefaultInputHandler.java 1438 2005-05-11 08:34:16Z benfry $
|
||||
*/
|
||||
public class DefaultInputHandler extends InputHandler
|
||||
{
|
||||
/**
|
||||
* Creates a new input handler with no key bindings defined.
|
||||
*/
|
||||
public DefaultInputHandler()
|
||||
{
|
||||
bindings = currentBindings = new Hashtable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the default key bindings.
|
||||
*/
|
||||
public void addDefaultKeyBindings()
|
||||
{
|
||||
addKeyBinding("BACK_SPACE",BACKSPACE);
|
||||
addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD);
|
||||
addKeyBinding("DELETE",DELETE);
|
||||
addKeyBinding("C+DELETE",DELETE_WORD);
|
||||
|
||||
addKeyBinding("ENTER",INSERT_BREAK);
|
||||
addKeyBinding("TAB",INSERT_TAB);
|
||||
|
||||
addKeyBinding("INSERT",OVERWRITE);
|
||||
addKeyBinding("C+\\",TOGGLE_RECT);
|
||||
|
||||
addKeyBinding("HOME",HOME);
|
||||
addKeyBinding("END",END);
|
||||
addKeyBinding("S+HOME",SELECT_HOME);
|
||||
addKeyBinding("S+END",SELECT_END);
|
||||
addKeyBinding("C+HOME",DOCUMENT_HOME);
|
||||
addKeyBinding("C+END",DOCUMENT_END);
|
||||
addKeyBinding("CS+HOME",SELECT_DOC_HOME);
|
||||
addKeyBinding("CS+END",SELECT_DOC_END);
|
||||
|
||||
addKeyBinding("PAGE_UP",PREV_PAGE);
|
||||
addKeyBinding("PAGE_DOWN",NEXT_PAGE);
|
||||
addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE);
|
||||
addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE);
|
||||
|
||||
addKeyBinding("LEFT",PREV_CHAR);
|
||||
addKeyBinding("S+LEFT",SELECT_PREV_CHAR);
|
||||
addKeyBinding("C+LEFT",PREV_WORD);
|
||||
addKeyBinding("CS+LEFT",SELECT_PREV_WORD);
|
||||
addKeyBinding("RIGHT",NEXT_CHAR);
|
||||
addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR);
|
||||
addKeyBinding("C+RIGHT",NEXT_WORD);
|
||||
addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD);
|
||||
addKeyBinding("UP",PREV_LINE);
|
||||
addKeyBinding("S+UP",SELECT_PREV_LINE);
|
||||
addKeyBinding("DOWN",NEXT_LINE);
|
||||
addKeyBinding("S+DOWN",SELECT_NEXT_LINE);
|
||||
|
||||
addKeyBinding("C+ENTER",REPEAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key binding to this input handler. The key binding is
|
||||
* a list of white space separated key strokes of the form
|
||||
* <i>[modifiers+]key</i> where modifier is C for Control, A for Alt,
|
||||
* or S for Shift, and key is either a character (a-z) or a field
|
||||
* name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE)
|
||||
* @param keyBinding The key binding
|
||||
* @param action The action
|
||||
*/
|
||||
public void addKeyBinding(String keyBinding, ActionListener action)
|
||||
{
|
||||
Hashtable current = bindings;
|
||||
|
||||
StringTokenizer st = new StringTokenizer(keyBinding);
|
||||
while(st.hasMoreTokens())
|
||||
{
|
||||
KeyStroke keyStroke = parseKeyStroke(st.nextToken());
|
||||
if(keyStroke == null)
|
||||
return;
|
||||
|
||||
if(st.hasMoreTokens())
|
||||
{
|
||||
Object o = current.get(keyStroke);
|
||||
if(o instanceof Hashtable)
|
||||
current = (Hashtable)o;
|
||||
else
|
||||
{
|
||||
o = new Hashtable();
|
||||
current.put(keyStroke,o);
|
||||
current = (Hashtable)o;
|
||||
}
|
||||
}
|
||||
else
|
||||
current.put(keyStroke,action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a key binding from this input handler. This is not yet
|
||||
* implemented.
|
||||
* @param keyBinding The key binding
|
||||
*/
|
||||
public void removeKeyBinding(String keyBinding)
|
||||
{
|
||||
throw new InternalError("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all key bindings from this input handler.
|
||||
*/
|
||||
public void removeAllKeyBindings()
|
||||
{
|
||||
bindings.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this input handler that shares the same
|
||||
* key bindings. Setting key bindings in the copy will also
|
||||
* set them in the original.
|
||||
*/
|
||||
public InputHandler copy()
|
||||
{
|
||||
return new DefaultInputHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a key pressed event. This will look up the binding for
|
||||
* the key stroke and execute it.
|
||||
*/
|
||||
public void keyPressed(KeyEvent evt)
|
||||
{
|
||||
int keyCode = evt.getKeyCode();
|
||||
int modifiers = evt.getModifiers();
|
||||
|
||||
// moved this earlier so it doesn't get random meta clicks
|
||||
if (keyCode == KeyEvent.VK_CONTROL ||
|
||||
keyCode == KeyEvent.VK_SHIFT ||
|
||||
keyCode == KeyEvent.VK_ALT ||
|
||||
keyCode == KeyEvent.VK_META) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't get command-s or other menu key equivs on mac
|
||||
// unless it's something that's specifically bound (cmd-left or right)
|
||||
//if ((modifiers & KeyEvent.META_MASK) != 0) return;
|
||||
if ((modifiers & KeyEvent.META_MASK) != 0) {
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers);
|
||||
if (currentBindings.get(keyStroke) == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
char keyChar = evt.getKeyChar();
|
||||
System.out.println("code=" + keyCode + " char=" + keyChar +
|
||||
" charint=" + ((int)keyChar));
|
||||
System.out.println("other codes " + KeyEvent.VK_ALT + " " +
|
||||
KeyEvent.VK_META);
|
||||
*/
|
||||
|
||||
if((modifiers & ~KeyEvent.SHIFT_MASK) != 0
|
||||
|| evt.isActionKey()
|
||||
|| keyCode == KeyEvent.VK_BACK_SPACE
|
||||
|| keyCode == KeyEvent.VK_DELETE
|
||||
|| keyCode == KeyEvent.VK_ENTER
|
||||
|| keyCode == KeyEvent.VK_TAB
|
||||
|| keyCode == KeyEvent.VK_ESCAPE)
|
||||
{
|
||||
if(grabAction != null)
|
||||
{
|
||||
handleGrabAction(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode,
|
||||
modifiers);
|
||||
Object o = currentBindings.get(keyStroke);
|
||||
if(o == null)
|
||||
{
|
||||
// Don't beep if the user presses some
|
||||
// key we don't know about unless a
|
||||
// prefix is active. Otherwise it will
|
||||
// beep when caps lock is pressed, etc.
|
||||
if(currentBindings != bindings)
|
||||
{
|
||||
Toolkit.getDefaultToolkit().beep();
|
||||
// F10 should be passed on, but C+e F10
|
||||
// shouldn't
|
||||
repeatCount = 0;
|
||||
repeat = false;
|
||||
evt.consume();
|
||||
}
|
||||
currentBindings = bindings;
|
||||
return;
|
||||
}
|
||||
else if(o instanceof ActionListener)
|
||||
{
|
||||
currentBindings = bindings;
|
||||
|
||||
executeAction(((ActionListener)o),
|
||||
evt.getSource(),null);
|
||||
|
||||
evt.consume();
|
||||
return;
|
||||
}
|
||||
else if(o instanceof Hashtable)
|
||||
{
|
||||
currentBindings = (Hashtable)o;
|
||||
evt.consume();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a key typed event. This inserts the key into the text area.
|
||||
*/
|
||||
public void keyTyped(KeyEvent evt)
|
||||
{
|
||||
int modifiers = evt.getModifiers();
|
||||
char c = evt.getKeyChar();
|
||||
|
||||
// this is the apple/cmd key on macosx.. so menu commands
|
||||
// were being passed through as legit keys.. added this line
|
||||
// in an attempt to prevent.
|
||||
if ((modifiers & KeyEvent.META_MASK) != 0) return;
|
||||
|
||||
if (c != KeyEvent.CHAR_UNDEFINED) // &&
|
||||
// (modifiers & KeyEvent.ALT_MASK) == 0)
|
||||
{
|
||||
if(c >= 0x20 && c != 0x7f)
|
||||
{
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStroke(
|
||||
Character.toUpperCase(c));
|
||||
Object o = currentBindings.get(keyStroke);
|
||||
|
||||
if(o instanceof Hashtable)
|
||||
{
|
||||
currentBindings = (Hashtable)o;
|
||||
return;
|
||||
}
|
||||
else if(o instanceof ActionListener)
|
||||
{
|
||||
currentBindings = bindings;
|
||||
executeAction((ActionListener)o,
|
||||
evt.getSource(),
|
||||
String.valueOf(c));
|
||||
return;
|
||||
}
|
||||
|
||||
currentBindings = bindings;
|
||||
|
||||
if(grabAction != null)
|
||||
{
|
||||
handleGrabAction(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
// 0-9 adds another 'digit' to the repeat number
|
||||
if(repeat && Character.isDigit(c))
|
||||
{
|
||||
repeatCount *= 10;
|
||||
repeatCount += (c - '0');
|
||||
return;
|
||||
}
|
||||
|
||||
executeAction(INSERT_CHAR,evt.getSource(),
|
||||
String.valueOf(evt.getKeyChar()));
|
||||
|
||||
repeatCount = 0;
|
||||
repeat = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to a keystroke. The string should be of the
|
||||
* form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i>
|
||||
* is any combination of A for Alt, C for Control, S for Shift
|
||||
* or M for Meta, and <i>shortcut</i> is either a single character,
|
||||
* or a keycode name from the <code>KeyEvent</code> class, without
|
||||
* the <code>VK_</code> prefix.
|
||||
* @param keyStroke A string description of the key stroke
|
||||
*/
|
||||
public static KeyStroke parseKeyStroke(String keyStroke)
|
||||
{
|
||||
if(keyStroke == null)
|
||||
return null;
|
||||
int modifiers = 0;
|
||||
int index = keyStroke.indexOf('+');
|
||||
if(index != -1)
|
||||
{
|
||||
for(int i = 0; i < index; i++)
|
||||
{
|
||||
switch(Character.toUpperCase(keyStroke
|
||||
.charAt(i)))
|
||||
{
|
||||
case 'A':
|
||||
modifiers |= InputEvent.ALT_MASK;
|
||||
break;
|
||||
case 'C':
|
||||
modifiers |= InputEvent.CTRL_MASK;
|
||||
break;
|
||||
case 'M':
|
||||
modifiers |= InputEvent.META_MASK;
|
||||
break;
|
||||
case 'S':
|
||||
modifiers |= InputEvent.SHIFT_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
String key = keyStroke.substring(index + 1);
|
||||
if(key.length() == 1)
|
||||
{
|
||||
char ch = Character.toUpperCase(key.charAt(0));
|
||||
if(modifiers == 0)
|
||||
return KeyStroke.getKeyStroke(ch);
|
||||
else
|
||||
return KeyStroke.getKeyStroke(ch,modifiers);
|
||||
}
|
||||
else if(key.length() == 0)
|
||||
{
|
||||
System.err.println("Invalid key stroke: " + keyStroke);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ch;
|
||||
|
||||
try
|
||||
{
|
||||
ch = KeyEvent.class.getField("VK_".concat(key))
|
||||
.getInt(null);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.err.println("Invalid key stroke: "
|
||||
+ keyStroke);
|
||||
return null;
|
||||
}
|
||||
|
||||
return KeyStroke.getKeyStroke(ch,modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
// private members
|
||||
private Hashtable bindings;
|
||||
private Hashtable currentBindings;
|
||||
|
||||
private DefaultInputHandler(DefaultInputHandler copy)
|
||||
{
|
||||
bindings = currentBindings = copy.bindings;
|
||||
}
|
||||
}
|
1102
app/src/processing/app/syntax/InputHandler.java
Normal file
1102
app/src/processing/app/syntax/InputHandler.java
Normal file
File diff suppressed because it is too large
Load Diff
2259
app/src/processing/app/syntax/JEditTextArea.java
Normal file
2259
app/src/processing/app/syntax/JEditTextArea.java
Normal file
File diff suppressed because it is too large
Load Diff
140
app/src/processing/app/syntax/KeywordMap.java
Normal file
140
app/src/processing/app/syntax/KeywordMap.java
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* KeywordMap.java - Fast keyword->id map
|
||||
* Copyright (C) 1998, 1999 Slava Pestov
|
||||
* Copyright (C) 1999 Mike Dillon
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.text.Segment;
|
||||
|
||||
/**
|
||||
* A <code>KeywordMap</code> is similar to a hashtable in that it maps keys
|
||||
* to values. However, the `keys' are Swing segments. This allows lookups of
|
||||
* text substrings without the overhead of creating a new string object.
|
||||
* <p>
|
||||
* This class is used by <code>CTokenMarker</code> to map keywords to ids.
|
||||
*
|
||||
* @author Slava Pestov, Mike Dillon
|
||||
* @version $Id: KeywordMap.java 2050 2006-03-11 00:50:01Z fry $
|
||||
*/
|
||||
public class KeywordMap
|
||||
{
|
||||
/**
|
||||
* Creates a new <code>KeywordMap</code>.
|
||||
* @param ignoreCase True if keys are case insensitive
|
||||
*/
|
||||
public KeywordMap(boolean ignoreCase)
|
||||
{
|
||||
this(ignoreCase, 52);
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>KeywordMap</code>.
|
||||
* @param ignoreCase True if the keys are case insensitive
|
||||
* @param mapLength The number of `buckets' to create.
|
||||
* A value of 52 will give good performance for most maps.
|
||||
*/
|
||||
public KeywordMap(boolean ignoreCase, int mapLength)
|
||||
{
|
||||
this.mapLength = mapLength;
|
||||
this.ignoreCase = ignoreCase;
|
||||
map = new Keyword[mapLength];
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a key.
|
||||
* @param text The text segment
|
||||
* @param offset The offset of the substring within the text segment
|
||||
* @param length The length of the substring
|
||||
*/
|
||||
public byte lookup(Segment text, int offset, int length)
|
||||
{
|
||||
if(length == 0)
|
||||
return Token.NULL;
|
||||
Keyword k = map[getSegmentMapKey(text, offset, length)];
|
||||
while(k != null)
|
||||
{
|
||||
if(length != k.keyword.length)
|
||||
{
|
||||
k = k.next;
|
||||
continue;
|
||||
}
|
||||
if(SyntaxUtilities.regionMatches(ignoreCase,text,offset,
|
||||
k.keyword))
|
||||
return k.id;
|
||||
k = k.next;
|
||||
}
|
||||
return Token.NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key-value mapping.
|
||||
* @param keyword The key
|
||||
* @param id The value
|
||||
*/
|
||||
public void add(String keyword, byte id)
|
||||
{
|
||||
int key = getStringMapKey(keyword);
|
||||
map[key] = new Keyword(keyword.toCharArray(),id,map[key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the keyword map is set to be case insensitive,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean getIgnoreCase()
|
||||
{
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the keyword map should be case insensitive.
|
||||
* @param ignoreCase True if the keyword map should be case
|
||||
* insensitive, false otherwise
|
||||
*/
|
||||
public void setIgnoreCase(boolean ignoreCase)
|
||||
{
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
// protected members
|
||||
protected int mapLength;
|
||||
|
||||
protected int getStringMapKey(String s)
|
||||
{
|
||||
return (Character.toUpperCase(s.charAt(0)) +
|
||||
Character.toUpperCase(s.charAt(s.length()-1)))
|
||||
% mapLength;
|
||||
}
|
||||
|
||||
protected int getSegmentMapKey(Segment s, int off, int len)
|
||||
{
|
||||
return (Character.toUpperCase(s.array[off]) +
|
||||
Character.toUpperCase(s.array[off + len - 1]))
|
||||
% mapLength;
|
||||
}
|
||||
|
||||
// private members
|
||||
class Keyword
|
||||
{
|
||||
public Keyword(char[] keyword, byte id, Keyword next)
|
||||
{
|
||||
this.keyword = keyword;
|
||||
this.id = id;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public char[] keyword;
|
||||
public byte id;
|
||||
public Keyword next;
|
||||
}
|
||||
|
||||
private Keyword[] map;
|
||||
private boolean ignoreCase;
|
||||
}
|
122
app/src/processing/app/syntax/PdeKeywords.java
Normal file
122
app/src/processing/app/syntax/PdeKeywords.java
Normal file
@ -0,0 +1,122 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
PdeKeywords - handles text coloring and links to html reference
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class PdeKeywords extends CTokenMarker {
|
||||
|
||||
// lookup table for the TokenMarker subclass, handles coloring
|
||||
static KeywordMap keywordColoring;
|
||||
|
||||
// lookup table that maps keywords to their html reference pages
|
||||
static Hashtable keywordToReference;
|
||||
|
||||
|
||||
public PdeKeywords() {
|
||||
super(false, getKeywords());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles loading of keywords file.
|
||||
* <P>
|
||||
* Uses getKeywords() method because that's part of the
|
||||
* TokenMarker classes.
|
||||
* <P>
|
||||
* It is recommended that a # sign be used for comments
|
||||
* inside keywords.txt.
|
||||
*/
|
||||
static public KeywordMap getKeywords() {
|
||||
if (keywordColoring == null) {
|
||||
try {
|
||||
keywordColoring = new KeywordMap(false);
|
||||
keywordToReference = new Hashtable();
|
||||
|
||||
InputStream input = Base.getLibStream("keywords.txt");
|
||||
InputStreamReader isr = new InputStreamReader(input);
|
||||
BufferedReader reader = new BufferedReader(isr);
|
||||
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
//System.out.println("line is " + line);
|
||||
// in case there's any garbage on the line
|
||||
//if (line.trim().length() == 0) continue;
|
||||
|
||||
String pieces[] = processing.core.PApplet.split(line, '\t');
|
||||
if (pieces.length >= 2) {
|
||||
//int tab = line.indexOf('\t');
|
||||
// any line with no tab is ignored
|
||||
// meaning that a comment is any line without a tab
|
||||
//if (tab == -1) continue;
|
||||
|
||||
String keyword = pieces[0].trim();
|
||||
//String keyword = line.substring(0, tab).trim();
|
||||
//String second = line.substring(tab + 1);
|
||||
//tab = second.indexOf('\t');
|
||||
//String coloring = second.substring(0, tab).trim();
|
||||
//String htmlFilename = second.substring(tab + 1).trim();
|
||||
String coloring = pieces[1].trim();
|
||||
|
||||
if (coloring.length() > 0) {
|
||||
// text will be KEYWORD or LITERAL
|
||||
boolean isKey = (coloring.charAt(0) == 'K');
|
||||
// KEYWORD1 -> 0, KEYWORD2 -> 1, etc
|
||||
int num = coloring.charAt(coloring.length() - 1) - '1';
|
||||
byte id = (byte)
|
||||
((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num);
|
||||
//System.out.println("got " + (isKey ? "keyword" : "literal") +
|
||||
// (num+1) + " for " + keyword);
|
||||
keywordColoring.add(keyword, id);
|
||||
}
|
||||
if (pieces.length >= 3) {
|
||||
String htmlFilename = pieces[2].trim();
|
||||
if (htmlFilename.length() > 0) {
|
||||
keywordToReference.put(keyword, htmlFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
Base.showError("Problem loading keywords",
|
||||
"Could not load keywords.txt,\n" +
|
||||
"please re-install Processing.", e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
return keywordColoring;
|
||||
}
|
||||
|
||||
|
||||
static public String getReference(String keyword) {
|
||||
return (String) keywordToReference.get(keyword);
|
||||
}
|
||||
}
|
192
app/src/processing/app/syntax/PdeTextAreaDefaults.java
Normal file
192
app/src/processing/app/syntax/PdeTextAreaDefaults.java
Normal file
@ -0,0 +1,192 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
PdeTextAreaDefaults - grabs font/color settings for the editor
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-03 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
|
||||
public class PdeTextAreaDefaults extends TextAreaDefaults {
|
||||
|
||||
public PdeTextAreaDefaults() {
|
||||
|
||||
inputHandler = new DefaultInputHandler();
|
||||
//inputHandler.addDefaultKeyBindings(); // 0122
|
||||
|
||||
// use option on mac for things that are ctrl on windows/linux
|
||||
String mod = Base.isMacOS() ? "A" : "C";
|
||||
|
||||
// right now, ctrl-up/down is select up/down, but mod should be
|
||||
// used instead, because the mac expects it to be option(alt)
|
||||
|
||||
inputHandler.addKeyBinding("BACK_SPACE", InputHandler.BACKSPACE);
|
||||
inputHandler.addKeyBinding("DELETE", InputHandler.DELETE);
|
||||
|
||||
//inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
||||
// for 0122, shift-backspace is delete
|
||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.DELETE);
|
||||
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
|
||||
|
||||
// the following two were changing for 0122 for better mac/pc compatability
|
||||
inputHandler.addKeyBinding(mod+"+BACK_SPACE", InputHandler.BACKSPACE_WORD);
|
||||
inputHandler.addKeyBinding(mod+"+DELETE", InputHandler.DELETE_WORD);
|
||||
|
||||
// handled by listener, don't bother here
|
||||
//inputHandler.addKeyBinding("ENTER", InputHandler.INSERT_BREAK);
|
||||
//inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
|
||||
|
||||
inputHandler.addKeyBinding("INSERT", InputHandler.OVERWRITE);
|
||||
// disabling for 0122, not sure what this does
|
||||
//inputHandler.addKeyBinding("C+\\", InputHandler.TOGGLE_RECT);
|
||||
|
||||
// for 0122, these have been changed for better compatability
|
||||
// HOME and END now mean the beginning/end of the document
|
||||
if (Base.isMacOS()) {
|
||||
inputHandler.addKeyBinding("HOME", InputHandler.DOCUMENT_HOME);
|
||||
inputHandler.addKeyBinding("END", InputHandler.DOCUMENT_END);
|
||||
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_DOC_HOME);
|
||||
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_DOC_END);
|
||||
} else {
|
||||
// for 0123 added the proper windows defaults
|
||||
inputHandler.addKeyBinding("HOME", InputHandler.HOME);
|
||||
inputHandler.addKeyBinding("END", InputHandler.END);
|
||||
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_HOME);
|
||||
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_END);
|
||||
inputHandler.addKeyBinding("C+HOME", InputHandler.DOCUMENT_HOME);
|
||||
inputHandler.addKeyBinding("C+END", InputHandler.DOCUMENT_END);
|
||||
inputHandler.addKeyBinding("CS+HOME", InputHandler.SELECT_DOC_HOME);
|
||||
inputHandler.addKeyBinding("CS+END", InputHandler.SELECT_DOC_END);
|
||||
}
|
||||
|
||||
if (Base.isMacOS()) {
|
||||
inputHandler.addKeyBinding("M+LEFT", InputHandler.HOME);
|
||||
inputHandler.addKeyBinding("M+RIGHT", InputHandler.END);
|
||||
inputHandler.addKeyBinding("MS+LEFT", InputHandler.SELECT_HOME); // 0122
|
||||
inputHandler.addKeyBinding("MS+RIGHT", InputHandler.SELECT_END); // 0122
|
||||
} else {
|
||||
inputHandler.addKeyBinding("C+LEFT", InputHandler.HOME); // 0122
|
||||
inputHandler.addKeyBinding("C+RIGHT", InputHandler.END); // 0122
|
||||
inputHandler.addKeyBinding("CS+HOME", InputHandler.SELECT_HOME); // 0122
|
||||
inputHandler.addKeyBinding("CS+END", InputHandler.SELECT_END); // 0122
|
||||
}
|
||||
|
||||
inputHandler.addKeyBinding("PAGE_UP", InputHandler.PREV_PAGE);
|
||||
inputHandler.addKeyBinding("PAGE_DOWN", InputHandler.NEXT_PAGE);
|
||||
inputHandler.addKeyBinding("S+PAGE_UP", InputHandler.SELECT_PREV_PAGE);
|
||||
inputHandler.addKeyBinding("S+PAGE_DOWN", InputHandler.SELECT_NEXT_PAGE);
|
||||
|
||||
inputHandler.addKeyBinding("LEFT", InputHandler.PREV_CHAR);
|
||||
inputHandler.addKeyBinding("S+LEFT", InputHandler.SELECT_PREV_CHAR);
|
||||
inputHandler.addKeyBinding(mod + "+LEFT", InputHandler.PREV_WORD);
|
||||
inputHandler.addKeyBinding(mod + "S+LEFT", InputHandler.SELECT_PREV_WORD);
|
||||
inputHandler.addKeyBinding("RIGHT", InputHandler.NEXT_CHAR);
|
||||
inputHandler.addKeyBinding("S+RIGHT", InputHandler.SELECT_NEXT_CHAR);
|
||||
inputHandler.addKeyBinding(mod + "+RIGHT", InputHandler.NEXT_WORD);
|
||||
inputHandler.addKeyBinding(mod + "S+RIGHT", InputHandler.SELECT_NEXT_WORD);
|
||||
|
||||
inputHandler.addKeyBinding("UP", InputHandler.PREV_LINE);
|
||||
inputHandler.addKeyBinding(mod + "+UP", InputHandler.PREV_LINE); // p5
|
||||
inputHandler.addKeyBinding("S+UP", InputHandler.SELECT_PREV_LINE);
|
||||
inputHandler.addKeyBinding("DOWN", InputHandler.NEXT_LINE);
|
||||
inputHandler.addKeyBinding(mod + "+DOWN", InputHandler.NEXT_LINE); // p5
|
||||
inputHandler.addKeyBinding("S+DOWN", InputHandler.SELECT_NEXT_LINE);
|
||||
|
||||
inputHandler.addKeyBinding("MS+UP", InputHandler.SELECT_DOC_HOME);
|
||||
inputHandler.addKeyBinding("CS+UP", InputHandler.SELECT_DOC_HOME);
|
||||
inputHandler.addKeyBinding("MS+DOWN", InputHandler.SELECT_DOC_END);
|
||||
inputHandler.addKeyBinding("CS+DOWN", InputHandler.SELECT_DOC_END);
|
||||
|
||||
inputHandler.addKeyBinding(mod + "+ENTER", InputHandler.REPEAT);
|
||||
|
||||
document = new SyntaxDocument();
|
||||
editable = true;
|
||||
electricScroll = 3;
|
||||
|
||||
cols = 80;
|
||||
rows = 15;
|
||||
|
||||
|
||||
// moved from SyntaxUtilities
|
||||
//DEFAULTS.styles = SyntaxUtilities.getDefaultSyntaxStyles();
|
||||
|
||||
styles = new SyntaxStyle[Token.ID_COUNT];
|
||||
|
||||
// comments
|
||||
styles[Token.COMMENT1] = Theme.getStyle("comment1");
|
||||
styles[Token.COMMENT2] = Theme.getStyle("comment2");
|
||||
|
||||
// abstract, final, private
|
||||
styles[Token.KEYWORD1] = Theme.getStyle("keyword1");
|
||||
|
||||
// beginShape, point, line
|
||||
styles[Token.KEYWORD2] = Theme.getStyle("keyword2");
|
||||
|
||||
// byte, char, short, color
|
||||
styles[Token.KEYWORD3] = Theme.getStyle("keyword3");
|
||||
|
||||
// constants: null, true, this, RGB, TWO_PI
|
||||
styles[Token.LITERAL1] = Theme.getStyle("literal1");
|
||||
|
||||
// p5 built in variables: mouseX, width, pixels
|
||||
styles[Token.LITERAL2] = Theme.getStyle("literal2");
|
||||
|
||||
// ??
|
||||
styles[Token.LABEL] = Theme.getStyle("label");
|
||||
|
||||
// + - = /
|
||||
styles[Token.OPERATOR] = Theme.getStyle("operator");
|
||||
|
||||
// area that's not in use by the text (replaced with tildes)
|
||||
styles[Token.INVALID] = Theme.getStyle("invalid");
|
||||
|
||||
|
||||
// moved from TextAreaPainter
|
||||
|
||||
font = Preferences.getFont("editor.font");
|
||||
|
||||
fgcolor = Theme.getColor("editor.fgcolor");
|
||||
bgcolor = Theme.getColor("editor.bgcolor");
|
||||
|
||||
caretVisible = true;
|
||||
caretBlinks = Preferences.getBoolean("editor.caret.blink");
|
||||
caretColor = Theme.getColor("editor.caret.color");
|
||||
|
||||
selectionColor = Theme.getColor("editor.selection.color");
|
||||
|
||||
lineHighlight =
|
||||
Theme.getBoolean("editor.linehighlight");
|
||||
lineHighlightColor =
|
||||
Theme.getColor("editor.linehighlight.color");
|
||||
|
||||
bracketHighlight =
|
||||
Theme.getBoolean("editor.brackethighlight");
|
||||
bracketHighlightColor =
|
||||
Theme.getColor("editor.brackethighlight.color");
|
||||
|
||||
eolMarkers = Theme.getBoolean("editor.eolmarkers");
|
||||
eolMarkerColor = Theme.getColor("editor.eolmarkers.color");
|
||||
|
||||
paintInvalid = Theme.getBoolean("editor.invalid");
|
||||
}
|
||||
}
|
166
app/src/processing/app/syntax/SyntaxDocument.java
Normal file
166
app/src/processing/app/syntax/SyntaxDocument.java
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* SyntaxDocument.java - Document that can be tokenized
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.undo.UndoableEdit;
|
||||
|
||||
/**
|
||||
* A document implementation that can be tokenized by the syntax highlighting
|
||||
* system.
|
||||
*
|
||||
* @author Slava Pestov
|
||||
* @version $Id: SyntaxDocument.java 1268 2005-04-09 02:30:37Z benfry $
|
||||
*/
|
||||
public class SyntaxDocument extends PlainDocument
|
||||
{
|
||||
/**
|
||||
* Returns the token marker that is to be used to split lines
|
||||
* of this document up into tokens. May return null if this
|
||||
* document is not to be colorized.
|
||||
*/
|
||||
public TokenMarker getTokenMarker()
|
||||
{
|
||||
return tokenMarker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the token marker that is to be used to split lines of
|
||||
* this document up into tokens. May throw an exception if
|
||||
* this is not supported for this type of document.
|
||||
* @param tm The new token marker
|
||||
*/
|
||||
public void setTokenMarker(TokenMarker tm)
|
||||
{
|
||||
tokenMarker = tm;
|
||||
if(tm == null)
|
||||
return;
|
||||
tokenMarker.insertLines(0,getDefaultRootElement()
|
||||
.getElementCount());
|
||||
tokenizeLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reparses the document, by passing all lines to the token
|
||||
* marker. This should be called after the document is first
|
||||
* loaded.
|
||||
*/
|
||||
public void tokenizeLines()
|
||||
{
|
||||
tokenizeLines(0,getDefaultRootElement().getElementCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reparses the document, by passing the specified lines to the
|
||||
* token marker. This should be called after a large quantity of
|
||||
* text is first inserted.
|
||||
* @param start The first line to parse
|
||||
* @param len The number of lines, after the first one to parse
|
||||
*/
|
||||
public void tokenizeLines(int start, int len)
|
||||
{
|
||||
if(tokenMarker == null || !tokenMarker.supportsMultilineTokens())
|
||||
return;
|
||||
|
||||
Segment lineSegment = new Segment();
|
||||
Element map = getDefaultRootElement();
|
||||
|
||||
len += start;
|
||||
|
||||
try
|
||||
{
|
||||
for(int i = start; i < len; i++)
|
||||
{
|
||||
Element lineElement = map.getElement(i);
|
||||
int lineStart = lineElement.getStartOffset();
|
||||
getText(lineStart,lineElement.getEndOffset()
|
||||
- lineStart - 1,lineSegment);
|
||||
tokenMarker.markTokens(lineSegment,i);
|
||||
}
|
||||
}
|
||||
catch(BadLocationException bl)
|
||||
{
|
||||
bl.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a compound edit that can be undone in one operation.
|
||||
* Subclasses that implement undo should override this method;
|
||||
* this class has no undo functionality so this method is
|
||||
* empty.
|
||||
*/
|
||||
public void beginCompoundEdit() {}
|
||||
|
||||
/**
|
||||
* Ends a compound edit that can be undone in one operation.
|
||||
* Subclasses that implement undo should override this method;
|
||||
* this class has no undo functionality so this method is
|
||||
* empty.
|
||||
*/
|
||||
public void endCompoundEdit() {}
|
||||
|
||||
/**
|
||||
* Adds an undoable edit to this document's undo list. The edit
|
||||
* should be ignored if something is currently being undone.
|
||||
* @param edit The undoable edit
|
||||
*
|
||||
* @since jEdit 2.2pre1
|
||||
*/
|
||||
public void addUndoableEdit(UndoableEdit edit) {}
|
||||
|
||||
// protected members
|
||||
protected TokenMarker tokenMarker;
|
||||
|
||||
/**
|
||||
* We overwrite this method to update the token marker
|
||||
* state immediately so that any event listeners get a
|
||||
* consistent token marker.
|
||||
*/
|
||||
protected void fireInsertUpdate(DocumentEvent evt)
|
||||
{
|
||||
if(tokenMarker != null)
|
||||
{
|
||||
DocumentEvent.ElementChange ch = evt.getChange(
|
||||
getDefaultRootElement());
|
||||
if(ch != null)
|
||||
{
|
||||
tokenMarker.insertLines(ch.getIndex() + 1,
|
||||
ch.getChildrenAdded().length -
|
||||
ch.getChildrenRemoved().length);
|
||||
}
|
||||
}
|
||||
|
||||
super.fireInsertUpdate(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* We overwrite this method to update the token marker
|
||||
* state immediately so that any event listeners get a
|
||||
* consistent token marker.
|
||||
*/
|
||||
protected void fireRemoveUpdate(DocumentEvent evt)
|
||||
{
|
||||
if(tokenMarker != null)
|
||||
{
|
||||
DocumentEvent.ElementChange ch = evt.getChange(
|
||||
getDefaultRootElement());
|
||||
if(ch != null)
|
||||
{
|
||||
tokenMarker.deleteLines(ch.getIndex() + 1,
|
||||
ch.getChildrenRemoved().length -
|
||||
ch.getChildrenAdded().length);
|
||||
}
|
||||
}
|
||||
|
||||
super.fireRemoveUpdate(evt);
|
||||
}
|
||||
}
|
138
app/src/processing/app/syntax/SyntaxStyle.java
Normal file
138
app/src/processing/app/syntax/SyntaxStyle.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* SyntaxStyle.java - A simple text style class
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
|
||||
/**
|
||||
* A simple text style class. It can specify the color, italic flag,
|
||||
* and bold flag of a run of text.
|
||||
* @author Slava Pestov
|
||||
* @version $Id: SyntaxStyle.java 4824 2008-10-11 23:41:40Z fry $
|
||||
*/
|
||||
public class SyntaxStyle
|
||||
{
|
||||
/**
|
||||
* Creates a new SyntaxStyle.
|
||||
* @param color The text color
|
||||
* @param italic True if the text should be italics
|
||||
* @param bold True if the text should be bold
|
||||
*/
|
||||
public SyntaxStyle(Color color, boolean italic, boolean bold)
|
||||
{
|
||||
this.color = color;
|
||||
this.italic = italic;
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color specified in this style.
|
||||
*/
|
||||
public Color getColor()
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if no font styles are enabled.
|
||||
*/
|
||||
public boolean isPlain()
|
||||
{
|
||||
return !(bold || italic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if italics is enabled for this style.
|
||||
*/
|
||||
public boolean isItalic()
|
||||
{
|
||||
return italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if boldface is enabled for this style.
|
||||
*/
|
||||
public boolean isBold()
|
||||
{
|
||||
return bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specified font, but with the style's bold and
|
||||
* italic flags applied.
|
||||
*/
|
||||
public Font getStyledFont(Font font)
|
||||
{
|
||||
if(font == null)
|
||||
throw new NullPointerException("font param must not"
|
||||
+ " be null");
|
||||
if(font.equals(lastFont))
|
||||
return lastStyledFont;
|
||||
lastFont = font;
|
||||
lastStyledFont = new Font(font.getFamily(),
|
||||
(bold ? Font.BOLD : 0)
|
||||
| (italic ? Font.ITALIC : 0),
|
||||
font.getSize());
|
||||
return lastStyledFont;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font metrics for the styled font.
|
||||
*/
|
||||
public FontMetrics getFontMetrics(Font font, JComponent comp)
|
||||
{
|
||||
if(font == null)
|
||||
throw new NullPointerException("font param must not"
|
||||
+ " be null");
|
||||
if(font.equals(lastFont) && fontMetrics != null)
|
||||
return fontMetrics;
|
||||
lastFont = font;
|
||||
lastStyledFont = new Font(font.getFamily(),
|
||||
(bold ? Font.BOLD : 0)
|
||||
| (italic ? Font.ITALIC : 0),
|
||||
font.getSize());
|
||||
//fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(lastStyledFont);
|
||||
fontMetrics = comp.getFontMetrics(lastStyledFont);
|
||||
return fontMetrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the foreground color and font of the specified graphics
|
||||
* context to that specified in this style.
|
||||
* @param gfx The graphics context
|
||||
* @param font The font to add the styles to
|
||||
*/
|
||||
public void setGraphicsFlags(Graphics gfx, Font font)
|
||||
{
|
||||
Font _font = getStyledFont(font);
|
||||
gfx.setFont(_font);
|
||||
gfx.setColor(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getName() + "[color=" + color +
|
||||
(italic ? ",italic" : "") +
|
||||
(bold ? ",bold" : "") + "]";
|
||||
}
|
||||
|
||||
// private members
|
||||
private Color color;
|
||||
private boolean italic;
|
||||
private boolean bold;
|
||||
private Font lastFont;
|
||||
private Font lastStyledFont;
|
||||
private FontMetrics fontMetrics;
|
||||
}
|
163
app/src/processing/app/syntax/SyntaxUtilities.java
Normal file
163
app/src/processing/app/syntax/SyntaxUtilities.java
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* SyntaxUtilities.java - Utility functions used by syntax colorizing
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.text.*;
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
/**
|
||||
* Class with several utility functions used by jEdit's syntax colorizing
|
||||
* subsystem.
|
||||
*
|
||||
* @author Slava Pestov
|
||||
* @version $Id: SyntaxUtilities.java 1268 2005-04-09 02:30:37Z benfry $
|
||||
*/
|
||||
public class SyntaxUtilities
|
||||
{
|
||||
/**
|
||||
* Checks if a subregion of a <code>Segment</code> is equal to a
|
||||
* string.
|
||||
* @param ignoreCase True if case should be ignored, false otherwise
|
||||
* @param text The segment
|
||||
* @param offset The offset into the segment
|
||||
* @param match The string to match
|
||||
*/
|
||||
public static boolean regionMatches(boolean ignoreCase, Segment text,
|
||||
int offset, String match)
|
||||
{
|
||||
int length = offset + match.length();
|
||||
char[] textArray = text.array;
|
||||
if(length > text.offset + text.count)
|
||||
return false;
|
||||
for(int i = offset, j = 0; i < length; i++, j++)
|
||||
{
|
||||
char c1 = textArray[i];
|
||||
char c2 = match.charAt(j);
|
||||
if(ignoreCase)
|
||||
{
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
}
|
||||
if(c1 != c2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a subregion of a <code>Segment</code> is equal to a
|
||||
* character array.
|
||||
* @param ignoreCase True if case should be ignored, false otherwise
|
||||
* @param text The segment
|
||||
* @param offset The offset into the segment
|
||||
* @param match The character array to match
|
||||
*/
|
||||
public static boolean regionMatches(boolean ignoreCase, Segment text,
|
||||
int offset, char[] match)
|
||||
{
|
||||
int length = offset + match.length;
|
||||
char[] textArray = text.array;
|
||||
if(length > text.offset + text.count)
|
||||
return false;
|
||||
for(int i = offset, j = 0; i < length; i++, j++)
|
||||
{
|
||||
char c1 = textArray[i];
|
||||
char c2 = match[j];
|
||||
if(ignoreCase)
|
||||
{
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
}
|
||||
if(c1 != c2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the default style table. This can be passed to the
|
||||
* <code>setStyles()</code> method of <code>SyntaxDocument</code>
|
||||
* to use the default syntax styles.
|
||||
*/
|
||||
public static SyntaxStyle[] getDefaultSyntaxStyles()
|
||||
{
|
||||
SyntaxStyle[] styles = new SyntaxStyle[Token.ID_COUNT];
|
||||
|
||||
styles[Token.COMMENT1] = new SyntaxStyle(Color.black,true,false);
|
||||
styles[Token.COMMENT2] = new SyntaxStyle(new Color(0x990033),true,false);
|
||||
styles[Token.KEYWORD1] = new SyntaxStyle(Color.black,false,true);
|
||||
styles[Token.KEYWORD2] = new SyntaxStyle(Color.magenta,false,false);
|
||||
styles[Token.KEYWORD3] = new SyntaxStyle(new Color(0x009600),false,false);
|
||||
styles[Token.LITERAL1] = new SyntaxStyle(new Color(0x650099),false,false);
|
||||
styles[Token.LITERAL2] = new SyntaxStyle(new Color(0x650099),false,true);
|
||||
styles[Token.LABEL] = new SyntaxStyle(new Color(0x990033),false,true);
|
||||
styles[Token.OPERATOR] = new SyntaxStyle(Color.black,false,true);
|
||||
styles[Token.INVALID] = new SyntaxStyle(Color.red,false,true);
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Paints the specified line onto the graphics context. Note that this
|
||||
* method munges the offset and count values of the segment.
|
||||
* @param line The line segment
|
||||
* @param tokens The token list for the line
|
||||
* @param styles The syntax style list
|
||||
* @param expander The tab expander used to determine tab stops. May
|
||||
* be null
|
||||
* @param gfx The graphics context
|
||||
* @param x The x co-ordinate
|
||||
* @param y The y co-ordinate
|
||||
* @return The x co-ordinate, plus the width of the painted string
|
||||
*/
|
||||
public static int paintSyntaxLine(Segment line, Token tokens,
|
||||
SyntaxStyle[] styles,
|
||||
TabExpander expander, Graphics gfx,
|
||||
int x, int y)
|
||||
{
|
||||
Font defaultFont = gfx.getFont();
|
||||
Color defaultColor = gfx.getColor();
|
||||
|
||||
int offset = 0;
|
||||
for(;;)
|
||||
{
|
||||
byte id = tokens.id;
|
||||
if(id == Token.END)
|
||||
break;
|
||||
|
||||
int length = tokens.length;
|
||||
if(id == Token.NULL)
|
||||
{
|
||||
if(!defaultColor.equals(gfx.getColor()))
|
||||
gfx.setColor(defaultColor);
|
||||
if(!defaultFont.equals(gfx.getFont()))
|
||||
gfx.setFont(defaultFont);
|
||||
}
|
||||
else
|
||||
styles[id].setGraphicsFlags(gfx,defaultFont);
|
||||
|
||||
line.count = length;
|
||||
x = Utilities.drawTabbedText(line,x,y,gfx,expander,0);
|
||||
line.offset += length;
|
||||
offset += length;
|
||||
|
||||
tokens = tokens.next;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// private members
|
||||
private SyntaxUtilities() {}
|
||||
}
|
90
app/src/processing/app/syntax/TextAreaDefaults.java
Normal file
90
app/src/processing/app/syntax/TextAreaDefaults.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* TextAreaDefaults.java - Encapsulates default values for various settings
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import java.awt.*;
|
||||
//import javax.swing.JPopupMenu;
|
||||
|
||||
/**
|
||||
* Encapsulates default settings for a text area. This can be passed
|
||||
* to the constructor once the necessary fields have been filled out.
|
||||
* The advantage of doing this over calling lots of set() methods after
|
||||
* creating the text area is that this method is faster.
|
||||
*/
|
||||
public class TextAreaDefaults
|
||||
{
|
||||
private static TextAreaDefaults DEFAULTS;
|
||||
|
||||
public InputHandler inputHandler;
|
||||
public SyntaxDocument document;
|
||||
public boolean editable;
|
||||
|
||||
public boolean caretVisible;
|
||||
public boolean caretBlinks;
|
||||
public boolean blockCaret;
|
||||
public int electricScroll;
|
||||
|
||||
public int cols;
|
||||
public int rows;
|
||||
public SyntaxStyle[] styles;
|
||||
public Color caretColor;
|
||||
public Color selectionColor;
|
||||
public Color lineHighlightColor;
|
||||
public boolean lineHighlight;
|
||||
public Color bracketHighlightColor;
|
||||
public boolean bracketHighlight;
|
||||
public Color eolMarkerColor;
|
||||
public boolean eolMarkers;
|
||||
public boolean paintInvalid;
|
||||
|
||||
|
||||
// moved from TextAreaPainter [fry]
|
||||
public Font font;
|
||||
public Color fgcolor;
|
||||
public Color bgcolor;
|
||||
|
||||
//public JPopupMenu popup;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new TextAreaDefaults object with the default values filled
|
||||
* in.
|
||||
*/
|
||||
public static TextAreaDefaults getDefaults()
|
||||
{
|
||||
if (DEFAULTS == null) {
|
||||
DEFAULTS = new TextAreaDefaults();
|
||||
|
||||
DEFAULTS.inputHandler = new DefaultInputHandler();
|
||||
DEFAULTS.inputHandler.addDefaultKeyBindings();
|
||||
DEFAULTS.document = new SyntaxDocument();
|
||||
DEFAULTS.editable = true;
|
||||
|
||||
DEFAULTS.caretVisible = true;
|
||||
DEFAULTS.caretBlinks = true;
|
||||
DEFAULTS.electricScroll = 3;
|
||||
|
||||
DEFAULTS.cols = 80;
|
||||
DEFAULTS.rows = 25;
|
||||
DEFAULTS.styles = SyntaxUtilities.getDefaultSyntaxStyles();
|
||||
DEFAULTS.caretColor = Color.red;
|
||||
DEFAULTS.selectionColor = new Color(0xccccff);
|
||||
DEFAULTS.lineHighlightColor = new Color(0xe0e0e0);
|
||||
DEFAULTS.lineHighlight = true;
|
||||
DEFAULTS.bracketHighlightColor = Color.black;
|
||||
DEFAULTS.bracketHighlight = true;
|
||||
DEFAULTS.eolMarkerColor = new Color(0x009999);
|
||||
DEFAULTS.eolMarkers = true;
|
||||
DEFAULTS.paintInvalid = true;
|
||||
}
|
||||
|
||||
return DEFAULTS;
|
||||
}
|
||||
}
|
756
app/src/processing/app/syntax/TextAreaPainter.java
Normal file
756
app/src/processing/app/syntax/TextAreaPainter.java
Normal file
@ -0,0 +1,756 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
* TextAreaPainter.java - Paints the text area
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.JComponent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.print.*;
|
||||
|
||||
/**
|
||||
* The text area repaint manager. It performs double buffering and paints
|
||||
* lines of text.
|
||||
* @author Slava Pestov
|
||||
*/
|
||||
public class TextAreaPainter extends JComponent
|
||||
implements TabExpander, Printable
|
||||
{
|
||||
/** True if inside printing, will handle disabling the highlight */
|
||||
boolean printing;
|
||||
|
||||
/**
|
||||
* Creates a new repaint manager. This should be not be called
|
||||
* directly.
|
||||
*/
|
||||
public TextAreaPainter(JEditTextArea textArea, TextAreaDefaults defaults)
|
||||
{
|
||||
this.textArea = textArea;
|
||||
|
||||
setAutoscrolls(true);
|
||||
setDoubleBuffered(true);
|
||||
setOpaque(true);
|
||||
|
||||
ToolTipManager.sharedInstance().registerComponent(this);
|
||||
|
||||
currentLine = new Segment();
|
||||
currentLineIndex = -1;
|
||||
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
|
||||
|
||||
setFont(defaults.font);
|
||||
setForeground(defaults.fgcolor);
|
||||
setBackground(defaults.bgcolor);
|
||||
|
||||
blockCaret = defaults.blockCaret;
|
||||
styles = defaults.styles;
|
||||
cols = defaults.cols;
|
||||
rows = defaults.rows;
|
||||
caretColor = defaults.caretColor;
|
||||
selectionColor = defaults.selectionColor;
|
||||
lineHighlightColor = defaults.lineHighlightColor;
|
||||
lineHighlight = defaults.lineHighlight;
|
||||
bracketHighlightColor = defaults.bracketHighlightColor;
|
||||
bracketHighlight = defaults.bracketHighlight;
|
||||
paintInvalid = defaults.paintInvalid;
|
||||
eolMarkerColor = defaults.eolMarkerColor;
|
||||
eolMarkers = defaults.eolMarkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this component can be traversed by pressing the
|
||||
* Tab key. This returns false.
|
||||
*/
|
||||
public final boolean isManagingFocus()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the syntax styles used to paint colorized text. Entry <i>n</i>
|
||||
* will be used to paint tokens with id = <i>n</i>.
|
||||
* @see processing.app.syntax.Token
|
||||
*/
|
||||
public final SyntaxStyle[] getStyles()
|
||||
{
|
||||
return styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the syntax styles used to paint colorized text. Entry <i>n</i>
|
||||
* will be used to paint tokens with id = <i>n</i>.
|
||||
* @param styles The syntax styles
|
||||
* @see processing.app.syntax.Token
|
||||
*/
|
||||
public final void setStyles(SyntaxStyle[] styles)
|
||||
{
|
||||
this.styles = styles;
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the caret color.
|
||||
*/
|
||||
public final Color getCaretColor()
|
||||
{
|
||||
return caretColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the caret color.
|
||||
* @param caretColor The caret color
|
||||
*/
|
||||
public final void setCaretColor(Color caretColor)
|
||||
{
|
||||
this.caretColor = caretColor;
|
||||
invalidateSelectedLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selection color.
|
||||
*/
|
||||
public final Color getSelectionColor()
|
||||
{
|
||||
return selectionColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selection color.
|
||||
* @param selectionColor The selection color
|
||||
*/
|
||||
public final void setSelectionColor(Color selectionColor)
|
||||
{
|
||||
this.selectionColor = selectionColor;
|
||||
invalidateSelectedLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line highlight color.
|
||||
*/
|
||||
public final Color getLineHighlightColor()
|
||||
{
|
||||
return lineHighlightColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line highlight color.
|
||||
* @param lineHighlightColor The line highlight color
|
||||
*/
|
||||
public final void setLineHighlightColor(Color lineHighlightColor)
|
||||
{
|
||||
this.lineHighlightColor = lineHighlightColor;
|
||||
invalidateSelectedLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if line highlight is enabled, false otherwise.
|
||||
*/
|
||||
public final boolean isLineHighlightEnabled()
|
||||
{
|
||||
return lineHighlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables current line highlighting.
|
||||
* @param lineHighlight True if current line highlight
|
||||
* should be enabled, false otherwise
|
||||
*/
|
||||
public final void setLineHighlightEnabled(boolean lineHighlight)
|
||||
{
|
||||
this.lineHighlight = lineHighlight;
|
||||
invalidateSelectedLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bracket highlight color.
|
||||
*/
|
||||
public final Color getBracketHighlightColor()
|
||||
{
|
||||
return bracketHighlightColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bracket highlight color.
|
||||
* @param bracketHighlightColor The bracket highlight color
|
||||
*/
|
||||
public final void setBracketHighlightColor(Color bracketHighlightColor)
|
||||
{
|
||||
this.bracketHighlightColor = bracketHighlightColor;
|
||||
invalidateLine(textArea.getBracketLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if bracket highlighting is enabled, false otherwise.
|
||||
* When bracket highlighting is enabled, the bracket matching the
|
||||
* one before the caret (if any) is highlighted.
|
||||
*/
|
||||
public final boolean isBracketHighlightEnabled()
|
||||
{
|
||||
return bracketHighlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables bracket highlighting.
|
||||
* When bracket highlighting is enabled, the bracket matching the
|
||||
* one before the caret (if any) is highlighted.
|
||||
* @param bracketHighlight True if bracket highlighting should be
|
||||
* enabled, false otherwise
|
||||
*/
|
||||
public final void setBracketHighlightEnabled(boolean bracketHighlight)
|
||||
{
|
||||
this.bracketHighlight = bracketHighlight;
|
||||
invalidateLine(textArea.getBracketLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the caret should be drawn as a block, false otherwise.
|
||||
*/
|
||||
public final boolean isBlockCaretEnabled()
|
||||
{
|
||||
return blockCaret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the caret should be drawn as a block, false otherwise.
|
||||
* @param blockCaret True if the caret should be drawn as a block,
|
||||
* false otherwise.
|
||||
*/
|
||||
public final void setBlockCaretEnabled(boolean blockCaret)
|
||||
{
|
||||
this.blockCaret = blockCaret;
|
||||
invalidateSelectedLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the EOL marker color.
|
||||
*/
|
||||
public final Color getEOLMarkerColor()
|
||||
{
|
||||
return eolMarkerColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the EOL marker color.
|
||||
* @param eolMarkerColor The EOL marker color
|
||||
*/
|
||||
public final void setEOLMarkerColor(Color eolMarkerColor)
|
||||
{
|
||||
this.eolMarkerColor = eolMarkerColor;
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if EOL markers are drawn, false otherwise.
|
||||
*/
|
||||
public final boolean getEOLMarkersPainted()
|
||||
{
|
||||
return eolMarkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if EOL markers are to be drawn.
|
||||
* @param eolMarkers True if EOL markers should be drawn, false otherwise
|
||||
*/
|
||||
public final void setEOLMarkersPainted(boolean eolMarkers)
|
||||
{
|
||||
this.eolMarkers = eolMarkers;
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if invalid lines are painted as red tildes (~),
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean getInvalidLinesPainted()
|
||||
{
|
||||
return paintInvalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if invalid lines are to be painted as red tildes.
|
||||
* @param paintInvalid True if invalid lines should be drawn, false otherwise
|
||||
*/
|
||||
public void setInvalidLinesPainted(boolean paintInvalid)
|
||||
{
|
||||
this.paintInvalid = paintInvalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom highlight painter.
|
||||
* @param highlight The highlight
|
||||
*/
|
||||
public void addCustomHighlight(Highlight highlight)
|
||||
{
|
||||
highlight.init(textArea,highlights);
|
||||
highlights = highlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight interface.
|
||||
*/
|
||||
public interface Highlight
|
||||
{
|
||||
/**
|
||||
* Called after the highlight painter has been added.
|
||||
* @param textArea The text area
|
||||
* @param next The painter this one should delegate to
|
||||
*/
|
||||
void init(JEditTextArea textArea, Highlight next);
|
||||
|
||||
/**
|
||||
* This should paint the highlight and delgate to the
|
||||
* next highlight painter.
|
||||
* @param gfx The graphics context
|
||||
* @param line The line number
|
||||
* @param y The y co-ordinate of the line
|
||||
*/
|
||||
void paintHighlight(Graphics gfx, int line, int y);
|
||||
|
||||
/**
|
||||
* Returns the tool tip to display at the specified
|
||||
* location. If this highlighter doesn't know what to
|
||||
* display, it should delegate to the next highlight
|
||||
* painter.
|
||||
* @param evt The mouse event
|
||||
*/
|
||||
String getToolTipText(MouseEvent evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tool tip to display at the specified location.
|
||||
* @param evt The mouse event
|
||||
*/
|
||||
public String getToolTipText(MouseEvent evt)
|
||||
{
|
||||
if(highlights != null)
|
||||
return highlights.getToolTipText(evt);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font metrics used by this component.
|
||||
*/
|
||||
public FontMetrics getFontMetrics()
|
||||
{
|
||||
return fm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the font for this component. This is overridden to update the
|
||||
* cached font metrics and to recalculate which lines are visible.
|
||||
* @param font The font
|
||||
*/
|
||||
public void setFont(Font font)
|
||||
{
|
||||
super.setFont(font);
|
||||
fm = super.getFontMetrics(font);
|
||||
textArea.recalculateVisibleLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaints the text.
|
||||
* @param gfx The graphics context
|
||||
*/
|
||||
public void paint(Graphics gfx)
|
||||
{
|
||||
if (Base.isMacOS()) {
|
||||
Graphics2D g2 = (Graphics2D) gfx;
|
||||
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
||||
}
|
||||
|
||||
tabSize = fm.charWidth(' ') * ((Integer)textArea.getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue();
|
||||
|
||||
Rectangle clipRect = gfx.getClipBounds();
|
||||
|
||||
gfx.setColor(getBackground());
|
||||
gfx.fillRect(clipRect.x,clipRect.y,clipRect.width,clipRect.height);
|
||||
|
||||
// We don't use yToLine() here because that method doesn't
|
||||
// return lines past the end of the document
|
||||
int height = fm.getHeight();
|
||||
int firstLine = textArea.getFirstLine();
|
||||
int firstInvalid = firstLine + clipRect.y / height;
|
||||
// Because the clipRect's height is usually an even multiple
|
||||
// of the font height, we subtract 1 from it, otherwise one
|
||||
// too many lines will always be painted.
|
||||
int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height;
|
||||
|
||||
try {
|
||||
TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();
|
||||
int x = textArea.getHorizontalOffset();
|
||||
|
||||
for (int line = firstInvalid; line <= lastInvalid; line++) {
|
||||
paintLine(gfx,tokenMarker,line,x);
|
||||
}
|
||||
|
||||
if (tokenMarker != null && tokenMarker.isNextLineRequested()) {
|
||||
int h = clipRect.y + clipRect.height;
|
||||
repaint(0,h,getWidth(),getHeight() - h);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error repainting line"
|
||||
+ " range {" + firstInvalid + ","
|
||||
+ lastInvalid + "}:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
|
||||
int lineHeight = fm.getHeight();
|
||||
int linesPerPage = (int) (pageFormat.getImageableHeight() / lineHeight);
|
||||
int lineCount = textArea.getLineCount();
|
||||
int lastPage = lineCount / linesPerPage;
|
||||
|
||||
if (pageIndex > lastPage) {
|
||||
return NO_SUCH_PAGE;
|
||||
|
||||
} else {
|
||||
Graphics2D g2d = (Graphics2D)g;
|
||||
TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();
|
||||
int firstLine = pageIndex*linesPerPage;
|
||||
g2d.translate(Math.max(54, pageFormat.getImageableX()),
|
||||
pageFormat.getImageableY() - firstLine*lineHeight);
|
||||
printing = true;
|
||||
for (int line = firstLine; line < firstLine + linesPerPage; line++) {
|
||||
paintLine(g2d, tokenMarker, line, 0);
|
||||
}
|
||||
printing = false;
|
||||
return PAGE_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks a line as needing a repaint.
|
||||
* @param line The line to invalidate
|
||||
*/
|
||||
public final void invalidateLine(int line)
|
||||
{
|
||||
repaint(0,textArea.lineToY(line) + fm.getMaxDescent() + fm.getLeading(),
|
||||
getWidth(),fm.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a range of lines as needing a repaint.
|
||||
* @param firstLine The first line to invalidate
|
||||
* @param lastLine The last line to invalidate
|
||||
*/
|
||||
public final void invalidateLineRange(int firstLine, int lastLine)
|
||||
{
|
||||
repaint(0,textArea.lineToY(firstLine) +
|
||||
fm.getMaxDescent() + fm.getLeading(),
|
||||
getWidth(),(lastLine - firstLine + 1) * fm.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaints the lines containing the selection.
|
||||
*/
|
||||
public final void invalidateSelectedLines()
|
||||
{
|
||||
invalidateLineRange(textArea.getSelectionStartLine(),
|
||||
textArea.getSelectionStopLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of TabExpander interface. Returns next tab stop after
|
||||
* a specified point.
|
||||
* @param x The x co-ordinate
|
||||
* @param tabOffset Ignored
|
||||
* @return The next tab stop after <i>x</i>
|
||||
*/
|
||||
public float nextTabStop(float x, int tabOffset)
|
||||
{
|
||||
int offset = textArea.getHorizontalOffset();
|
||||
int ntabs = ((int)x - offset) / tabSize;
|
||||
return (ntabs + 1) * tabSize + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the painter's preferred size.
|
||||
*/
|
||||
public Dimension getPreferredSize()
|
||||
{
|
||||
Dimension dim = new Dimension();
|
||||
dim.width = fm.charWidth('w') * cols;
|
||||
dim.height = fm.getHeight() * rows;
|
||||
return dim;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the painter's minimum size.
|
||||
*/
|
||||
public Dimension getMinimumSize()
|
||||
{
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
// package-private members
|
||||
int currentLineIndex;
|
||||
Token currentLineTokens;
|
||||
Segment currentLine;
|
||||
|
||||
/**
|
||||
* Accessor used by tools that want to hook in and grab the formatting.
|
||||
*/
|
||||
public int getCurrentLineIndex() {
|
||||
return currentLineIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor used by tools that want to hook in and grab the formatting.
|
||||
*/
|
||||
public void setCurrentLineIndex(int what) {
|
||||
currentLineIndex = what;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor used by tools that want to hook in and grab the formatting.
|
||||
*/
|
||||
public Token getCurrentLineTokens() {
|
||||
return currentLineTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor used by tools that want to hook in and grab the formatting.
|
||||
*/
|
||||
public void setCurrentLineTokens(Token tokens) {
|
||||
currentLineTokens = tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor used by tools that want to hook in and grab the formatting.
|
||||
*/
|
||||
public Segment getCurrentLine() {
|
||||
return currentLine;
|
||||
}
|
||||
|
||||
|
||||
// protected members
|
||||
protected JEditTextArea textArea;
|
||||
|
||||
protected SyntaxStyle[] styles;
|
||||
protected Color caretColor;
|
||||
protected Color selectionColor;
|
||||
protected Color lineHighlightColor;
|
||||
protected Color bracketHighlightColor;
|
||||
protected Color eolMarkerColor;
|
||||
|
||||
protected boolean blockCaret;
|
||||
protected boolean lineHighlight;
|
||||
protected boolean bracketHighlight;
|
||||
protected boolean paintInvalid;
|
||||
protected boolean eolMarkers;
|
||||
protected int cols;
|
||||
protected int rows;
|
||||
|
||||
protected int tabSize;
|
||||
protected FontMetrics fm;
|
||||
|
||||
protected Highlight highlights;
|
||||
|
||||
protected void paintLine(Graphics gfx, TokenMarker tokenMarker,
|
||||
int line, int x)
|
||||
{
|
||||
Font defaultFont = getFont();
|
||||
Color defaultColor = getForeground();
|
||||
|
||||
currentLineIndex = line;
|
||||
int y = textArea.lineToY(line);
|
||||
|
||||
if (line < 0 || line >= textArea.getLineCount()) {
|
||||
if (paintInvalid) {
|
||||
paintHighlight(gfx,line,y);
|
||||
styles[Token.INVALID].setGraphicsFlags(gfx,defaultFont);
|
||||
gfx.drawString("~",0,y + fm.getHeight());
|
||||
}
|
||||
} else if(tokenMarker == null) {
|
||||
paintPlainLine(gfx,line,defaultFont,defaultColor,x,y);
|
||||
} else {
|
||||
paintSyntaxLine(gfx,tokenMarker,line,defaultFont,
|
||||
defaultColor,x,y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintPlainLine(Graphics gfx, int line, Font defaultFont,
|
||||
Color defaultColor, int x, int y)
|
||||
{
|
||||
paintHighlight(gfx,line,y);
|
||||
textArea.getLineText(line,currentLine);
|
||||
|
||||
gfx.setFont(defaultFont);
|
||||
gfx.setColor(defaultColor);
|
||||
|
||||
y += fm.getHeight();
|
||||
x = Utilities.drawTabbedText(currentLine,x,y,gfx,this,0);
|
||||
|
||||
if (eolMarkers) {
|
||||
gfx.setColor(eolMarkerColor);
|
||||
gfx.drawString(".",x,y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintSyntaxLine(Graphics gfx, TokenMarker tokenMarker,
|
||||
int line, Font defaultFont,
|
||||
Color defaultColor, int x, int y)
|
||||
{
|
||||
textArea.getLineText(currentLineIndex,currentLine);
|
||||
currentLineTokens = tokenMarker.markTokens(currentLine,
|
||||
currentLineIndex);
|
||||
|
||||
paintHighlight(gfx,line,y);
|
||||
|
||||
gfx.setFont(defaultFont);
|
||||
gfx.setColor(defaultColor);
|
||||
y += fm.getHeight();
|
||||
x = SyntaxUtilities.paintSyntaxLine(currentLine,
|
||||
currentLineTokens,
|
||||
styles, this, gfx, x, y);
|
||||
|
||||
if (eolMarkers) {
|
||||
gfx.setColor(eolMarkerColor);
|
||||
gfx.drawString(".",x,y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintHighlight(Graphics gfx, int line, int y)
|
||||
{
|
||||
if (!printing) {
|
||||
if (line >= textArea.getSelectionStartLine()
|
||||
&& line <= textArea.getSelectionStopLine())
|
||||
paintLineHighlight(gfx,line,y);
|
||||
|
||||
if (highlights != null)
|
||||
highlights.paintHighlight(gfx,line,y);
|
||||
|
||||
if (bracketHighlight && line == textArea.getBracketLine())
|
||||
paintBracketHighlight(gfx,line,y);
|
||||
|
||||
if (line == textArea.getCaretLine())
|
||||
paintCaret(gfx,line,y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintLineHighlight(Graphics gfx, int line, int y)
|
||||
{
|
||||
int height = fm.getHeight();
|
||||
y += fm.getLeading() + fm.getMaxDescent();
|
||||
|
||||
int selectionStart = textArea.getSelectionStart();
|
||||
int selectionEnd = textArea.getSelectionStop();
|
||||
|
||||
if (selectionStart == selectionEnd) {
|
||||
if (lineHighlight) {
|
||||
gfx.setColor(lineHighlightColor);
|
||||
gfx.fillRect(0,y,getWidth(),height);
|
||||
}
|
||||
} else {
|
||||
gfx.setColor(selectionColor);
|
||||
|
||||
int selectionStartLine = textArea.getSelectionStartLine();
|
||||
int selectionEndLine = textArea.getSelectionStopLine();
|
||||
int lineStart = textArea.getLineStartOffset(line);
|
||||
|
||||
int x1, x2;
|
||||
if (textArea.isSelectionRectangular()) {
|
||||
int lineLen = textArea.getLineLength(line);
|
||||
x1 = textArea._offsetToX(line,Math.min(lineLen, selectionStart - textArea.getLineStartOffset(selectionStartLine)));
|
||||
x2 = textArea._offsetToX(line,Math.min(lineLen, selectionEnd - textArea.getLineStartOffset(selectionEndLine)));
|
||||
if (x1 == x2)
|
||||
x2++;
|
||||
} else if(selectionStartLine == selectionEndLine) {
|
||||
x1 = textArea._offsetToX(line, selectionStart - lineStart);
|
||||
x2 = textArea._offsetToX(line, selectionEnd - lineStart);
|
||||
} else if(line == selectionStartLine) {
|
||||
x1 = textArea._offsetToX(line, selectionStart - lineStart);
|
||||
x2 = getWidth();
|
||||
} else if(line == selectionEndLine) {
|
||||
//x1 = 0;
|
||||
// hack from stendahl to avoid doing weird side selection thing
|
||||
x1 = textArea._offsetToX(line, 0);
|
||||
// attempt at getting the gutter too, but doesn't seem to work
|
||||
//x1 = textArea._offsetToX(line, -textArea.getHorizontalOffset());
|
||||
x2 = textArea._offsetToX(line, selectionEnd - lineStart);
|
||||
} else {
|
||||
//x1 = 0;
|
||||
// hack from stendahl to avoid doing weird side selection thing
|
||||
x1 = textArea._offsetToX(line, 0);
|
||||
// attempt at getting the gutter too, but doesn't seem to work
|
||||
//x1 = textArea._offsetToX(line, -textArea.getHorizontalOffset());
|
||||
x2 = getWidth();
|
||||
}
|
||||
|
||||
// "inlined" min/max()
|
||||
gfx.fillRect(x1 > x2 ? x2 : x1,y,x1 > x2 ?
|
||||
(x1 - x2) : (x2 - x1),height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void paintBracketHighlight(Graphics gfx, int line, int y)
|
||||
{
|
||||
int position = textArea.getBracketPosition();
|
||||
if(position == -1)
|
||||
return;
|
||||
y += fm.getLeading() + fm.getMaxDescent();
|
||||
int x = textArea._offsetToX(line,position);
|
||||
gfx.setColor(bracketHighlightColor);
|
||||
// Hack!!! Since there is no fast way to get the character
|
||||
// from the bracket matching routine, we use ( since all
|
||||
// brackets probably have the same width anyway
|
||||
gfx.drawRect(x,y,fm.charWidth('(') - 1,
|
||||
fm.getHeight() - 1);
|
||||
}
|
||||
|
||||
protected void paintCaret(Graphics gfx, int line, int y)
|
||||
{
|
||||
//System.out.println("painting caret " + line + " " + y);
|
||||
if (textArea.isCaretVisible()) {
|
||||
//System.out.println("caret is visible");
|
||||
int offset =
|
||||
textArea.getCaretPosition() - textArea.getLineStartOffset(line);
|
||||
int caretX = textArea._offsetToX(line, offset);
|
||||
int caretWidth = ((blockCaret ||
|
||||
textArea.isOverwriteEnabled()) ?
|
||||
fm.charWidth('w') : 1);
|
||||
y += fm.getLeading() + fm.getMaxDescent();
|
||||
int height = fm.getHeight();
|
||||
|
||||
//System.out.println("caretX, width = " + caretX + " " + caretWidth);
|
||||
|
||||
gfx.setColor(caretColor);
|
||||
|
||||
if (textArea.isOverwriteEnabled()) {
|
||||
gfx.fillRect(caretX,y + height - 1, caretWidth,1);
|
||||
|
||||
} else {
|
||||
// some machines don't like the drawRect for the single
|
||||
// pixel caret.. this caused a lot of hell because on that
|
||||
// minority of machines, the caret wouldn't show up past
|
||||
// the first column. the fix is to use drawLine() in
|
||||
// those cases, as a workaround.
|
||||
if (caretWidth == 1) {
|
||||
gfx.drawLine(caretX, y, caretX, y + height - 1);
|
||||
} else {
|
||||
gfx.drawRect(caretX, y, caretWidth - 1, height - 1);
|
||||
}
|
||||
//gfx.drawRect(caretX, y, caretWidth, height - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
184
app/src/processing/app/syntax/TextUtilities.java
Normal file
184
app/src/processing/app/syntax/TextUtilities.java
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* TextUtilities.java - Utility functions used by the text area classes
|
||||
* Copyright (C) 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.text.*;
|
||||
|
||||
/**
|
||||
* Class with several utility functions used by the text area component.
|
||||
* @author Slava Pestov
|
||||
* @version $Id: TextUtilities.java 1268 2005-04-09 02:30:37Z benfry $
|
||||
*/
|
||||
public class TextUtilities
|
||||
{
|
||||
/**
|
||||
* Returns the offset of the bracket matching the one at the
|
||||
* specified offset of the document, or -1 if the bracket is
|
||||
* unmatched (or if the character is not a bracket).
|
||||
* @param doc The document
|
||||
* @param offset The offset
|
||||
* @exception BadLocationException If an out-of-bounds access
|
||||
* was attempted on the document text
|
||||
*/
|
||||
public static int findMatchingBracket(Document doc, int offset)
|
||||
throws BadLocationException
|
||||
{
|
||||
if(doc.getLength() == 0)
|
||||
return -1;
|
||||
char c = doc.getText(offset,1).charAt(0);
|
||||
char cprime; // c` - corresponding character
|
||||
boolean direction; // true = back, false = forward
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '(': cprime = ')'; direction = false; break;
|
||||
case ')': cprime = '('; direction = true; break;
|
||||
case '[': cprime = ']'; direction = false; break;
|
||||
case ']': cprime = '['; direction = true; break;
|
||||
case '{': cprime = '}'; direction = false; break;
|
||||
case '}': cprime = '{'; direction = true; break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
int count;
|
||||
|
||||
// How to merge these two cases is left as an exercise
|
||||
// for the reader.
|
||||
|
||||
// Go back or forward
|
||||
if(direction)
|
||||
{
|
||||
// Count is 1 initially because we have already
|
||||
// `found' one closing bracket
|
||||
count = 1;
|
||||
|
||||
// Get text[0,offset-1];
|
||||
String text = doc.getText(0,offset);
|
||||
|
||||
// Scan backwards
|
||||
for(int i = offset - 1; i >= 0; i--)
|
||||
{
|
||||
// If text[i] == c, we have found another
|
||||
// closing bracket, therefore we will need
|
||||
// two opening brackets to complete the
|
||||
// match.
|
||||
char x = text.charAt(i);
|
||||
if(x == c)
|
||||
count++;
|
||||
|
||||
// If text[i] == cprime, we have found a
|
||||
// opening bracket, so we return i if
|
||||
// --count == 0
|
||||
else if(x == cprime)
|
||||
{
|
||||
if(--count == 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count is 1 initially because we have already
|
||||
// `found' one opening bracket
|
||||
count = 1;
|
||||
|
||||
// So we don't have to + 1 in every loop
|
||||
offset++;
|
||||
|
||||
// Number of characters to check
|
||||
int len = doc.getLength() - offset;
|
||||
|
||||
// Get text[offset+1,len];
|
||||
String text = doc.getText(offset,len);
|
||||
|
||||
// Scan forwards
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
// If text[i] == c, we have found another
|
||||
// opening bracket, therefore we will need
|
||||
// two closing brackets to complete the
|
||||
// match.
|
||||
char x = text.charAt(i);
|
||||
|
||||
if(x == c)
|
||||
count++;
|
||||
|
||||
// If text[i] == cprime, we have found an
|
||||
// closing bracket, so we return i if
|
||||
// --count == 0
|
||||
else if(x == cprime)
|
||||
{
|
||||
if(--count == 0)
|
||||
return i + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the start of the word at the specified position.
|
||||
* @param line The text
|
||||
* @param pos The position
|
||||
*/
|
||||
public static int findWordStart(String line, int pos, String noWordSep)
|
||||
{
|
||||
char ch = line.charAt(pos - 1);
|
||||
|
||||
if(noWordSep == null)
|
||||
noWordSep = "";
|
||||
boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
|
||||
&& noWordSep.indexOf(ch) == -1);
|
||||
|
||||
int wordStart = 0;
|
||||
for(int i = pos - 1; i >= 0; i--)
|
||||
{
|
||||
ch = line.charAt(i);
|
||||
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
|
||||
noWordSep.indexOf(ch) == -1))
|
||||
{
|
||||
wordStart = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return wordStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the end of the word at the specified position.
|
||||
* @param line The text
|
||||
* @param pos The position
|
||||
*/
|
||||
public static int findWordEnd(String line, int pos, String noWordSep)
|
||||
{
|
||||
char ch = line.charAt(pos);
|
||||
|
||||
if(noWordSep == null)
|
||||
noWordSep = "";
|
||||
boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
|
||||
&& noWordSep.indexOf(ch) == -1);
|
||||
|
||||
int wordEnd = line.length();
|
||||
for(int i = pos; i < line.length(); i++)
|
||||
{
|
||||
ch = line.charAt(i);
|
||||
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
|
||||
noWordSep.indexOf(ch) == -1))
|
||||
{
|
||||
wordEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return wordEnd;
|
||||
}
|
||||
}
|
149
app/src/processing/app/syntax/Token.java
Normal file
149
app/src/processing/app/syntax/Token.java
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Token.java - Generic token
|
||||
* Copyright (C) 1998, 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
/**
|
||||
* A linked list of tokens. Each token has three fields - a token
|
||||
* identifier, which is a byte value that can be looked up in the
|
||||
* array returned by <code>SyntaxDocument.getColors()</code>
|
||||
* to get a color value, a length value which is the length of the
|
||||
* token in the text, and a pointer to the next token in the list.
|
||||
*
|
||||
* @author Slava Pestov
|
||||
* @version $Id: Token.java 1268 2005-04-09 02:30:37Z benfry $
|
||||
*/
|
||||
public class Token
|
||||
{
|
||||
/**
|
||||
* Normal text token id. This should be used to mark
|
||||
* normal text.
|
||||
*/
|
||||
public static final byte NULL = 0;
|
||||
|
||||
/**
|
||||
* Comment 1 token id. This can be used to mark a comment.
|
||||
*/
|
||||
public static final byte COMMENT1 = 1;
|
||||
|
||||
/**
|
||||
* Comment 2 token id. This can be used to mark a comment.
|
||||
*/
|
||||
public static final byte COMMENT2 = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Literal 1 token id. This can be used to mark a string
|
||||
* literal (eg, C mode uses this to mark "..." literals)
|
||||
*/
|
||||
public static final byte LITERAL1 = 3;
|
||||
|
||||
/**
|
||||
* Literal 2 token id. This can be used to mark an object
|
||||
* literal (eg, Java mode uses this to mark true, false, etc)
|
||||
*/
|
||||
public static final byte LITERAL2 = 4;
|
||||
|
||||
/**
|
||||
* Label token id. This can be used to mark labels
|
||||
* (eg, C mode uses this to mark ...: sequences)
|
||||
*/
|
||||
public static final byte LABEL = 5;
|
||||
|
||||
/**
|
||||
* Keyword 1 token id. This can be used to mark a
|
||||
* keyword. This should be used for general language
|
||||
* constructs.
|
||||
*/
|
||||
public static final byte KEYWORD1 = 6;
|
||||
|
||||
/**
|
||||
* Keyword 2 token id. This can be used to mark a
|
||||
* keyword. This should be used for preprocessor
|
||||
* commands, or variables.
|
||||
*/
|
||||
public static final byte KEYWORD2 = 7;
|
||||
|
||||
/**
|
||||
* Keyword 3 token id. This can be used to mark a
|
||||
* keyword. This should be used for data types.
|
||||
*/
|
||||
public static final byte KEYWORD3 = 8;
|
||||
|
||||
/**
|
||||
* Operator token id. This can be used to mark an
|
||||
* operator. (eg, SQL mode marks +, -, etc with this
|
||||
* token type)
|
||||
*/
|
||||
public static final byte OPERATOR = 9;
|
||||
|
||||
/**
|
||||
* Invalid token id. This can be used to mark invalid
|
||||
* or incomplete tokens, so the user can easily spot
|
||||
* syntax errors.
|
||||
*/
|
||||
public static final byte INVALID = 10;
|
||||
|
||||
/**
|
||||
* The total number of defined token ids.
|
||||
*/
|
||||
public static final byte ID_COUNT = 11;
|
||||
|
||||
/**
|
||||
* The first id that can be used for internal state
|
||||
* in a token marker.
|
||||
*/
|
||||
public static final byte INTERNAL_FIRST = 100;
|
||||
|
||||
/**
|
||||
* The last id that can be used for internal state
|
||||
* in a token marker.
|
||||
*/
|
||||
public static final byte INTERNAL_LAST = 126;
|
||||
|
||||
/**
|
||||
* The token type, that along with a length of 0
|
||||
* marks the end of the token list.
|
||||
*/
|
||||
public static final byte END = 127;
|
||||
|
||||
/**
|
||||
* The length of this token.
|
||||
*/
|
||||
public int length;
|
||||
|
||||
/**
|
||||
* The id of this token.
|
||||
*/
|
||||
public byte id;
|
||||
|
||||
/**
|
||||
* The next token in the linked list.
|
||||
*/
|
||||
public Token next;
|
||||
|
||||
/**
|
||||
* Creates a new token.
|
||||
* @param length The length of the token
|
||||
* @param id The id of the token
|
||||
*/
|
||||
public Token(int length, byte id)
|
||||
{
|
||||
this.length = length;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this token.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return "[id=" + id + ",length=" + length + "]";
|
||||
}
|
||||
}
|
341
app/src/processing/app/syntax/TokenMarker.java
Normal file
341
app/src/processing/app/syntax/TokenMarker.java
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* TokenMarker.java - Generic token marker
|
||||
* Copyright (C) 1998, 1999 Slava Pestov
|
||||
*
|
||||
* You may use and modify this package for any purpose. Redistribution is
|
||||
* permitted, in both source and binary form, provided that this notice
|
||||
* remains intact in all source distributions of this package.
|
||||
*/
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.text.Segment;
|
||||
|
||||
/**
|
||||
* A token marker that splits lines of text into tokens. Each token carries
|
||||
* a length field and an indentification tag that can be mapped to a color
|
||||
* for painting that token.<p>
|
||||
*
|
||||
* For performance reasons, the linked list of tokens is reused after each
|
||||
* line is tokenized. Therefore, the return value of <code>markTokens</code>
|
||||
* should only be used for immediate painting. Notably, it cannot be
|
||||
* cached.
|
||||
*
|
||||
* @author Slava Pestov
|
||||
*/
|
||||
public abstract class TokenMarker
|
||||
{
|
||||
/**
|
||||
* A wrapper for the lower-level <code>markTokensImpl</code> method
|
||||
* that is called to split a line up into tokens.
|
||||
* @param line The line
|
||||
* @param lineIndex The line number
|
||||
*/
|
||||
public Token markTokens(Segment line, int lineIndex)
|
||||
{
|
||||
if(lineIndex >= length)
|
||||
{
|
||||
throw new IllegalArgumentException("Tokenizing invalid line: "
|
||||
+ lineIndex);
|
||||
}
|
||||
|
||||
lastToken = null;
|
||||
|
||||
LineInfo info = lineInfo[lineIndex];
|
||||
LineInfo prev;
|
||||
if(lineIndex == 0)
|
||||
prev = null;
|
||||
else
|
||||
prev = lineInfo[lineIndex - 1];
|
||||
|
||||
byte oldToken = info.token;
|
||||
byte token = markTokensImpl(prev == null ?
|
||||
Token.NULL : prev.token,line,lineIndex);
|
||||
|
||||
info.token = token;
|
||||
|
||||
/*
|
||||
* This is a foul hack. It stops nextLineRequested
|
||||
* from being cleared if the same line is marked twice.
|
||||
*
|
||||
* Why is this necessary? It's all JEditTextArea's fault.
|
||||
* When something is inserted into the text, firing a
|
||||
* document event, the insertUpdate() method shifts the
|
||||
* caret (if necessary) by the amount inserted.
|
||||
*
|
||||
* All caret movement is handled by the select() method,
|
||||
* which eventually pipes the new position to scrollTo()
|
||||
* and calls repaint().
|
||||
*
|
||||
* Note that at this point in time, the new line hasn't
|
||||
* yet been painted; the caret is moved first.
|
||||
*
|
||||
* scrollTo() calls offsetToX(), which tokenizes the line
|
||||
* unless it is being called on the last line painted
|
||||
* (in which case it uses the text area's painter cached
|
||||
* token list). What scrollTo() does next is irrelevant.
|
||||
*
|
||||
* After scrollTo() has done it's job, repaint() is
|
||||
* called, and eventually we end up in paintLine(), whose
|
||||
* job is to paint the changed line. It, too, calls
|
||||
* markTokens().
|
||||
*
|
||||
* The problem was that if the line started a multiline
|
||||
* token, the first markTokens() (done in offsetToX())
|
||||
* would set nextLineRequested (because the line end
|
||||
* token had changed) but the second would clear it
|
||||
* (because the line was the same that time) and therefore
|
||||
* paintLine() would never know that it needed to repaint
|
||||
* subsequent lines.
|
||||
*
|
||||
* This bug took me ages to track down, that's why I wrote
|
||||
* all the relevant info down so that others wouldn't
|
||||
* duplicate it.
|
||||
*/
|
||||
if(!(lastLine == lineIndex && nextLineRequested))
|
||||
nextLineRequested = (oldToken != token);
|
||||
|
||||
lastLine = lineIndex;
|
||||
|
||||
addToken(0,Token.END);
|
||||
|
||||
return firstToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract method that splits a line up into tokens. It
|
||||
* should parse the line, and call <code>addToken()</code> to
|
||||
* add syntax tokens to the token list. Then, it should return
|
||||
* the initial token type for the next line.<p>
|
||||
*
|
||||
* For example if the current line contains the start of a
|
||||
* multiline comment that doesn't end on that line, this method
|
||||
* should return the comment token type so that it continues on
|
||||
* the next line.
|
||||
*
|
||||
* @param token The initial token type for this line
|
||||
* @param line The line to be tokenized
|
||||
* @param lineIndex The index of the line in the document,
|
||||
* starting at 0
|
||||
* @return The initial token type for the next line
|
||||
*/
|
||||
protected abstract byte markTokensImpl(byte token, Segment line,
|
||||
int lineIndex);
|
||||
|
||||
/**
|
||||
* Returns if the token marker supports tokens that span multiple
|
||||
* lines. If this is true, the object using this token marker is
|
||||
* required to pass all lines in the document to the
|
||||
* <code>markTokens()</code> method (in turn).<p>
|
||||
*
|
||||
* The default implementation returns true; it should be overridden
|
||||
* to return false on simpler token markers for increased speed.
|
||||
*/
|
||||
public boolean supportsMultilineTokens()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the token marker that lines have been inserted into
|
||||
* the document. This inserts a gap in the <code>lineInfo</code>
|
||||
* array.
|
||||
* @param index The first line number
|
||||
* @param lines The number of lines
|
||||
*/
|
||||
public void insertLines(int index, int lines)
|
||||
{
|
||||
if(lines <= 0)
|
||||
return;
|
||||
length += lines;
|
||||
ensureCapacity(length);
|
||||
int len = index + lines;
|
||||
System.arraycopy(lineInfo,index,lineInfo,len,
|
||||
lineInfo.length - len);
|
||||
|
||||
for(int i = index + lines - 1; i >= index; i--)
|
||||
{
|
||||
lineInfo[i] = new LineInfo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the token marker that line have been deleted from
|
||||
* the document. This removes the lines in question from the
|
||||
* <code>lineInfo</code> array.
|
||||
* @param index The first line number
|
||||
* @param lines The number of lines
|
||||
*/
|
||||
public void deleteLines(int index, int lines)
|
||||
{
|
||||
if (lines <= 0)
|
||||
return;
|
||||
int len = index + lines;
|
||||
length -= lines;
|
||||
System.arraycopy(lineInfo,len,lineInfo,
|
||||
index,lineInfo.length - len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of lines in this token marker.
|
||||
*/
|
||||
public int getLineCount()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the next line should be repainted. This
|
||||
* will return true after a line has been tokenized that starts
|
||||
* a multiline token that continues onto the next line.
|
||||
*/
|
||||
public boolean isNextLineRequested()
|
||||
{
|
||||
return nextLineRequested;
|
||||
}
|
||||
|
||||
// protected members
|
||||
|
||||
/**
|
||||
* The first token in the list. This should be used as the return
|
||||
* value from <code>markTokens()</code>.
|
||||
*/
|
||||
protected Token firstToken;
|
||||
|
||||
/**
|
||||
* The last token in the list. New tokens are added here.
|
||||
* This should be set to null before a new line is to be tokenized.
|
||||
*/
|
||||
protected Token lastToken;
|
||||
|
||||
/**
|
||||
* An array for storing information about lines. It is enlarged and
|
||||
* shrunk automatically by the <code>insertLines()</code> and
|
||||
* <code>deleteLines()</code> methods.
|
||||
*/
|
||||
protected LineInfo[] lineInfo;
|
||||
|
||||
/**
|
||||
* The number of lines in the model being tokenized. This can be
|
||||
* less than the length of the <code>lineInfo</code> array.
|
||||
*/
|
||||
protected int length;
|
||||
|
||||
/**
|
||||
* The last tokenized line.
|
||||
*/
|
||||
protected int lastLine;
|
||||
|
||||
/**
|
||||
* True if the next line should be painted.
|
||||
*/
|
||||
protected boolean nextLineRequested;
|
||||
|
||||
/**
|
||||
* Creates a new <code>TokenMarker</code>. This DOES NOT create
|
||||
* a lineInfo array; an initial call to <code>insertLines()</code>
|
||||
* does that.
|
||||
*/
|
||||
protected TokenMarker()
|
||||
{
|
||||
lastLine = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the <code>lineInfo</code> array can contain the
|
||||
* specified index. This enlarges it if necessary. No action is
|
||||
* taken if the array is large enough already.<p>
|
||||
*
|
||||
* It should be unnecessary to call this under normal
|
||||
* circumstances; <code>insertLine()</code> should take care of
|
||||
* enlarging the line info array automatically.
|
||||
*
|
||||
* @param index The array index
|
||||
*/
|
||||
protected void ensureCapacity(int index)
|
||||
{
|
||||
if(lineInfo == null)
|
||||
lineInfo = new LineInfo[index + 1];
|
||||
else if(lineInfo.length <= index)
|
||||
{
|
||||
LineInfo[] lineInfoN = new LineInfo[(index + 1) * 2];
|
||||
System.arraycopy(lineInfo,0,lineInfoN,0,
|
||||
lineInfo.length);
|
||||
lineInfo = lineInfoN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a token to the token list.
|
||||
* @param length The length of the token
|
||||
* @param id The id of the token
|
||||
*/
|
||||
protected void addToken(int length, byte id)
|
||||
{
|
||||
if(id >= Token.INTERNAL_FIRST && id <= Token.INTERNAL_LAST)
|
||||
throw new InternalError("Invalid id: " + id);
|
||||
|
||||
if(length == 0 && id != Token.END)
|
||||
return;
|
||||
|
||||
if(firstToken == null)
|
||||
{
|
||||
firstToken = new Token(length,id);
|
||||
lastToken = firstToken;
|
||||
}
|
||||
else if(lastToken == null)
|
||||
{
|
||||
lastToken = firstToken;
|
||||
firstToken.length = length;
|
||||
firstToken.id = id;
|
||||
}
|
||||
else if(lastToken.next == null)
|
||||
{
|
||||
lastToken.next = new Token(length,id);
|
||||
lastToken = lastToken.next;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastToken = lastToken.next;
|
||||
lastToken.length = length;
|
||||
lastToken.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for storing information about tokenized lines.
|
||||
*/
|
||||
public class LineInfo
|
||||
{
|
||||
/**
|
||||
* Creates a new LineInfo object with token = Token.NULL
|
||||
* and obj = null.
|
||||
*/
|
||||
public LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new LineInfo object with the specified
|
||||
* parameters.
|
||||
*/
|
||||
public LineInfo(byte token, Object obj)
|
||||
{
|
||||
this.token = token;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* The id of the last token of the line.
|
||||
*/
|
||||
public byte token;
|
||||
|
||||
/**
|
||||
* This is for use by the token marker implementations
|
||||
* themselves. It can be used to store anything that
|
||||
* is an object and that needs to exist on a per-line
|
||||
* basis.
|
||||
*/
|
||||
public Object obj;
|
||||
}
|
||||
}
|
46
app/src/processing/app/syntax/readme.txt
Normal file
46
app/src/processing/app/syntax/readme.txt
Normal file
@ -0,0 +1,46 @@
|
||||
OLDSYNTAX PACKAGE README
|
||||
|
||||
I am placing the jEdit 2.2.1 syntax highlighting package in the public
|
||||
domain. This means it can be integrated into commercial programs, etc.
|
||||
|
||||
This package requires at least Java 1.1 and Swing 1.1. Syntax
|
||||
highlighting for the following file types is supported:
|
||||
|
||||
- C++, C
|
||||
- CORBA IDL
|
||||
- Eiffel
|
||||
- HTML
|
||||
- Java
|
||||
- Java properties
|
||||
- JavaScript
|
||||
- MS-DOS INI
|
||||
- MS-DOS batch files
|
||||
- Makefile
|
||||
- PHP
|
||||
- Perl
|
||||
- Python
|
||||
- TeX
|
||||
- Transact-SQL
|
||||
- Unix patch/diff
|
||||
- Unix shell script
|
||||
- XML
|
||||
|
||||
This package is undocumented; read the source (start by taking a look at
|
||||
JEditTextArea.java) to find out how to use it; it's really simple. Feel
|
||||
free to e-mail questions, queries, etc. to me, but keep in mind that
|
||||
this code is very old and I no longer maintain it. So if you find a bug,
|
||||
don't bother me about it; fix it yourself.
|
||||
|
||||
* Copyright
|
||||
|
||||
The jEdit 2.2.1 syntax highlighting package contains code that is
|
||||
Copyright 1998-1999 Slava Pestov, Artur Biesiadowski, Clancy Malcolm,
|
||||
Jonathan Revusky, Juha Lindfors and Mike Dillon.
|
||||
|
||||
You may use and modify this package for any purpose. Redistribution is
|
||||
permitted, in both source and binary form, provided that this notice
|
||||
remains intact in all source distributions of this package.
|
||||
|
||||
-- Slava Pestov
|
||||
25 September 2000
|
||||
<sp@gjt.org>
|
184
app/src/processing/app/tools/Archiver.java
Executable file
184
app/src/processing/app/tools/Archiver.java
Executable file
@ -0,0 +1,184 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Archiver - plugin tool for archiving sketches
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
import java.awt.FileDialog;
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
|
||||
public class Archiver implements Tool {
|
||||
Editor editor;
|
||||
|
||||
// someday these will be settable
|
||||
boolean useDate;
|
||||
int digits = 3;
|
||||
|
||||
NumberFormat numberFormat;
|
||||
SimpleDateFormat dateFormat;
|
||||
|
||||
|
||||
public String getMenuTitle() {
|
||||
return "Archive Sketch";
|
||||
}
|
||||
|
||||
|
||||
public void init(Editor editor) {
|
||||
this.editor = editor;
|
||||
|
||||
numberFormat = NumberFormat.getInstance();
|
||||
numberFormat.setGroupingUsed(false); // no commas
|
||||
numberFormat.setMinimumIntegerDigits(digits);
|
||||
|
||||
dateFormat = new SimpleDateFormat("yyMMdd");
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
Sketch sketch = editor.getSketch();
|
||||
|
||||
// first save the sketch so that things don't archive strangely
|
||||
boolean success = false;
|
||||
try {
|
||||
success = sketch.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (!success) {
|
||||
Base.showWarning("Couldn't archive sketch",
|
||||
"Archiving the sketch has been canceled because\n" +
|
||||
"the sketch couldn't save properly.", null);
|
||||
return;
|
||||
}
|
||||
|
||||
File location = sketch.getFolder();
|
||||
String name = location.getName();
|
||||
File parent = new File(location.getParent());
|
||||
|
||||
//System.out.println("loc " + location);
|
||||
//System.out.println("par " + parent);
|
||||
|
||||
File newbie = null;
|
||||
String namely = null;
|
||||
int index = 0;
|
||||
do {
|
||||
// only use the date if the sketch name isn't the default name
|
||||
useDate = !name.startsWith("sketch_");
|
||||
|
||||
if (useDate) {
|
||||
String purty = dateFormat.format(new Date());
|
||||
String stamp = purty + ((char) ('a' + index));
|
||||
namely = name + "-" + stamp;
|
||||
newbie = new File(parent, namely + ".zip");
|
||||
|
||||
} else {
|
||||
String diggie = numberFormat.format(index + 1);
|
||||
namely = name + "-" + diggie;
|
||||
newbie = new File(parent, namely + ".zip");
|
||||
}
|
||||
index++;
|
||||
} while (newbie.exists());
|
||||
|
||||
// open up a prompt for where to save this fella
|
||||
FileDialog fd =
|
||||
new FileDialog(editor, "Archive sketch as:", FileDialog.SAVE);
|
||||
fd.setDirectory(parent.getAbsolutePath());
|
||||
fd.setFile(newbie.getName());
|
||||
fd.setVisible(true);
|
||||
|
||||
String directory = fd.getDirectory();
|
||||
String filename = fd.getFile();
|
||||
|
||||
// only write the file if not canceled
|
||||
if (filename != null) {
|
||||
newbie = new File(directory, filename);
|
||||
|
||||
try {
|
||||
//System.out.println(newbie);
|
||||
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
|
||||
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
|
||||
|
||||
// recursively fill the zip file
|
||||
buildZip(location, name, zos);
|
||||
|
||||
// close up the jar file
|
||||
zos.flush();
|
||||
zos.close();
|
||||
|
||||
editor.statusNotice("Created archive " + newbie.getName() + ".");
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
editor.statusNotice("Archive sketch canceled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void buildZip(File dir, String sofar,
|
||||
ZipOutputStream zos) throws IOException {
|
||||
String files[] = dir.list();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].equals(".") ||
|
||||
files[i].equals("..")) continue;
|
||||
|
||||
File sub = new File(dir, files[i]);
|
||||
String nowfar = (sofar == null) ?
|
||||
files[i] : (sofar + "/" + files[i]);
|
||||
|
||||
if (sub.isDirectory()) {
|
||||
// directories are empty entries and have / at the end
|
||||
ZipEntry entry = new ZipEntry(nowfar + "/");
|
||||
//System.out.println(entry);
|
||||
zos.putNextEntry(entry);
|
||||
zos.closeEntry();
|
||||
buildZip(sub, nowfar, zos);
|
||||
|
||||
} else {
|
||||
ZipEntry entry = new ZipEntry(nowfar);
|
||||
entry.setTime(sub.lastModified());
|
||||
zos.putNextEntry(entry);
|
||||
zos.write(Base.loadBytesRaw(sub));
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int index = 0;
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
|
||||
String purty = formatter.format(new Date());
|
||||
do {
|
||||
newbieName = "sketch_" + purty + ((char) ('a' + index));
|
||||
newbieDir = new File(newbieParentDir, newbieName);
|
||||
index++;
|
||||
} while (newbieDir.exists());
|
||||
*/
|
946
app/src/processing/app/tools/AutoFormat.java
Normal file
946
app/src/processing/app/tools/AutoFormat.java
Normal file
@ -0,0 +1,946 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2005-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2003 Martin Gomez, Ateneo de Manila University
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Alternate handler for dealing with auto format.
|
||||
* Contributed by Martin Gomez, additional bug fixes by Ben Fry.
|
||||
*/
|
||||
public class AutoFormat implements Tool {
|
||||
Editor editor;
|
||||
|
||||
static final int BLOCK_MAXLEN = 1024;
|
||||
|
||||
StringBuffer strOut;
|
||||
//String formattedText;
|
||||
int indentValue;
|
||||
String indentChar;
|
||||
//String uhOh = null;
|
||||
//String theStuff;
|
||||
int EOF;
|
||||
BufferedInputStream bin = null;
|
||||
int nBytesRead, indexBlock, lineLength, lineNumber;
|
||||
byte bArray[];
|
||||
String strBlock;
|
||||
int s_level[];
|
||||
int c_level;
|
||||
int sp_flg[][];
|
||||
int s_ind[][];
|
||||
int s_if_lev[];
|
||||
int s_if_flg[];
|
||||
int if_lev, if_flg, level;
|
||||
int ind[];
|
||||
int e_flg, paren;
|
||||
static int p_flg[];
|
||||
char l_char, p_char;
|
||||
int a_flg, q_flg, ct;
|
||||
int s_tabs[][];
|
||||
String w_if_, w_else, w_for, w_ds, w_case, w_cpp_comment, w_jdoc;
|
||||
int jdoc, j;
|
||||
char string[];
|
||||
byte bstring[];
|
||||
byte bblank;
|
||||
char cc;
|
||||
int s_flg, b_flg;
|
||||
int peek;
|
||||
char peekc;
|
||||
int tabs;
|
||||
char next_char, last_char;
|
||||
char lastc0, lastc1;
|
||||
char c, c0;
|
||||
char w_kptr;
|
||||
|
||||
String line_feed;
|
||||
|
||||
//static int outfil; // temporary
|
||||
|
||||
|
||||
public void init(Editor editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
|
||||
public String getMenuTitle() {
|
||||
return "Auto Format";
|
||||
}
|
||||
|
||||
public void comment() throws IOException {
|
||||
int save_s_flg;
|
||||
save_s_flg = s_flg;
|
||||
|
||||
int done = 0;
|
||||
c = string[j++] = getchr(); // extra char
|
||||
while (done == 0) {
|
||||
c = string[j++] = getchr();
|
||||
while ((c != '/') && (j < string.length)) {
|
||||
if(c == '\n' || c == '\r') {
|
||||
lineNumber++;
|
||||
putcoms();
|
||||
s_flg = 1;
|
||||
}
|
||||
c = string[j++] = getchr();
|
||||
}
|
||||
//String tmpstr = new String(string);
|
||||
if (j>1 && string[j-2] == '*') {
|
||||
done = 1;
|
||||
jdoc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
putcoms();
|
||||
s_flg = save_s_flg;
|
||||
jdoc = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public char get_string() throws IOException {
|
||||
char ch;
|
||||
ch = '*';
|
||||
while (true) {
|
||||
switch (ch) {
|
||||
default:
|
||||
ch = string[j++] = getchr();
|
||||
if (ch == '\\') {
|
||||
string[j++] = getchr();
|
||||
break;
|
||||
}
|
||||
if (ch == '\'' || ch == '"') {
|
||||
cc = string[j++] = getchr();
|
||||
while (cc != ch) {
|
||||
if (cc == '\\') string[j++] = getchr();
|
||||
cc = string[j++] = getchr();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ch == '\n' || ch == '\r') {
|
||||
indent_puts();
|
||||
a_flg = 1;
|
||||
break;
|
||||
} else {
|
||||
return(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void indent_puts() {
|
||||
string[j] = '\0';
|
||||
if (j > 0) {
|
||||
if (s_flg != 0) {
|
||||
if((tabs > 0) && (string[0] != '{') && (a_flg == 1)) {
|
||||
tabs++;
|
||||
}
|
||||
p_tabs();
|
||||
s_flg = 0;
|
||||
if ((tabs > 0) && (string[0] != '{') && (a_flg == 1)) {
|
||||
tabs--;
|
||||
}
|
||||
a_flg = 0;
|
||||
}
|
||||
String j_string = new String(string);
|
||||
strOut.append(j_string.substring(0,j));
|
||||
for (int i=0; i<j; i++) string[i] = '\0';
|
||||
j = 0;
|
||||
|
||||
} else {
|
||||
if (s_flg != 0) {
|
||||
s_flg = 0;
|
||||
a_flg = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//public void fprintf(int outfil, String out_string) {
|
||||
public void fprintf(String out_string) {
|
||||
//int out_len = out_string.length();
|
||||
//String j_string = new String(string);
|
||||
strOut.append(out_string);
|
||||
}
|
||||
|
||||
|
||||
public int grabLines() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
|
||||
/* special edition of put string for comment processing */
|
||||
public void putcoms()
|
||||
{
|
||||
int i = 0;
|
||||
int sav_s_flg = s_flg;
|
||||
if(j > 0)
|
||||
{
|
||||
if(s_flg != 0)
|
||||
{
|
||||
p_tabs();
|
||||
s_flg = 0;
|
||||
}
|
||||
string[j] = '\0';
|
||||
i = 0;
|
||||
while (string[i] == ' ') i++;
|
||||
if (lookup_com(w_jdoc) == 1) jdoc = 1;
|
||||
String strBuffer = new String(string,0,j);
|
||||
if (string[i] == '/' && string[i+1]=='*')
|
||||
{
|
||||
if ((last_char != ';') && (sav_s_flg==1) )
|
||||
{
|
||||
//fprintf(outfil, strBuffer.substring(i,j));
|
||||
fprintf(strBuffer.substring(i,j));
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(outfil, strBuffer);
|
||||
fprintf(strBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string[i]=='*' || jdoc == 0)
|
||||
//fprintf (outfil, " "+strBuffer.substring(i,j));
|
||||
fprintf (" "+strBuffer.substring(i,j));
|
||||
else
|
||||
//fprintf (outfil, " * "+strBuffer.substring(i,j));
|
||||
fprintf (" * "+strBuffer.substring(i,j));
|
||||
}
|
||||
j = 0;
|
||||
string[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
public void cpp_comment() throws IOException
|
||||
{
|
||||
c = getchr();
|
||||
while(c != '\n' && c != '\r' && j<133)
|
||||
{
|
||||
string[j++] = c;
|
||||
c = getchr();
|
||||
}
|
||||
lineNumber++;
|
||||
indent_puts();
|
||||
s_flg = 1;
|
||||
}
|
||||
|
||||
|
||||
/* expand indentValue into tabs and spaces */
|
||||
public void p_tabs()
|
||||
{
|
||||
int i,k;
|
||||
|
||||
if (tabs<0) tabs = 0;
|
||||
if (tabs==0) return;
|
||||
i = tabs * indentValue; // calc number of spaces
|
||||
//j = i/8; /* calc number of tab chars */
|
||||
|
||||
for (k=0; k < i; k++) {
|
||||
strOut.append(indentChar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public char getchr() throws IOException
|
||||
{
|
||||
if((peek < 0) && (last_char != ' ') && (last_char != '\t'))
|
||||
{
|
||||
if((last_char != '\n') && (last_char != '\r'))
|
||||
p_char = last_char;
|
||||
}
|
||||
if(peek > 0) /* char was read previously */
|
||||
{
|
||||
last_char = peekc;
|
||||
peek = -1;
|
||||
}
|
||||
else /* read next char in string */
|
||||
{
|
||||
indexBlock++;
|
||||
if (indexBlock >= lineLength)
|
||||
{
|
||||
for (int ib=0; ib<nBytesRead; ib++) bArray[ib] = '\0';
|
||||
|
||||
lineLength = nBytesRead = 0;
|
||||
//try /* to get the next block */
|
||||
//{
|
||||
if (bin.available() > 0)
|
||||
{
|
||||
nBytesRead = bin.read(bArray);
|
||||
lineLength = nBytesRead;
|
||||
strBlock = new String(bArray);
|
||||
indexBlock = 0;
|
||||
last_char = strBlock.charAt(indexBlock);
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
}
|
||||
else
|
||||
{
|
||||
//System.out.println("eof a");
|
||||
EOF = 1;
|
||||
peekc = '\0';
|
||||
}
|
||||
//}
|
||||
//catch(IOException ioe)
|
||||
//{
|
||||
//System.out.println(ioe.toString());
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_char = strBlock.charAt(indexBlock);
|
||||
}
|
||||
}
|
||||
peek = -1;
|
||||
if (last_char == '\r')
|
||||
{
|
||||
last_char = getchr();
|
||||
}
|
||||
|
||||
return last_char;
|
||||
}
|
||||
|
||||
/* else processing */
|
||||
public void gotelse()
|
||||
{
|
||||
tabs = s_tabs[c_level][if_lev];
|
||||
p_flg[level] = sp_flg[c_level][if_lev];
|
||||
ind[level] = s_ind[c_level][if_lev];
|
||||
if_flg = 1;
|
||||
}
|
||||
|
||||
/* read to new_line */
|
||||
public int getnl() throws IOException
|
||||
{
|
||||
int save_s_flg;
|
||||
save_s_flg = tabs;
|
||||
peekc = getchr();
|
||||
//while ((peekc == '\t' || peekc == ' ') &&
|
||||
// (j < string.length)) {
|
||||
while (peekc == '\t' || peekc == ' ') {
|
||||
string[j++] = peekc;
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
peekc = getchr();
|
||||
peek = 1;
|
||||
}
|
||||
peek = 1;
|
||||
|
||||
if (peekc == '/')
|
||||
{
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
peekc = getchr();
|
||||
if (peekc == '*')
|
||||
{
|
||||
string[j++] = '/';
|
||||
string[j++] = '*';
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
comment();
|
||||
}
|
||||
else if (peekc == '/')
|
||||
{
|
||||
string[j++] = '/';
|
||||
string[j++] = '/';
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
cpp_comment();
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
string[j++] = '/';
|
||||
peek = 1;
|
||||
}
|
||||
}
|
||||
peekc = getchr();
|
||||
if(peekc == '\n')
|
||||
{
|
||||
lineNumber++;
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
tabs = save_s_flg;
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
peek = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int lookup (String keyword)
|
||||
{
|
||||
char r;
|
||||
int l,kk; //,k,i;
|
||||
String j_string = new String(string);
|
||||
|
||||
if (j<1) return (0);
|
||||
kk=0;
|
||||
while(string[kk] == ' ')kk++;
|
||||
l=0;
|
||||
l = j_string.indexOf(keyword);
|
||||
if (l<0 || l!=kk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
r = string[kk+keyword.length()];
|
||||
if(r >= 'a' && r <= 'z') return(0);
|
||||
if(r >= 'A' && r <= 'Z') return(0);
|
||||
if(r >= '0' && r <= '9') return(0);
|
||||
if(r == '_' || r == '&') return(0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
public int lookup_com (String keyword)
|
||||
{
|
||||
//char r;
|
||||
int l,kk; //,k,i;
|
||||
String j_string = new String(string);
|
||||
|
||||
if (j<1) return (0);
|
||||
kk=0;
|
||||
while(string[kk] == ' ')kk++;
|
||||
l=0;
|
||||
l = j_string.indexOf(keyword);
|
||||
if (l<0 || l!=kk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
StringBuffer onechar;
|
||||
|
||||
// Adding an additional newline as a hack around other errors
|
||||
String originalText = editor.getText() + "\n";
|
||||
strOut = new StringBuffer();
|
||||
indentValue = Preferences.getInteger("editor.tabs.size");
|
||||
indentChar = new String(" ");
|
||||
|
||||
lineNumber = 0;
|
||||
//BLOCK_MAXLEN = 256;
|
||||
c_level = if_lev = level = e_flg = paren = 0;
|
||||
a_flg = q_flg = j = b_flg = tabs = 0;
|
||||
if_flg = peek = -1;
|
||||
peekc = '`';
|
||||
s_flg = 1;
|
||||
bblank = ' ';
|
||||
jdoc = 0;
|
||||
|
||||
s_level = new int[10];
|
||||
sp_flg = new int[20][10];
|
||||
s_ind = new int[20][10];
|
||||
s_if_lev = new int[10];
|
||||
s_if_flg = new int[10];
|
||||
ind = new int[10];
|
||||
p_flg = new int[10];
|
||||
s_tabs = new int[20][10];
|
||||
|
||||
w_else = new String ("else");
|
||||
w_if_ = new String ("if");
|
||||
w_for = new String ("for");
|
||||
w_ds = new String ("default");
|
||||
w_case = new String ("case");
|
||||
w_cpp_comment = new String ("//");
|
||||
w_jdoc = new String ("/**");
|
||||
line_feed = new String ("\n");
|
||||
|
||||
// read as long as there is something to read
|
||||
EOF = 0; // = 1 set in getchr when EOF
|
||||
|
||||
bArray = new byte[BLOCK_MAXLEN];
|
||||
string = new char[BLOCK_MAXLEN];
|
||||
try { // the whole process
|
||||
// open for input
|
||||
ByteArrayInputStream in =
|
||||
new ByteArrayInputStream(originalText.getBytes());
|
||||
|
||||
// add buffering to that InputStream
|
||||
bin = new BufferedInputStream(in);
|
||||
|
||||
for (int ib = 0; ib < BLOCK_MAXLEN; ib++) bArray[ib] = '\0';
|
||||
|
||||
lineLength = nBytesRead = 0;
|
||||
// read up a block - remember how many bytes read
|
||||
nBytesRead = bin.read(bArray);
|
||||
strBlock = new String(bArray);
|
||||
|
||||
lineLength = nBytesRead;
|
||||
lineNumber = 1;
|
||||
indexBlock = -1;
|
||||
j = 0;
|
||||
while (EOF == 0)
|
||||
{
|
||||
c = getchr();
|
||||
switch(c)
|
||||
{
|
||||
default:
|
||||
string[j++] = c;
|
||||
if(c != ',')
|
||||
{
|
||||
l_char = c;
|
||||
}
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if(lookup(w_else) == 1)
|
||||
{
|
||||
gotelse();
|
||||
if(s_flg == 0 || j > 0)string[j++] = c;
|
||||
indent_puts();
|
||||
s_flg = 0;
|
||||
break;
|
||||
}
|
||||
if(s_flg == 0 || j > 0)string[j++] = c;
|
||||
break;
|
||||
|
||||
case '\r': // <CR> for MS Windows 95
|
||||
case '\n':
|
||||
lineNumber++;
|
||||
if (EOF==1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
//String j_string = new String(string);
|
||||
|
||||
e_flg = lookup(w_else);
|
||||
if(e_flg == 1) gotelse();
|
||||
if (lookup_com(w_cpp_comment) == 1)
|
||||
{
|
||||
if (string[j] == '\n')
|
||||
{
|
||||
string[j] = '\0';
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
indent_puts();
|
||||
//fprintf(outfil, line_feed);
|
||||
fprintf(line_feed);
|
||||
s_flg = 1;
|
||||
if(e_flg == 1)
|
||||
{
|
||||
p_flg[level]++;
|
||||
tabs++;
|
||||
}
|
||||
else
|
||||
if(p_char == l_char)
|
||||
{
|
||||
a_flg = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '{':
|
||||
if(lookup(w_else) == 1)gotelse();
|
||||
s_if_lev[c_level] = if_lev;
|
||||
s_if_flg[c_level] = if_flg;
|
||||
if_lev = if_flg = 0;
|
||||
c_level++;
|
||||
if(s_flg == 1 && p_flg[level] != 0)
|
||||
{
|
||||
p_flg[level]--;
|
||||
tabs--;
|
||||
}
|
||||
string[j++] = c;
|
||||
indent_puts();
|
||||
getnl() ;
|
||||
indent_puts();
|
||||
//fprintf(outfil,"\n");
|
||||
fprintf("\n");
|
||||
tabs++;
|
||||
s_flg = 1;
|
||||
if(p_flg[level] > 0)
|
||||
{
|
||||
ind[level] = 1;
|
||||
level++;
|
||||
s_level[level] = c_level;
|
||||
}
|
||||
break;
|
||||
|
||||
case '}':
|
||||
c_level--;
|
||||
if (c_level < 0)
|
||||
{
|
||||
EOF = 1;
|
||||
//System.out.println("eof b");
|
||||
string[j++] = c;
|
||||
indent_puts();
|
||||
break;
|
||||
}
|
||||
if ((if_lev = s_if_lev[c_level]-1) < 0)
|
||||
if_lev = 0;
|
||||
if_flg = s_if_flg[c_level];
|
||||
indent_puts();
|
||||
tabs--;
|
||||
p_tabs();
|
||||
peekc = getchr();
|
||||
if( peekc == ';')
|
||||
{
|
||||
onechar = new StringBuffer();
|
||||
onechar.append(c); // the }
|
||||
onechar.append(';');
|
||||
//fprintf(outfil, onechar.toString());
|
||||
fprintf(onechar.toString());
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
}
|
||||
else
|
||||
{
|
||||
onechar = new StringBuffer();
|
||||
onechar.append(c);
|
||||
//fprintf(outfil, onechar.toString());
|
||||
fprintf(onechar.toString());
|
||||
peek = 1;
|
||||
}
|
||||
getnl();
|
||||
indent_puts();
|
||||
//fprintf(outfil,"\n");
|
||||
fprintf("\n");
|
||||
s_flg = 1;
|
||||
if(c_level < s_level[level])
|
||||
if(level > 0) level--;
|
||||
if(ind[level] != 0)
|
||||
{
|
||||
tabs -= p_flg[level];
|
||||
p_flg[level] = 0;
|
||||
ind[level] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
string[j++] = c;
|
||||
cc = getchr();
|
||||
while(cc != c)
|
||||
{
|
||||
// max. length of line should be 256
|
||||
string[j++] = cc;
|
||||
|
||||
if(cc == '\\')
|
||||
{
|
||||
cc = string[j++] = getchr();
|
||||
}
|
||||
if(cc == '\n')
|
||||
{
|
||||
lineNumber++;
|
||||
indent_puts();
|
||||
s_flg = 1;
|
||||
}
|
||||
cc = getchr();
|
||||
|
||||
}
|
||||
string[j++] = cc;
|
||||
if(getnl() == 1)
|
||||
{
|
||||
l_char = cc;
|
||||
peek = 1;
|
||||
peekc = '\n';
|
||||
}
|
||||
break;
|
||||
|
||||
case ';':
|
||||
string[j++] = c;
|
||||
indent_puts();
|
||||
if(p_flg[level] > 0 && ind[level] == 0)
|
||||
{
|
||||
tabs -= p_flg[level];
|
||||
p_flg[level] = 0;
|
||||
}
|
||||
getnl();
|
||||
indent_puts();
|
||||
//fprintf(outfil,"\n");
|
||||
fprintf("\n");
|
||||
s_flg = 1;
|
||||
if(if_lev > 0)
|
||||
if(if_flg == 1)
|
||||
{
|
||||
if_lev--;
|
||||
if_flg = 0;
|
||||
}
|
||||
else if_lev = 0;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
string[j++] = c;
|
||||
string[j++] = getchr();
|
||||
break;
|
||||
|
||||
case '?':
|
||||
q_flg = 1;
|
||||
string[j++] = c;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
string[j++] = c;
|
||||
peekc = getchr();
|
||||
if(peekc == ':')
|
||||
{
|
||||
indent_puts();
|
||||
//fprintf (outfil,":");
|
||||
fprintf(":");
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
//int double_colon = 0;
|
||||
peek = 1;
|
||||
}
|
||||
|
||||
if(q_flg == 1)
|
||||
{
|
||||
q_flg = 0;
|
||||
break;
|
||||
}
|
||||
if(lookup(w_ds) == 0 && lookup(w_case) == 0)
|
||||
{
|
||||
s_flg = 0;
|
||||
indent_puts();
|
||||
}
|
||||
else
|
||||
{
|
||||
tabs--;
|
||||
indent_puts();
|
||||
tabs++;
|
||||
}
|
||||
peekc = getchr();
|
||||
if(peekc == ';')
|
||||
{
|
||||
//fprintf(outfil,";");
|
||||
fprintf(";");
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
}
|
||||
else
|
||||
{
|
||||
peek = 1;
|
||||
}
|
||||
getnl();
|
||||
indent_puts();
|
||||
//fprintf(outfil,"\n");
|
||||
fprintf("\n");
|
||||
s_flg = 1;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
c0 = string[j];
|
||||
string[j++] = c;
|
||||
peekc = getchr();
|
||||
|
||||
if(peekc == '/')
|
||||
{
|
||||
string[j++] = peekc;
|
||||
peekc = '`';
|
||||
peek = -1;
|
||||
cpp_comment();
|
||||
//fprintf(outfil,"\n");
|
||||
fprintf("\n");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
peek = 1;
|
||||
}
|
||||
|
||||
if(peekc != '*') {
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (j > 0) string[j--] = '\0';
|
||||
if (j > 0) indent_puts();
|
||||
string[j++] = '/';
|
||||
string[j++] = '*';
|
||||
peek = -1;
|
||||
peekc = '`';
|
||||
comment();
|
||||
break;
|
||||
}
|
||||
|
||||
case '#':
|
||||
string[j++] = c;
|
||||
cc = getchr();
|
||||
while(cc != '\n')
|
||||
{
|
||||
string[j++] = cc;
|
||||
cc = getchr();
|
||||
}
|
||||
string[j++] = cc;
|
||||
s_flg = 0;
|
||||
indent_puts();
|
||||
s_flg = 1;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
paren--;
|
||||
if (paren < 0)
|
||||
{
|
||||
EOF = 1;
|
||||
//System.out.println("eof c");
|
||||
}
|
||||
string[j++] = c;
|
||||
indent_puts();
|
||||
if(getnl() == 1)
|
||||
{
|
||||
peekc = '\n';
|
||||
peek = 1;
|
||||
if(paren != 0)
|
||||
{
|
||||
a_flg = 1;
|
||||
}
|
||||
else if(tabs > 0)
|
||||
{
|
||||
p_flg[level]++;
|
||||
tabs++;
|
||||
ind[level] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '(':
|
||||
string[j++] = c;
|
||||
paren++;
|
||||
if ((lookup(w_for) == 1))
|
||||
{
|
||||
c = get_string();
|
||||
while(c != ';') c = get_string();
|
||||
ct=0;
|
||||
int for_done = 0;
|
||||
while (for_done==0)
|
||||
{
|
||||
c = get_string();
|
||||
while(c != ')')
|
||||
{
|
||||
if(c == '(') ct++;
|
||||
c = get_string();
|
||||
}
|
||||
if(ct != 0)
|
||||
{
|
||||
ct--;
|
||||
}
|
||||
else for_done = 1;
|
||||
} // endwhile for_done
|
||||
paren--;
|
||||
if (paren < 0)
|
||||
{
|
||||
EOF = 1;
|
||||
//System.out.println("eof d");
|
||||
}
|
||||
indent_puts();
|
||||
if(getnl() == 1)
|
||||
{
|
||||
peekc = '\n';
|
||||
peek = 1;
|
||||
p_flg[level]++;
|
||||
tabs++;
|
||||
ind[level] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(lookup(w_if_) == 1)
|
||||
{
|
||||
indent_puts();
|
||||
s_tabs[c_level][if_lev] = tabs;
|
||||
sp_flg[c_level][if_lev] = p_flg[level];
|
||||
s_ind[c_level][if_lev] = ind[level];
|
||||
if_lev++;
|
||||
if_flg = 1;
|
||||
}
|
||||
} // end switch
|
||||
|
||||
//System.out.println("string len is " + string.length);
|
||||
//if (EOF == 1) System.out.println(string);
|
||||
//String j_string = new String(string);
|
||||
|
||||
} // end while not EOF
|
||||
|
||||
/*
|
||||
int bad;
|
||||
while ((bad = bin.read()) != -1) {
|
||||
System.out.print((char) bad);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
char bad;
|
||||
//while ((bad = getchr()) != 0) {
|
||||
while (true) {
|
||||
getchr();
|
||||
if (peek != -1) {
|
||||
System.out.print(last_char);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// save current (rough) selection point
|
||||
int selectionEnd = editor.getSelectionStop();
|
||||
|
||||
// make sure the caret would be past the end of the text
|
||||
if (strOut.length() < selectionEnd - 1) {
|
||||
selectionEnd = strOut.length() - 1;
|
||||
}
|
||||
|
||||
bin.close(); // close buff
|
||||
|
||||
String formattedText = strOut.toString();
|
||||
if (formattedText.equals(originalText)) {
|
||||
editor.statusNotice("No changes necessary for Auto Format.");
|
||||
|
||||
} else if (paren != 0) {
|
||||
// warn user if there are too many parens in either direction
|
||||
editor.statusError("Auto Format Canceled: Too many " +
|
||||
((paren < 0) ? "right" : "left") +
|
||||
" parentheses.");
|
||||
|
||||
} else if (c_level != 0) { // check braces only if parens are ok
|
||||
editor.statusError("Auto Format Canceled: Too many " +
|
||||
((c_level < 0) ? "right" : "left") +
|
||||
" curly braces.");
|
||||
|
||||
} else {
|
||||
// replace with new bootiful text
|
||||
// selectionEnd hopefully at least in the neighborhood
|
||||
editor.setText(formattedText);
|
||||
editor.setSelection(selectionEnd, selectionEnd);
|
||||
editor.getSketch().setModified(true);
|
||||
// mark as finished
|
||||
editor.statusNotice("Auto Format finished.");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
editor.statusError(e);
|
||||
}
|
||||
}
|
||||
}
|
596
app/src/processing/app/tools/ColorSelector.java
Normal file
596
app/src/processing/app/tools/ColorSelector.java
Normal file
@ -0,0 +1,596 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2006-08 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
|
||||
/**
|
||||
* Color selector tool for the Tools menu.
|
||||
* <p/>
|
||||
* Using the keyboard shortcuts, you can copy/paste the values for the
|
||||
* colors and paste them into your program. We didn't do any sort of
|
||||
* auto-insert of colorMode() or fill() or stroke() code cuz we couldn't
|
||||
* decide on a good way to do this.. your contributions welcome).
|
||||
*/
|
||||
public class ColorSelector implements Tool, DocumentListener {
|
||||
|
||||
Editor editor;
|
||||
JFrame frame;
|
||||
|
||||
int hue, saturation, brightness; // range 360, 100, 100
|
||||
int red, green, blue; // range 256, 256, 256
|
||||
|
||||
ColorRange range;
|
||||
ColorSlider slider;
|
||||
|
||||
JTextField hueField, saturationField, brightnessField;
|
||||
JTextField redField, greenField, blueField;
|
||||
|
||||
JTextField hexField;
|
||||
|
||||
JPanel colorPanel;
|
||||
|
||||
|
||||
public String getMenuTitle() {
|
||||
return "Color Selector";
|
||||
}
|
||||
|
||||
|
||||
public void init(Editor editor) {
|
||||
this.editor = editor;
|
||||
|
||||
frame = new JFrame("Color Selector");
|
||||
frame.getContentPane().setLayout(new BorderLayout());
|
||||
|
||||
Box box = Box.createHorizontalBox();
|
||||
box.setBorder(new EmptyBorder(12, 12, 12, 12));
|
||||
|
||||
range = new ColorRange();
|
||||
range.init();
|
||||
Box rangeBox = new Box(BoxLayout.Y_AXIS);
|
||||
rangeBox.setAlignmentY(0);
|
||||
rangeBox.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
||||
rangeBox.add(range);
|
||||
box.add(rangeBox);
|
||||
box.add(Box.createHorizontalStrut(10));
|
||||
|
||||
slider = new ColorSlider();
|
||||
slider.init();
|
||||
Box sliderBox = new Box(BoxLayout.Y_AXIS);
|
||||
sliderBox.setAlignmentY(0);
|
||||
sliderBox.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
||||
sliderBox.add(slider);
|
||||
box.add(sliderBox);
|
||||
box.add(Box.createHorizontalStrut(10));
|
||||
|
||||
box.add(createColorFields());
|
||||
box.add(Box.createHorizontalStrut(10));
|
||||
|
||||
frame.getContentPane().add(box, BorderLayout.CENTER);
|
||||
frame.pack();
|
||||
frame.setResizable(false);
|
||||
|
||||
// these don't help either.. they fix the component size but
|
||||
// leave a gap where the component is located
|
||||
//range.setSize(256, 256);
|
||||
//slider.setSize(256, 20);
|
||||
|
||||
Dimension size = frame.getSize();
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
frame.setLocation((screen.width - size.width) / 2,
|
||||
(screen.height - size.height) / 2);
|
||||
|
||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
});
|
||||
Base.registerWindowCloseKeys(frame.getRootPane(), new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
});
|
||||
Base.setIcon(frame);
|
||||
|
||||
hueField.getDocument().addDocumentListener(this);
|
||||
saturationField.getDocument().addDocumentListener(this);
|
||||
brightnessField.getDocument().addDocumentListener(this);
|
||||
redField.getDocument().addDocumentListener(this);
|
||||
greenField.getDocument().addDocumentListener(this);
|
||||
blueField.getDocument().addDocumentListener(this);
|
||||
hexField.getDocument().addDocumentListener(this);
|
||||
|
||||
hexField.setText("FFFFFF");
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
frame.setVisible(true);
|
||||
// You've got to be f--ing kidding me.. why did the following line
|
||||
// get deprecated for the pile of s-- that follows it?
|
||||
//frame.setCursor(Cursor.CROSSHAIR_CURSOR);
|
||||
frame.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
|
||||
}
|
||||
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
//System.out.println("changed");
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
//System.out.println("remove");
|
||||
}
|
||||
|
||||
|
||||
boolean updating;
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
if (updating) return; // don't update forever recursively
|
||||
updating = true;
|
||||
|
||||
Document doc = e.getDocument();
|
||||
if (doc == hueField.getDocument()) {
|
||||
hue = bounded(hue, hueField, 359);
|
||||
updateRGB();
|
||||
updateHex();
|
||||
|
||||
} else if (doc == saturationField.getDocument()) {
|
||||
saturation = bounded(saturation, saturationField, 99);
|
||||
updateRGB();
|
||||
updateHex();
|
||||
|
||||
} else if (doc == brightnessField.getDocument()) {
|
||||
brightness = bounded(brightness, brightnessField, 99);
|
||||
updateRGB();
|
||||
updateHex();
|
||||
|
||||
} else if (doc == redField.getDocument()) {
|
||||
red = bounded(red, redField, 255);
|
||||
updateHSB();
|
||||
updateHex();
|
||||
|
||||
} else if (doc == greenField.getDocument()) {
|
||||
green = bounded(green, greenField, 255);
|
||||
updateHSB();
|
||||
updateHex();
|
||||
|
||||
} else if (doc == blueField.getDocument()) {
|
||||
blue = bounded(blue, blueField, 255);
|
||||
updateHSB();
|
||||
updateHex();
|
||||
|
||||
} else if (doc == hexField.getDocument()) {
|
||||
String str = hexField.getText();
|
||||
while (str.length() < 6) {
|
||||
str += "0";
|
||||
}
|
||||
if (str.length() > 6) {
|
||||
str = str.substring(0, 6);
|
||||
}
|
||||
updateRGB2(Integer.parseInt(str, 16));
|
||||
updateHSB();
|
||||
}
|
||||
range.redraw();
|
||||
slider.redraw();
|
||||
colorPanel.repaint();
|
||||
updating = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the RGB values based on the current HSB values.
|
||||
*/
|
||||
protected void updateRGB() {
|
||||
int rgb = Color.HSBtoRGB((float)hue / 359f,
|
||||
(float)saturation / 99f,
|
||||
(float)brightness / 99f);
|
||||
updateRGB2(rgb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the RGB values based on a calculated ARGB int.
|
||||
* Used by both updateRGB() to set the color from the HSB values,
|
||||
* and by updateHex(), to unpack the hex colors and assign them.
|
||||
*/
|
||||
protected void updateRGB2(int rgb) {
|
||||
red = (rgb >> 16) & 0xff;
|
||||
green = (rgb >> 8) & 0xff;
|
||||
blue = rgb & 0xff;
|
||||
|
||||
redField.setText(String.valueOf(red));
|
||||
greenField.setText(String.valueOf(green));
|
||||
blueField.setText(String.valueOf(blue));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the HSB values based on the current RGB values.
|
||||
*/
|
||||
protected void updateHSB() {
|
||||
float hsb[] = new float[3];
|
||||
Color.RGBtoHSB(red, green, blue, hsb);
|
||||
|
||||
hue = (int) (hsb[0] * 359.0f);
|
||||
saturation = (int) (hsb[1] * 99.0f);
|
||||
brightness = (int) (hsb[2] * 99.0f);
|
||||
|
||||
hueField.setText(String.valueOf(hue));
|
||||
saturationField.setText(String.valueOf(saturation));
|
||||
brightnessField.setText(String.valueOf(brightness));
|
||||
}
|
||||
|
||||
|
||||
protected void updateHex() {
|
||||
hexField.setText(PApplet.hex(red, 2) +
|
||||
PApplet.hex(green, 2) +
|
||||
PApplet.hex(blue, 2));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the bounded value for a specific range. If the value is outside
|
||||
* the max, you can't edit right away, so just act as if it's already
|
||||
* been bounded and return the bounded value, then fire an event to set
|
||||
* it to the value that was just returned.
|
||||
*/
|
||||
protected int bounded(int current, final JTextField field, final int max) {
|
||||
String text = field.getText();
|
||||
if (text.length() == 0) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
int value = Integer.parseInt(text);
|
||||
if (value > max) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
field.setText(String.valueOf(max));
|
||||
}
|
||||
});
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
return current; // should not be reachable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Container createColorFields() {
|
||||
Box box = Box.createVerticalBox();
|
||||
box.setAlignmentY(0);
|
||||
|
||||
colorPanel = new JPanel() {
|
||||
public void paintComponent(Graphics g) {
|
||||
g.setColor(new Color(red, green, blue));
|
||||
Dimension size = getSize();
|
||||
g.fillRect(0, 0, size.width, size.height);
|
||||
}
|
||||
};
|
||||
colorPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
||||
Dimension dim = new Dimension(60, 40);
|
||||
colorPanel.setMinimumSize(dim);
|
||||
//colorPanel.setMaximumSize(dim);
|
||||
//colorPanel.setPreferredSize(dim);
|
||||
box.add(colorPanel);
|
||||
box.add(Box.createVerticalStrut(10));
|
||||
|
||||
Box row;
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("H:"));
|
||||
row.add(hueField = new NumberField(4, false));
|
||||
row.add(new JLabel(" \u00B0")); // degree symbol
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(5));
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("S:"));
|
||||
row.add(saturationField = new NumberField(4, false));
|
||||
row.add(new JLabel(" %"));
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(5));
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("B:"));
|
||||
row.add(brightnessField = new NumberField(4, false));
|
||||
row.add(new JLabel(" %"));
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(10));
|
||||
|
||||
//
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("R:"));
|
||||
row.add(redField = new NumberField(4, false));
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(5));
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("G:"));
|
||||
row.add(greenField = new NumberField(4, false));
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(5));
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("B:"));
|
||||
row.add(blueField = new NumberField(4, false));
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(10));
|
||||
|
||||
//
|
||||
|
||||
row = Box.createHorizontalBox();
|
||||
row.add(createFixedLabel("#"));
|
||||
row.add(hexField = new NumberField(5, true));
|
||||
row.add(Box.createHorizontalGlue());
|
||||
box.add(row);
|
||||
box.add(Box.createVerticalStrut(10));
|
||||
|
||||
box.add(Box.createVerticalGlue());
|
||||
return box;
|
||||
}
|
||||
|
||||
|
||||
int labelH;
|
||||
|
||||
/**
|
||||
* return a label of a fixed width
|
||||
*/
|
||||
protected JLabel createFixedLabel(String title) {
|
||||
JLabel label = new JLabel(title);
|
||||
if (labelH == 0) {
|
||||
labelH = label.getPreferredSize().height;
|
||||
}
|
||||
Dimension dim = new Dimension(20, labelH);
|
||||
label.setPreferredSize(dim);
|
||||
label.setMinimumSize(dim);
|
||||
label.setMaximumSize(dim);
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
public class ColorRange extends PApplet {
|
||||
|
||||
static final int WIDE = 256;
|
||||
static final int HIGH = 256;
|
||||
|
||||
int lastX, lastY;
|
||||
|
||||
|
||||
public void setup() {
|
||||
size(WIDE, HIGH, P3D);
|
||||
noLoop();
|
||||
|
||||
colorMode(HSB, 360, 256, 256);
|
||||
noFill();
|
||||
rectMode(CENTER);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
if ((g == null) || (g.pixels == null)) return;
|
||||
if ((width != WIDE) || (height < HIGH)) {
|
||||
//System.out.println("bad size " + width + " " + height);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (int j = 0; j < 256; j++) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
g.pixels[index++] = color(hue, i, 255 - j);
|
||||
}
|
||||
}
|
||||
|
||||
stroke((brightness > 50) ? 0 : 255);
|
||||
rect(lastX, lastY, 9, 9);
|
||||
}
|
||||
|
||||
public void mousePressed() {
|
||||
updateMouse();
|
||||
}
|
||||
|
||||
public void mouseDragged() {
|
||||
updateMouse();
|
||||
}
|
||||
|
||||
public void updateMouse() {
|
||||
if ((mouseX >= 0) && (mouseX < 256) &&
|
||||
(mouseY >= 0) && (mouseY < 256)) {
|
||||
int nsaturation = (int) (100 * (mouseX / 255.0f));
|
||||
int nbrightness = 100 - ((int) (100 * (mouseY / 255.0f)));
|
||||
saturationField.setText(String.valueOf(nsaturation));
|
||||
brightnessField.setText(String.valueOf(nbrightness));
|
||||
|
||||
lastX = mouseX;
|
||||
lastY = mouseY;
|
||||
}
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
//System.out.println("getting pref " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
//System.out.println("getting min " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
//System.out.println("getting max " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ColorSlider extends PApplet {
|
||||
|
||||
static final int WIDE = 20;
|
||||
static final int HIGH = 256;
|
||||
|
||||
public void setup() {
|
||||
size(WIDE, HIGH, P3D);
|
||||
colorMode(HSB, 255, 100, 100);
|
||||
noLoop();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
if ((g == null) || (g.pixels == null)) return;
|
||||
if ((width != WIDE) || (height < HIGH)) {
|
||||
//System.out.println("bad size " + width + " " + height);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
int sel = 255 - (int) (255 * (hue / 359f));
|
||||
for (int j = 0; j < 256; j++) {
|
||||
int c = color(255 - j, 100, 100);
|
||||
if (j == sel) c = 0xFF000000;
|
||||
for (int i = 0; i < WIDE; i++) {
|
||||
g.pixels[index++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mousePressed() {
|
||||
updateMouse();
|
||||
}
|
||||
|
||||
public void mouseDragged() {
|
||||
updateMouse();
|
||||
}
|
||||
|
||||
public void updateMouse() {
|
||||
if ((mouseX >= 0) && (mouseX < 256) &&
|
||||
(mouseY >= 0) && (mouseY < 256)) {
|
||||
int nhue = 359 - (int) (359 * (mouseY / 255.0f));
|
||||
hueField.setText(String.valueOf(nhue));
|
||||
}
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
//System.out.println("s getting pref " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
//System.out.println("s getting min " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
//System.out.println("s getting max " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extension of JTextField that only allows numbers
|
||||
*/
|
||||
class NumberField extends JTextField {
|
||||
|
||||
public boolean allowHex;
|
||||
|
||||
public NumberField(int cols, boolean allowHex) {
|
||||
super(cols);
|
||||
this.allowHex = allowHex;
|
||||
}
|
||||
|
||||
protected Document createDefaultModel() {
|
||||
return new NumberDocument(this);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
if (!allowHex) {
|
||||
return new Dimension(35, super.getPreferredSize().height);
|
||||
}
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Document model to go with JTextField that only allows numbers.
|
||||
*/
|
||||
class NumberDocument extends PlainDocument {
|
||||
|
||||
NumberField parentField;
|
||||
|
||||
public NumberDocument(NumberField parentField) {
|
||||
this.parentField = parentField;
|
||||
//System.out.println("setting parent to " + parentSelector);
|
||||
}
|
||||
|
||||
public void insertString(int offs, String str, AttributeSet a)
|
||||
throws BadLocationException {
|
||||
|
||||
if (str == null) return;
|
||||
|
||||
char chars[] = str.toCharArray();
|
||||
int charCount = 0;
|
||||
// remove any non-digit chars
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
boolean ok = Character.isDigit(chars[i]);
|
||||
if (parentField.allowHex) {
|
||||
if ((chars[i] >= 'A') && (chars[i] <= 'F')) ok = true;
|
||||
if ((chars[i] >= 'a') && (chars[i] <= 'f')) ok = true;
|
||||
}
|
||||
if (ok) {
|
||||
if (charCount != i) { // shift if necessary
|
||||
chars[charCount] = chars[i];
|
||||
}
|
||||
charCount++;
|
||||
}
|
||||
}
|
||||
super.insertString(offs, new String(chars, 0, charCount), a);
|
||||
// can't call any sort of methods on the enclosing class here
|
||||
// seems to have something to do with how Document objects are set up
|
||||
}
|
||||
}
|
||||
}
|
345
app/src/processing/app/tools/CreateFont.java
Normal file
345
app/src/processing/app/tools/CreateFont.java
Normal file
@ -0,0 +1,345 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
|
||||
/**
|
||||
* gui interface to font creation heaven/hell.
|
||||
*/
|
||||
public class CreateFont extends JFrame implements Tool {
|
||||
Editor editor;
|
||||
//Sketch sketch;
|
||||
|
||||
Dimension windowSize;
|
||||
|
||||
JList fontSelector;
|
||||
//JComboBox styleSelector;
|
||||
JTextField sizeSelector;
|
||||
JCheckBox allBox;
|
||||
JCheckBox smoothBox;
|
||||
JTextArea sample;
|
||||
JButton okButton;
|
||||
JTextField filenameField;
|
||||
|
||||
Hashtable table;
|
||||
boolean smooth = true;
|
||||
boolean all = false;
|
||||
|
||||
Font font;
|
||||
|
||||
String[] list;
|
||||
int selection = -1;
|
||||
|
||||
|
||||
//static {
|
||||
//System.out.println("yep yep yep");
|
||||
//}
|
||||
//static final String styles[] = {
|
||||
//"Plain", "Bold", "Italic", "Bold Italic"
|
||||
//};
|
||||
|
||||
|
||||
public CreateFont() {
|
||||
super("Create Font");
|
||||
}
|
||||
|
||||
|
||||
public String getMenuTitle() {
|
||||
return "Create Font...";
|
||||
}
|
||||
|
||||
|
||||
public void init(Editor editor) {
|
||||
this.editor = editor;
|
||||
|
||||
Container paine = getContentPane();
|
||||
paine.setLayout(new BorderLayout()); //10, 10));
|
||||
|
||||
JPanel pain = new JPanel();
|
||||
pain.setBorder(new EmptyBorder(13, 13, 13, 13));
|
||||
paine.add(pain, BorderLayout.CENTER);
|
||||
|
||||
pain.setLayout(new BoxLayout(pain, BoxLayout.Y_AXIS));
|
||||
|
||||
String labelText =
|
||||
"Use this tool to create bitmap fonts for your program.\n" +
|
||||
"Select a font and size, and click 'OK' to generate the font.\n" +
|
||||
"It will be added to the data folder of the current sketch.";
|
||||
|
||||
JTextArea textarea = new JTextArea(labelText);
|
||||
textarea.setBorder(new EmptyBorder(10, 10, 20, 10));
|
||||
textarea.setBackground(null);
|
||||
textarea.setEditable(false);
|
||||
textarea.setHighlighter(null);
|
||||
textarea.setFont(new Font("Dialog", Font.PLAIN, 12));
|
||||
pain.add(textarea);
|
||||
|
||||
// don't care about families starting with . or #
|
||||
// also ignore dialog, dialoginput, monospaced, serif, sansserif
|
||||
|
||||
// getFontList is deprecated in 1.4, so this has to be used
|
||||
GraphicsEnvironment ge =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
|
||||
Font fonts[] = ge.getAllFonts();
|
||||
|
||||
String flist[] = new String[fonts.length];
|
||||
table = new Hashtable();
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < fonts.length; i++) {
|
||||
//String psname = fonts[i].getPSName();
|
||||
//if (psname == null) System.err.println("ps name is null");
|
||||
|
||||
flist[index++] = fonts[i].getPSName();
|
||||
table.put(fonts[i].getPSName(), fonts[i]);
|
||||
}
|
||||
|
||||
list = new String[index];
|
||||
System.arraycopy(flist, 0, list, 0, index);
|
||||
|
||||
fontSelector = new JList(list);
|
||||
fontSelector.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting() == false) {
|
||||
selection = fontSelector.getSelectedIndex();
|
||||
okButton.setEnabled(true);
|
||||
update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
fontSelector.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
fontSelector.setVisibleRowCount(12);
|
||||
JScrollPane fontScroller = new JScrollPane(fontSelector);
|
||||
pain.add(fontScroller);
|
||||
|
||||
Dimension d1 = new Dimension(13, 13);
|
||||
pain.add(new Box.Filler(d1, d1, d1));
|
||||
|
||||
// see http://rinkworks.com/words/pangrams.shtml
|
||||
sample = new JTextArea("The quick brown fox blah blah.") {
|
||||
// Forsaking monastic tradition, twelve jovial friars gave up their
|
||||
// vocation for a questionable existence on the flying trapeze.
|
||||
public void paintComponent(Graphics g) {
|
||||
//System.out.println("disabling aa");
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
smooth ?
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_ON :
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
||||
super.paintComponent(g2);
|
||||
}
|
||||
};
|
||||
// Seems that in some instances, no default font is set
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=777
|
||||
sample.setFont(new Font("Dialog", Font.PLAIN, 12));
|
||||
|
||||
pain.add(sample);
|
||||
|
||||
Dimension d2 = new Dimension(6, 6);
|
||||
pain.add(new Box.Filler(d2, d2, d2));
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.add(new JLabel("Size:"));
|
||||
sizeSelector = new JTextField(" 48 ");
|
||||
sizeSelector.getDocument().addDocumentListener(new DocumentListener() {
|
||||
public void insertUpdate(DocumentEvent e) { update(); }
|
||||
public void removeUpdate(DocumentEvent e) { update(); }
|
||||
public void changedUpdate(DocumentEvent e) { }
|
||||
});
|
||||
panel.add(sizeSelector);
|
||||
|
||||
smoothBox = new JCheckBox("Smooth");
|
||||
smoothBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
smooth = smoothBox.isSelected();
|
||||
update();
|
||||
}
|
||||
});
|
||||
smoothBox.setSelected(smooth);
|
||||
panel.add(smoothBox);
|
||||
|
||||
allBox = new JCheckBox("All Characters");
|
||||
allBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
all = allBox.isSelected();
|
||||
}
|
||||
});
|
||||
allBox.setSelected(all);
|
||||
panel.add(allBox);
|
||||
|
||||
pain.add(panel);
|
||||
|
||||
JPanel filestuff = new JPanel();
|
||||
filestuff.add(new JLabel("Filename:"));
|
||||
filestuff.add(filenameField = new JTextField(20));
|
||||
filestuff.add(new JLabel(".vlw"));
|
||||
pain.add(filestuff);
|
||||
|
||||
JPanel buttons = new JPanel();
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
okButton = new JButton("OK");
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
build();
|
||||
}
|
||||
});
|
||||
okButton.setEnabled(false);
|
||||
|
||||
buttons.add(cancelButton);
|
||||
buttons.add(okButton);
|
||||
pain.add(buttons);
|
||||
|
||||
JRootPane root = getRootPane();
|
||||
root.setDefaultButton(okButton);
|
||||
ActionListener disposer = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
setVisible(false);
|
||||
}
|
||||
};
|
||||
Base.registerWindowCloseKeys(root, disposer);
|
||||
Base.setIcon(this);
|
||||
|
||||
pack();
|
||||
|
||||
// do this after pack so it doesn't affect layout
|
||||
sample.setFont(new Font(list[0], Font.PLAIN, 48));
|
||||
|
||||
fontSelector.setSelectedIndex(0);
|
||||
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
windowSize = getSize();
|
||||
|
||||
setLocation((screen.width - windowSize.width) / 2,
|
||||
(screen.height - windowSize.height) / 2);
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* make the window vertically resizable
|
||||
*/
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(windowSize.width, 2000);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public void show(File targetFolder) {
|
||||
this.targetFolder = targetFolder;
|
||||
show();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void update() {
|
||||
int fontsize = 0;
|
||||
try {
|
||||
fontsize = Integer.parseInt(sizeSelector.getText().trim());
|
||||
//System.out.println("'" + sizeSelector.getText() + "'");
|
||||
} catch (NumberFormatException e2) { }
|
||||
|
||||
// if a deselect occurred, selection will be -1
|
||||
if ((fontsize > 0) && (fontsize < 256) && (selection != -1)) {
|
||||
//font = new Font(list[selection], Font.PLAIN, fontsize);
|
||||
Font instance = (Font) table.get(list[selection]);
|
||||
font = instance.deriveFont(Font.PLAIN, fontsize);
|
||||
//System.out.println("setting font to " + font);
|
||||
sample.setFont(font);
|
||||
|
||||
String filenameSuggestion = list[selection].replace(' ', '_');
|
||||
filenameSuggestion += "-" + fontsize;
|
||||
filenameField.setText(filenameSuggestion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void build() {
|
||||
int fontsize = 0;
|
||||
try {
|
||||
fontsize = Integer.parseInt(sizeSelector.getText().trim());
|
||||
} catch (NumberFormatException e) { }
|
||||
|
||||
if (fontsize <= 0) {
|
||||
JOptionPane.showMessageDialog(this, "Bad font size, try again.",
|
||||
"Badness", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
String filename = filenameField.getText();
|
||||
if (filename.length() == 0) {
|
||||
JOptionPane.showMessageDialog(this, "Enter a file name for the font.",
|
||||
"Lameness", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
if (!filename.endsWith(".vlw")) {
|
||||
filename += ".vlw";
|
||||
}
|
||||
|
||||
try {
|
||||
Font instance = (Font) table.get(list[selection]);
|
||||
font = instance.deriveFont(Font.PLAIN, fontsize);
|
||||
PFont f = new PFont(font, smooth, all ? null : PFont.DEFAULT_CHARSET);
|
||||
|
||||
// make sure the 'data' folder exists
|
||||
File folder = editor.getSketch().prepareDataFolder();
|
||||
f.save(new FileOutputStream(new File(folder, filename)));
|
||||
|
||||
} catch (IOException e) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"An error occurred while creating font.",
|
||||
"No font for you",
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
225
app/src/processing/app/tools/DiscourseFormat.java
Normal file
225
app/src/processing/app/tools/DiscourseFormat.java
Normal file
@ -0,0 +1,225 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2005-06 Ignacio Manuel Gonzalez Moreta.
|
||||
Copyright (c) 2006-08 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.*;
|
||||
import javax.swing.text.Segment;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.app.syntax.*;
|
||||
import processing.core.PApplet;
|
||||
|
||||
/**
|
||||
* Format for Discourse Tool
|
||||
* <p/>
|
||||
* Original code by <A HREF="http://usuarios.iponet.es/imoreta">owd</A>.
|
||||
* Revised and updated for revision 0108 by Ben Fry (10 March 2006).
|
||||
* This code may later be moved to its own 'Tool' plugin, but is included
|
||||
* with release 0108+ while features for the "Tools" menu are in testing.
|
||||
* <p/>
|
||||
* Updated for 0122 to simply copy the code directly to the clipboard,
|
||||
* rather than opening a new window.
|
||||
* <p/>
|
||||
* Updated for 0144 to only format the selected lines.
|
||||
* <p/>
|
||||
* Notes from the original source:
|
||||
* Discourse.java This is a dirty-mix source.
|
||||
* NOTE that: No macs and no keyboard. Unreliable source.
|
||||
* Only format processing code using fontMetrics.
|
||||
* It works under my windows XP + PentiumIV + Processing 0091.
|
||||
*/
|
||||
public class DiscourseFormat {
|
||||
|
||||
Editor editor;
|
||||
// JTextArea of the actual Editor
|
||||
JEditTextArea textarea;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new window with the formated (YaBB tags) sketchcode
|
||||
* from the actual Processing Tab ready to send to the processing discourse
|
||||
* web (copy & paste)
|
||||
*/
|
||||
public DiscourseFormat(Editor editor) {
|
||||
this.editor = editor;
|
||||
this.textarea = editor.getTextArea();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format and render sketch code.
|
||||
*/
|
||||
public void show() {
|
||||
// [code] tag cancels other tags, using [quote]
|
||||
StringBuffer cf = new StringBuffer("[quote]\n");
|
||||
|
||||
int selStart = textarea.getSelectionStart();
|
||||
int selStop = textarea.getSelectionStop();
|
||||
|
||||
int startLine = textarea.getSelectionStartLine();
|
||||
int stopLine = textarea.getSelectionStopLine();
|
||||
|
||||
// If no selection, convert all the lines
|
||||
if (selStart == selStop) {
|
||||
startLine = 0;
|
||||
stopLine = textarea.getLineCount() - 1;
|
||||
} else {
|
||||
// Make sure the selection doesn't end at the beginning of the last line
|
||||
if (textarea.getLineStartOffset(stopLine) == selStop) {
|
||||
stopLine--;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the code line by line
|
||||
for (int i = startLine; i <= stopLine; i++) {
|
||||
appendFormattedLine(cf, i);
|
||||
}
|
||||
|
||||
cf.append("\n[/quote]");
|
||||
|
||||
StringSelection formatted = new StringSelection(cf.toString());
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
clipboard.setContents(formatted, new ClipboardOwner() {
|
||||
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||
// i don't care about ownership
|
||||
}
|
||||
});
|
||||
|
||||
editor.statusNotice("Code formatted for processing.org/discourse " +
|
||||
"has been copied to the clipboard.");
|
||||
}
|
||||
|
||||
|
||||
// A terrible headache...
|
||||
public void appendFormattedLine(StringBuffer cf, int line) {
|
||||
Segment segment = new Segment();
|
||||
|
||||
TextAreaPainter painter = textarea.getPainter();
|
||||
TokenMarker tokenMarker = textarea.getTokenMarker();
|
||||
|
||||
// Use painter's cached info for speed
|
||||
// FontMetrics fm = painter.getFontMetrics();
|
||||
|
||||
// get line text from parent text area
|
||||
textarea.getLineText(line, segment);
|
||||
|
||||
char[] segmentArray = segment.array;
|
||||
int limit = segment.getEndIndex();
|
||||
int segmentOffset = segment.offset;
|
||||
int segmentCount = segment.count;
|
||||
// int width = 0;
|
||||
|
||||
// If syntax coloring is disabled, do simple translation
|
||||
if (tokenMarker == null) {
|
||||
for (int j = 0; j < segmentCount; j++) {
|
||||
char c = segmentArray[j + segmentOffset];
|
||||
cf = cf.append(c);
|
||||
// int charWidth;
|
||||
// if (c == '\t') {
|
||||
// charWidth = (int) painter.nextTabStop(width, j) - width;
|
||||
// } else {
|
||||
// charWidth = fm.charWidth(c);
|
||||
// }
|
||||
// width += charWidth;
|
||||
}
|
||||
|
||||
} else {
|
||||
// If syntax coloring is enabled, we have to do this
|
||||
// because tokens can vary in width
|
||||
Token tokens;
|
||||
if ((painter.getCurrentLineIndex() == line) &&
|
||||
(painter.getCurrentLineTokens() != null)) {
|
||||
tokens = painter.getCurrentLineTokens();
|
||||
|
||||
} else {
|
||||
painter.setCurrentLineIndex(line);
|
||||
painter.setCurrentLineTokens(tokenMarker.markTokens(segment, line));
|
||||
tokens = painter.getCurrentLineTokens();
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
// Font defaultFont = painter.getFont();
|
||||
SyntaxStyle[] styles = painter.getStyles();
|
||||
|
||||
for (;;) {
|
||||
byte id = tokens.id;
|
||||
if (id == Token.END) {
|
||||
char c = segmentArray[segmentOffset + offset];
|
||||
if (segmentOffset + offset < limit) {
|
||||
cf.append(c);
|
||||
} else {
|
||||
cf.append('\n');
|
||||
}
|
||||
return; // cf.toString();
|
||||
}
|
||||
if (id == Token.NULL) {
|
||||
// fm = painter.getFontMetrics();
|
||||
} else {
|
||||
// Place open tags []
|
||||
cf.append("[color=#");
|
||||
cf.append(PApplet.hex(styles[id].getColor().getRGB() & 0xFFFFFF, 6));
|
||||
cf.append("]");
|
||||
|
||||
if (styles[id].isBold())
|
||||
cf.append("[b]");
|
||||
|
||||
// fm = styles[id].getFontMetrics(defaultFont);
|
||||
}
|
||||
int length = tokens.length;
|
||||
|
||||
for (int j = 0; j < length; j++) {
|
||||
char c = segmentArray[segmentOffset + offset + j];
|
||||
if (offset == 0 && c == ' ') {
|
||||
// Works on Safari but not Camino 1.6.3 or Firefox 2.x on OS X.
|
||||
cf.append('\u00A0'); //
|
||||
// if ((j % 2) == 1) {
|
||||
// cf.append("[b]\u00A0[/b]");
|
||||
// } else {
|
||||
// cf.append(' ');
|
||||
// }
|
||||
} else {
|
||||
cf.append(c);
|
||||
}
|
||||
// Place close tags [/]
|
||||
if (j == (length - 1) && id != Token.NULL && styles[id].isBold())
|
||||
cf.append("[/b]");
|
||||
if (j == (length - 1) && id != Token.NULL)
|
||||
cf.append("[/color]");
|
||||
// int charWidth;
|
||||
// if (c == '\t') {
|
||||
// charWidth = (int) painter
|
||||
// .nextTabStop(width, offset + j)
|
||||
// - width;
|
||||
// } else {
|
||||
// charWidth = fm.charWidth(c);
|
||||
// }
|
||||
// width += charWidth;
|
||||
}
|
||||
offset += length;
|
||||
tokens = tokens.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
99
app/src/processing/app/tools/FixEncoding.java
Normal file
99
app/src/processing/app/tools/FixEncoding.java
Normal file
@ -0,0 +1,99 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
|
||||
public class FixEncoding implements Tool {
|
||||
Editor editor;
|
||||
|
||||
|
||||
public String getMenuTitle() {
|
||||
return "Fix Encoding & Reload";
|
||||
}
|
||||
|
||||
|
||||
public void init(Editor editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
Sketch sketch = editor.getSketch();
|
||||
//SketchCode code = sketch.current;
|
||||
|
||||
if (sketch.isModified()) {
|
||||
int result =
|
||||
JOptionPane.showConfirmDialog(editor,
|
||||
"Discard all changes and reload sketch?",
|
||||
"Fix Encoding & Reload",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
if (result == JOptionPane.NO_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
SketchCode code = sketch.getCode(i);
|
||||
code.setProgram(loadWithLocalEncoding(code.getFile()));
|
||||
code.setModified(true); // yes, because we want them to save this
|
||||
}
|
||||
// Update the currently visible program with its code
|
||||
editor.setText(sketch.getCurrentCode().getProgram());
|
||||
|
||||
} catch (IOException e) {
|
||||
String msg =
|
||||
"An error occurred while trying to fix the file encoding.\n" +
|
||||
"Do not attempt to save this sketch as it may overwrite\n" +
|
||||
"the old version. Use Open to re-open the sketch and try again.\n" +
|
||||
e.getMessage();
|
||||
Base.showWarning("Fix Encoding & Reload", msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected String loadWithLocalEncoding(File file) throws IOException {
|
||||
// FileReader uses the default encoding, which is what we want.
|
||||
FileReader fr = new FileReader(file);
|
||||
BufferedReader reader = new BufferedReader(fr);
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
buffer.append(line);
|
||||
buffer.append('\n');
|
||||
}
|
||||
reader.close();
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
44
app/src/processing/app/tools/Tool.java
Normal file
44
app/src/processing/app/tools/Tool.java
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Tool - interface implementation for the Processing tools menu
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.Editor;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for items to be shown in the Tools menu.
|
||||
*/
|
||||
public interface Tool extends Runnable {
|
||||
|
||||
public void init(Editor editor);
|
||||
|
||||
public void run();
|
||||
|
||||
// Not doing shortcuts for now, no way to resolve between tools.
|
||||
// Also would need additional modifiers for shift and alt.
|
||||
//public char getShortcutKey();
|
||||
|
||||
public String getMenuTitle();
|
||||
}
|
||||
|
159
app/src/processing/app/tools/format/src/AutoFormat.java
Normal file
159
app/src/processing/app/tools/format/src/AutoFormat.java
Normal file
@ -0,0 +1,159 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2006 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Tool for auto-formatting code that interfaces to
|
||||
* <A HREF="http://jalopy.sourceforge.net/">Jalopy</A>. This is to replace
|
||||
* the buggy code formatter found in previous releases.
|
||||
*/
|
||||
public class AutoFormat {
|
||||
Editor editor;
|
||||
|
||||
|
||||
public AutoFormat(Editor editor) {
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
|
||||
public void show() {
|
||||
String originalText = editor.textarea.getText();
|
||||
int indentSize = Preferences.getInteger("editor.tabs.size");
|
||||
|
||||
//
|
||||
|
||||
String formattedText = null; //strOut.toString();
|
||||
if (formattedText.equals(originalText)) {
|
||||
editor.message("No changes necessary for Auto Format.");
|
||||
|
||||
} else {
|
||||
// replace with new bootiful text
|
||||
// selectionEnd hopefully at least in the neighborhood
|
||||
editor.setText(formattedText, selectionEnd, selectionEnd);
|
||||
editor.sketch.setModified(true);
|
||||
|
||||
/*
|
||||
// warn user if there are too many parens in either direction
|
||||
if (paren != 0) {
|
||||
editor.error("Warning: Too many " +
|
||||
((paren < 0) ? "right" : "left") +
|
||||
" parentheses.");
|
||||
|
||||
} else if (c_level != 0) { // check braces only if parens are ok
|
||||
editor.error("Warning: Too many " +
|
||||
((c_level < 0) ? "right" : "left") +
|
||||
" curly braces.");
|
||||
} else {
|
||||
editor.message("Auto Format finished.");
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
private static class PluginImpl extends AbstractPlugin {
|
||||
JEditStatusBar statusBar;
|
||||
Project project;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new PluginImpl object.
|
||||
*/
|
||||
public PluginImpl()
|
||||
{
|
||||
super(new JEditAppender());
|
||||
}
|
||||
|
||||
|
||||
public Project getActiveProject()
|
||||
{
|
||||
if (this.project == null)
|
||||
{
|
||||
this.project = new JEditProject();
|
||||
}
|
||||
|
||||
return this.project;
|
||||
}
|
||||
|
||||
|
||||
public FileFormat getFileFormat()
|
||||
{
|
||||
// there is a bug(?) in jEdit's text area whereas inserting text with
|
||||
// DOS file format results in displaying EOF characters, so we always
|
||||
// use UNIX format and let jEdit handle the specified file format upon
|
||||
// file saving
|
||||
return FileFormat.UNIX;
|
||||
}
|
||||
|
||||
|
||||
public Frame getMainWindow()
|
||||
{
|
||||
return jEdit.getActiveView();
|
||||
}
|
||||
|
||||
|
||||
public StatusBar getStatusBar()
|
||||
{
|
||||
return this.statusBar;
|
||||
}
|
||||
|
||||
|
||||
public void afterEnd()
|
||||
{
|
||||
super.afterEnd();
|
||||
MessageView.getInstance().update();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats the currently active buffer.
|
||||
*/
|
||||
public void formatActive()
|
||||
{
|
||||
// only perform the action if the current Buffer contains
|
||||
// a Java source file
|
||||
//if (isJava(jEdit.getActiveView().getBuffer()))
|
||||
//{
|
||||
performAction(Action.FORMAT_ACTIVE);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats the currently open buffers.
|
||||
*/
|
||||
public void formatOpen()
|
||||
{
|
||||
performAction(Action.FORMAT_OPEN);
|
||||
}
|
||||
}
|
||||
}
|
BIN
app/src/processing/app/tools/format/tool/jalopy.jar
Normal file
BIN
app/src/processing/app/tools/format/tool/jalopy.jar
Normal file
Binary file not shown.
BIN
app/src/processing/app/tools/format/tool/log4j.jar
Normal file
BIN
app/src/processing/app/tools/format/tool/log4j.jar
Normal file
Binary file not shown.
335
app/src/processing/app/windows/Advapi32.java
Normal file
335
app/src/processing/app/windows/Advapi32.java
Normal file
@ -0,0 +1,335 @@
|
||||
package processing.app.windows;
|
||||
|
||||
/*
|
||||
* Advapi32.java
|
||||
*
|
||||
* Created on 6. August 2007, 11:24
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
import com.sun.jna.*;
|
||||
import com.sun.jna.ptr.*;
|
||||
import com.sun.jna.win32.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TB
|
||||
*/
|
||||
public interface Advapi32 extends StdCallLibrary {
|
||||
Advapi32 INSTANCE = (Advapi32) Native.loadLibrary("Advapi32", Advapi32.class, Options.UNICODE_OPTIONS);
|
||||
|
||||
/*
|
||||
BOOL WINAPI LookupAccountName(
|
||||
LPCTSTR lpSystemName,
|
||||
LPCTSTR lpAccountName,
|
||||
PSID Sid,
|
||||
LPDWORD cbSid,
|
||||
LPTSTR ReferencedDomainName,
|
||||
LPDWORD cchReferencedDomainName,
|
||||
PSID_NAME_USE peUse
|
||||
);*/
|
||||
public boolean LookupAccountName(String lpSystemName, String lpAccountName,
|
||||
byte[] Sid, IntByReference cbSid, char[] ReferencedDomainName,
|
||||
IntByReference cchReferencedDomainName, PointerByReference peUse);
|
||||
|
||||
/*
|
||||
BOOL WINAPI LookupAccountSid(
|
||||
LPCTSTR lpSystemName,
|
||||
PSID lpSid,
|
||||
LPTSTR lpName,
|
||||
LPDWORD cchName,
|
||||
LPTSTR lpReferencedDomainName,
|
||||
LPDWORD cchReferencedDomainName,
|
||||
PSID_NAME_USE peUse
|
||||
);*/
|
||||
public boolean LookupAccountSid(String lpSystemName, byte[] Sid,
|
||||
char[] lpName, IntByReference cchName, char[] ReferencedDomainName,
|
||||
IntByReference cchReferencedDomainName, PointerByReference peUse);
|
||||
|
||||
/*
|
||||
BOOL ConvertSidToStringSid(
|
||||
PSID Sid,
|
||||
LPTSTR* StringSid
|
||||
);*/
|
||||
public boolean ConvertSidToStringSid(byte[] Sid, PointerByReference StringSid);
|
||||
|
||||
/*
|
||||
BOOL WINAPI ConvertStringSidToSid(
|
||||
LPCTSTR StringSid,
|
||||
PSID* Sid
|
||||
);*/
|
||||
public boolean ConvertStringSidToSid(String StringSid, PointerByReference Sid);
|
||||
|
||||
/*
|
||||
SC_HANDLE WINAPI OpenSCManager(
|
||||
LPCTSTR lpMachineName,
|
||||
LPCTSTR lpDatabaseName,
|
||||
DWORD dwDesiredAccess
|
||||
);*/
|
||||
public Pointer OpenSCManager(String lpMachineName, WString lpDatabaseName, int dwDesiredAccess);
|
||||
|
||||
/*
|
||||
BOOL WINAPI CloseServiceHandle(
|
||||
SC_HANDLE hSCObject
|
||||
);*/
|
||||
public boolean CloseServiceHandle(Pointer hSCObject);
|
||||
|
||||
/*
|
||||
SC_HANDLE WINAPI OpenService(
|
||||
SC_HANDLE hSCManager,
|
||||
LPCTSTR lpServiceName,
|
||||
DWORD dwDesiredAccess
|
||||
);*/
|
||||
public Pointer OpenService(Pointer hSCManager, String lpServiceName, int dwDesiredAccess);
|
||||
|
||||
/*
|
||||
BOOL WINAPI StartService(
|
||||
SC_HANDLE hService,
|
||||
DWORD dwNumServiceArgs,
|
||||
LPCTSTR* lpServiceArgVectors
|
||||
);*/
|
||||
public boolean StartService(Pointer hService, int dwNumServiceArgs, char[] lpServiceArgVectors);
|
||||
|
||||
/*
|
||||
BOOL WINAPI ControlService(
|
||||
SC_HANDLE hService,
|
||||
DWORD dwControl,
|
||||
LPSERVICE_STATUS lpServiceStatus
|
||||
);*/
|
||||
public boolean ControlService(Pointer hService, int dwControl, SERVICE_STATUS lpServiceStatus);
|
||||
|
||||
/*
|
||||
BOOL WINAPI StartServiceCtrlDispatcher(
|
||||
const SERVICE_TABLE_ENTRY* lpServiceTable
|
||||
);*/
|
||||
public boolean StartServiceCtrlDispatcher(Structure[] lpServiceTable);
|
||||
|
||||
/*
|
||||
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandler(
|
||||
LPCTSTR lpServiceName,
|
||||
LPHANDLER_FUNCTION lpHandlerProc
|
||||
);*/
|
||||
public Pointer RegisterServiceCtrlHandler(String lpServiceName, Handler lpHandlerProc);
|
||||
|
||||
/*
|
||||
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerEx(
|
||||
LPCTSTR lpServiceName,
|
||||
LPHANDLER_FUNCTION_EX lpHandlerProc,
|
||||
LPVOID lpContext
|
||||
);*/
|
||||
public Pointer RegisterServiceCtrlHandlerEx(String lpServiceName, HandlerEx lpHandlerProc, Pointer lpContext);
|
||||
|
||||
/*
|
||||
BOOL WINAPI SetServiceStatus(
|
||||
SERVICE_STATUS_HANDLE hServiceStatus,
|
||||
LPSERVICE_STATUS lpServiceStatus
|
||||
);*/
|
||||
public boolean SetServiceStatus(Pointer hServiceStatus, SERVICE_STATUS lpServiceStatus);
|
||||
|
||||
/*
|
||||
SC_HANDLE WINAPI CreateService(
|
||||
SC_HANDLE hSCManager,
|
||||
LPCTSTR lpServiceName,
|
||||
LPCTSTR lpDisplayName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwServiceType,
|
||||
DWORD dwStartType,
|
||||
DWORD dwErrorControl,
|
||||
LPCTSTR lpBinaryPathName,
|
||||
LPCTSTR lpLoadOrderGroup,
|
||||
LPDWORD lpdwTagId,
|
||||
LPCTSTR lpDependencies,
|
||||
LPCTSTR lpServiceStartName,
|
||||
LPCTSTR lpPassword
|
||||
);*/
|
||||
public Pointer CreateService(Pointer hSCManager, String lpServiceName, String lpDisplayName,
|
||||
int dwDesiredAccess, int dwServiceType, int dwStartType, int dwErrorControl,
|
||||
String lpBinaryPathName, String lpLoadOrderGroup, IntByReference lpdwTagId,
|
||||
String lpDependencies, String lpServiceStartName, String lpPassword);
|
||||
|
||||
/*
|
||||
BOOL WINAPI DeleteService(
|
||||
SC_HANDLE hService
|
||||
);*/
|
||||
public boolean DeleteService(Pointer hService);
|
||||
|
||||
/*
|
||||
BOOL WINAPI ChangeServiceConfig2(
|
||||
SC_HANDLE hService,
|
||||
DWORD dwInfoLevel,
|
||||
LPVOID lpInfo
|
||||
);*/
|
||||
public boolean ChangeServiceConfig2(Pointer hService, int dwInfoLevel, ChangeServiceConfig2Info lpInfo);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegOpenKeyEx(
|
||||
HKEY hKey,
|
||||
LPCTSTR lpSubKey,
|
||||
DWORD ulOptions,
|
||||
REGSAM samDesired,
|
||||
PHKEY phkResult
|
||||
);*/
|
||||
public int RegOpenKeyEx(int hKey, String lpSubKey, int ulOptions, int samDesired, IntByReference phkResult);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegQueryValueEx(
|
||||
HKEY hKey,
|
||||
LPCTSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData
|
||||
);*/
|
||||
public int RegQueryValueEx(int hKey, String lpValueName, IntByReference lpReserved, IntByReference lpType, byte[] lpData, IntByReference lpcbData);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegCloseKey(
|
||||
HKEY hKey
|
||||
);*/
|
||||
public int RegCloseKey(int hKey);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegDeleteValue(
|
||||
HKEY hKey,
|
||||
LPCTSTR lpValueName
|
||||
);*/
|
||||
public int RegDeleteValue(int hKey, String lpValueName);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegSetValueEx(
|
||||
HKEY hKey,
|
||||
LPCTSTR lpValueName,
|
||||
DWORD Reserved,
|
||||
DWORD dwType,
|
||||
const BYTE* lpData,
|
||||
DWORD cbData
|
||||
);*/
|
||||
public int RegSetValueEx(int hKey, String lpValueName, int Reserved, int dwType, byte[] lpData, int cbData);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegCreateKeyEx(
|
||||
HKEY hKey,
|
||||
LPCTSTR lpSubKey,
|
||||
DWORD Reserved,
|
||||
LPTSTR lpClass,
|
||||
DWORD dwOptions,
|
||||
REGSAM samDesired,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
PHKEY phkResult,
|
||||
LPDWORD lpdwDisposition
|
||||
);*/
|
||||
public int RegCreateKeyEx(int hKey, String lpSubKey, int Reserved, String lpClass, int dwOptions,
|
||||
int samDesired, WINBASE.SECURITY_ATTRIBUTES lpSecurityAttributes, IntByReference phkResult,
|
||||
IntByReference lpdwDisposition);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegDeleteKey(
|
||||
HKEY hKey,
|
||||
LPCTSTR lpSubKey
|
||||
);*/
|
||||
public int RegDeleteKey(int hKey, String name);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegEnumKeyEx(
|
||||
HKEY hKey,
|
||||
DWORD dwIndex,
|
||||
LPTSTR lpName,
|
||||
LPDWORD lpcName,
|
||||
LPDWORD lpReserved,
|
||||
LPTSTR lpClass,
|
||||
LPDWORD lpcClass,
|
||||
PFILETIME lpftLastWriteTime
|
||||
);*/
|
||||
public int RegEnumKeyEx(int hKey, int dwIndex, char[] lpName, IntByReference lpcName, IntByReference reserved,
|
||||
char[] lpClass, IntByReference lpcClass, WINBASE.FILETIME lpftLastWriteTime);
|
||||
|
||||
/*
|
||||
LONG WINAPI RegEnumValue(
|
||||
HKEY hKey,
|
||||
DWORD dwIndex,
|
||||
LPTSTR lpValueName,
|
||||
LPDWORD lpcchValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData
|
||||
);*/
|
||||
public int RegEnumValue(int hKey, int dwIndex, char[] lpValueName, IntByReference lpcchValueName, IntByReference reserved,
|
||||
IntByReference lpType, byte[] lpData, IntByReference lpcbData);
|
||||
|
||||
interface SERVICE_MAIN_FUNCTION extends StdCallCallback {
|
||||
/*
|
||||
VOID WINAPI ServiceMain(
|
||||
DWORD dwArgc,
|
||||
LPTSTR* lpszArgv
|
||||
);*/
|
||||
public void callback(int dwArgc, Pointer lpszArgv);
|
||||
}
|
||||
|
||||
interface Handler extends StdCallCallback {
|
||||
/*
|
||||
VOID WINAPI Handler(
|
||||
DWORD fdwControl
|
||||
);*/
|
||||
public void callback(int fdwControl);
|
||||
}
|
||||
|
||||
interface HandlerEx extends StdCallCallback {
|
||||
/*
|
||||
DWORD WINAPI HandlerEx(
|
||||
DWORD dwControl,
|
||||
DWORD dwEventType,
|
||||
LPVOID lpEventData,
|
||||
LPVOID lpContext
|
||||
);*/
|
||||
public void callback(int dwControl, int dwEventType, Pointer lpEventData, Pointer lpContext);
|
||||
}
|
||||
|
||||
/*
|
||||
typedef struct _SERVICE_STATUS {
|
||||
DWORD dwServiceType;
|
||||
DWORD dwCurrentState;
|
||||
DWORD dwControlsAccepted;
|
||||
DWORD dwWin32ExitCode;
|
||||
DWORD dwServiceSpecificExitCode;
|
||||
DWORD dwCheckPoint;
|
||||
DWORD dwWaitHint;
|
||||
} SERVICE_STATUS,
|
||||
*LPSERVICE_STATUS;*/
|
||||
public static class SERVICE_STATUS extends Structure {
|
||||
public int dwServiceType;
|
||||
public int dwCurrentState;
|
||||
public int dwControlsAccepted;
|
||||
public int dwWin32ExitCode;
|
||||
public int dwServiceSpecificExitCode;
|
||||
public int dwCheckPoint;
|
||||
public int dwWaitHint;
|
||||
}
|
||||
|
||||
/*
|
||||
typedef struct _SERVICE_TABLE_ENTRY {
|
||||
LPTSTR lpServiceName;
|
||||
LPSERVICE_MAIN_FUNCTION lpServiceProc;
|
||||
} SERVICE_TABLE_ENTRY,
|
||||
*LPSERVICE_TABLE_ENTRY;*/
|
||||
public static class SERVICE_TABLE_ENTRY extends Structure {
|
||||
public String lpServiceName;
|
||||
public SERVICE_MAIN_FUNCTION lpServiceProc;
|
||||
}
|
||||
|
||||
public static class ChangeServiceConfig2Info extends Structure {
|
||||
}
|
||||
|
||||
/*
|
||||
typedef struct _SERVICE_DESCRIPTION {
|
||||
LPTSTR lpDescription;
|
||||
} SERVICE_DESCRIPTION,
|
||||
*LPSERVICE_DESCRIPTION;*/
|
||||
public static class SERVICE_DESCRIPTION extends ChangeServiceConfig2Info {
|
||||
public String lpDescription;
|
||||
}
|
||||
}
|
||||
|
||||
|
27
app/src/processing/app/windows/Options.java
Normal file
27
app/src/processing/app/windows/Options.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Options.java
|
||||
*
|
||||
* Created on 8. August 2007, 17:07
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
import static com.sun.jna.Library.*;
|
||||
import com.sun.jna.win32.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TB
|
||||
*/
|
||||
public interface Options {
|
||||
Map<String, Object> UNICODE_OPTIONS = new HashMap<String, Object>() {
|
||||
{
|
||||
put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
|
||||
put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
|
||||
}
|
||||
};
|
||||
}
|
268
app/src/processing/app/windows/Platform.java
Normal file
268
app/src/processing/app/windows/Platform.java
Normal file
@ -0,0 +1,268 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Preferences;
|
||||
import processing.app.windows.Registry.REGISTRY_ROOT_KEY;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
// http://developer.apple.com/documentation/QuickTime/Conceptual/QT7Win_Update_Guide/Chapter03/chapter_3_section_1.html
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Apple Computer, Inc.\QuickTime\QTSysDir
|
||||
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\CurrentVersion -> 1.6 (String)
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\CurrentVersion\1.6\JavaHome -> c:\jdk-1.6.0_05
|
||||
|
||||
public class Platform extends processing.app.Platform {
|
||||
|
||||
static final String openCommand =
|
||||
System.getProperty("user.dir").replace('/', '\\') +
|
||||
"\\processing.exe \"%1\"";
|
||||
static final String DOC = "Processing.Document";
|
||||
|
||||
public void init(Base base) {
|
||||
super.init(base);
|
||||
|
||||
checkAssociations();
|
||||
checkQuickTime();
|
||||
checkPath();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure that .pde files are associated with processing.exe.
|
||||
*/
|
||||
protected void checkAssociations() {
|
||||
try {
|
||||
String knownCommand =
|
||||
Registry.getStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
DOC + "\\shell\\open\\command", "");
|
||||
if (knownCommand == null) {
|
||||
if (Preferences.getBoolean("platform.auto_file_type_associations")) {
|
||||
setAssociations();
|
||||
}
|
||||
|
||||
} else if (!knownCommand.equals(openCommand)) {
|
||||
// If the value is set differently, just change the registry setting.
|
||||
if (Preferences.getBoolean("platform.auto_file_type_associations")) {
|
||||
setAssociations();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associate .pde files with this version of Processing.
|
||||
*/
|
||||
protected void setAssociations() throws UnsupportedEncodingException {
|
||||
if (Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
"", ".pde") &&
|
||||
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
".pde", "", DOC) &&
|
||||
|
||||
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT, "", DOC) &&
|
||||
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT, DOC, "",
|
||||
"Processing Source Code") &&
|
||||
|
||||
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
DOC, "shell") &&
|
||||
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
DOC + "\\shell", "open") &&
|
||||
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
DOC + "\\shell\\open", "command") &&
|
||||
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||
DOC + "\\shell\\open\\command", "",
|
||||
openCommand)) {
|
||||
// everything ok
|
||||
// hooray!
|
||||
|
||||
} else {
|
||||
Preferences.setBoolean("platform.auto_file_type_associations", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find QuickTime for Java installation.
|
||||
*/
|
||||
protected void checkQuickTime() {
|
||||
try {
|
||||
String qtsystemPath =
|
||||
Registry.getStringValue(REGISTRY_ROOT_KEY.LOCAL_MACHINE,
|
||||
"Software\\Apple Computer, Inc.\\QuickTime",
|
||||
"QTSysDir");
|
||||
// Could show a warning message here if QT not installed, but that
|
||||
// would annoy people who don't want anything to do with QuickTime.
|
||||
if (qtsystemPath != null) {
|
||||
File qtjavaZip = new File(qtsystemPath, "QTJava.zip");
|
||||
if (qtjavaZip.exists()) {
|
||||
String qtjavaZipPath = qtjavaZip.getAbsolutePath();
|
||||
String cp = System.getProperty("java.class.path");
|
||||
System.setProperty("java.class.path",
|
||||
cp + File.pathSeparator + qtjavaZipPath);
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove extra quotes, slashes, and garbage from the Windows PATH.
|
||||
*/
|
||||
protected void checkPath() {
|
||||
String path = System.getProperty("java.library.path");
|
||||
String[] pieces = PApplet.split(path, File.pathSeparatorChar);
|
||||
String[] legit = new String[pieces.length];
|
||||
int legitCount = 0;
|
||||
for (String item : pieces) {
|
||||
if (item.startsWith("\"")) {
|
||||
item = item.substring(1);
|
||||
}
|
||||
if (item.endsWith("\"")) {
|
||||
item = item.substring(0, item.length() - 1);
|
||||
}
|
||||
if (item.endsWith(File.separator)) {
|
||||
item = item.substring(0, item.length() - File.separator.length());
|
||||
}
|
||||
File directory = new File(item);
|
||||
if (!directory.exists()) {
|
||||
continue;
|
||||
}
|
||||
if (item.trim().length() == 0) {
|
||||
continue;
|
||||
}
|
||||
legit[legitCount++] = item;
|
||||
}
|
||||
legit = PApplet.subset(legit, 0, legitCount);
|
||||
String newPath = PApplet.join(legit, File.pathSeparator);
|
||||
if (!newPath.equals(path)) {
|
||||
System.setProperty("java.library.path", newPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// looking for Documents and Settings/blah/Application Data/Processing
|
||||
public File getSettingsFolder() throws Exception {
|
||||
// HKEY_CURRENT_USER\Software\Microsoft
|
||||
// \Windows\CurrentVersion\Explorer\Shell Folders
|
||||
// Value Name: AppData
|
||||
// Value Type: REG_SZ
|
||||
// Value Data: path
|
||||
|
||||
String keyPath =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion" +
|
||||
"\\Explorer\\Shell Folders";
|
||||
String appDataPath =
|
||||
Registry.getStringValue(REGISTRY_ROOT_KEY.CURRENT_USER, keyPath, "AppData");
|
||||
|
||||
File dataFolder = new File(appDataPath, "Processing");
|
||||
return dataFolder;
|
||||
}
|
||||
|
||||
|
||||
// looking for Documents and Settings/blah/My Documents/Processing
|
||||
// (though using a reg key since it's different on other platforms)
|
||||
public File getDefaultSketchbookFolder() throws Exception {
|
||||
|
||||
// http://support.microsoft.com/?kbid=221837&sd=RMVP
|
||||
// http://support.microsoft.com/kb/242557/en-us
|
||||
|
||||
// The path to the My Documents folder is stored in the following
|
||||
// registry key, where path is the complete path to your storage location
|
||||
|
||||
// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
|
||||
// Value Name: Personal
|
||||
// Value Type: REG_SZ
|
||||
// Value Data: path
|
||||
|
||||
// in some instances, this may be overridden by a policy, in which case check:
|
||||
// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
|
||||
|
||||
String keyPath =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion" +
|
||||
"\\Explorer\\Shell Folders";
|
||||
String personalPath =
|
||||
Registry.getStringValue(REGISTRY_ROOT_KEY.CURRENT_USER, keyPath, "Personal");
|
||||
|
||||
return new File(personalPath, "Processing");
|
||||
}
|
||||
|
||||
|
||||
public void openURL(String url) throws Exception {
|
||||
// this is not guaranteed to work, because who knows if the
|
||||
// path will always be c:\progra~1 et al. also if the user has
|
||||
// a different browser set as their default (which would
|
||||
// include me) it'd be annoying to be dropped into ie.
|
||||
//Runtime.getRuntime().exec("c:\\progra~1\\intern~1\\iexplore "
|
||||
// + currentDir
|
||||
|
||||
// the following uses a shell execute to launch the .html file
|
||||
// note that under cygwin, the .html files have to be chmodded +x
|
||||
// after they're unpacked from the zip file. i don't know why,
|
||||
// and don't understand what this does in terms of windows
|
||||
// permissions. without the chmod, the command prompt says
|
||||
// "Access is denied" in both cygwin and the "dos" prompt.
|
||||
//Runtime.getRuntime().exec("cmd /c " + currentDir + "\\reference\\" +
|
||||
// referenceFile + ".html");
|
||||
if (url.startsWith("http://")) {
|
||||
// open dos prompt, give it 'start' command, which will
|
||||
// open the url properly. start by itself won't work since
|
||||
// it appears to need cmd
|
||||
Runtime.getRuntime().exec("cmd /c start " + url);
|
||||
} else {
|
||||
// just launching the .html file via the shell works
|
||||
// but make sure to chmod +x the .html files first
|
||||
// also place quotes around it in case there's a space
|
||||
// in the user.dir part of the url
|
||||
Runtime.getRuntime().exec("cmd /c \"" + url + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean openFolderAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void openFolder(File file) throws Exception {
|
||||
String folder = file.getAbsolutePath();
|
||||
|
||||
// doesn't work
|
||||
//Runtime.getRuntime().exec("cmd /c \"" + folder + "\"");
|
||||
|
||||
// works fine on winxp, prolly win2k as well
|
||||
Runtime.getRuntime().exec("explorer \"" + folder + "\"");
|
||||
|
||||
// not tested
|
||||
//Runtime.getRuntime().exec("start explorer \"" + folder + "\"");
|
||||
}
|
||||
}
|
456
app/src/processing/app/windows/Registry.java
Normal file
456
app/src/processing/app/windows/Registry.java
Normal file
@ -0,0 +1,456 @@
|
||||
package processing.app.windows;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
|
||||
/**
|
||||
* Methods for accessing the Windows Registry. Only String and DWORD values supported at the moment.
|
||||
*/
|
||||
public class Registry {
|
||||
public static enum REGISTRY_ROOT_KEY{CLASSES_ROOT, CURRENT_USER, LOCAL_MACHINE, USERS};
|
||||
private final static HashMap<REGISTRY_ROOT_KEY, Integer> rootKeyMap = new HashMap<REGISTRY_ROOT_KEY, Integer>();
|
||||
|
||||
static {
|
||||
rootKeyMap.put(REGISTRY_ROOT_KEY.CLASSES_ROOT, WINREG.HKEY_CLASSES_ROOT);
|
||||
rootKeyMap.put(REGISTRY_ROOT_KEY.CURRENT_USER, WINREG.HKEY_CURRENT_USER);
|
||||
rootKeyMap.put(REGISTRY_ROOT_KEY.LOCAL_MACHINE, WINREG.HKEY_LOCAL_MACHINE);
|
||||
rootKeyMap.put(REGISTRY_ROOT_KEY.USERS, WINREG.HKEY_USERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing.
|
||||
*
|
||||
* @param args arguments
|
||||
* @throws java.lang.Exception on error
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets one of the root keys.
|
||||
*
|
||||
* @param key key type
|
||||
* @return root key
|
||||
*/
|
||||
private static int getRegistryRootKey(REGISTRY_ROOT_KEY key) {
|
||||
Advapi32 advapi32;
|
||||
IntByReference pHandle;
|
||||
int handle = 0;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
pHandle = new IntByReference();
|
||||
|
||||
if(advapi32.RegOpenKeyEx(rootKeyMap.get(key), null, 0, 0, pHandle) == WINERROR.ERROR_SUCCESS) {
|
||||
handle = pHandle.getValue();
|
||||
}
|
||||
return(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a key.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param subKeyName name of the key
|
||||
* @param access access mode
|
||||
* @return handle to the key or 0
|
||||
*/
|
||||
private static int openKey(REGISTRY_ROOT_KEY rootKey, String subKeyName, int access) {
|
||||
Advapi32 advapi32;
|
||||
IntByReference pHandle;
|
||||
int rootKeyHandle;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
rootKeyHandle = getRegistryRootKey(rootKey);
|
||||
pHandle = new IntByReference();
|
||||
|
||||
if(advapi32.RegOpenKeyEx(rootKeyHandle, subKeyName, 0, access, pHandle) == WINERROR.ERROR_SUCCESS) {
|
||||
return(pHandle.getValue());
|
||||
|
||||
} else {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Windows buffer to a Java String.
|
||||
*
|
||||
* @param buf buffer
|
||||
* @throws java.io.UnsupportedEncodingException on error
|
||||
* @return String
|
||||
*/
|
||||
private static String convertBufferToString(byte[] buf) throws UnsupportedEncodingException {
|
||||
return(new String(buf, 0, buf.length - 2, "UTF-16LE"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Windows buffer to an int.
|
||||
*
|
||||
* @param buf buffer
|
||||
* @return int
|
||||
*/
|
||||
private static int convertBufferToInt(byte[] buf) {
|
||||
return(((int)(buf[0] & 0xff)) + (((int)(buf[1] & 0xff)) << 8) + (((int)(buf[2] & 0xff)) << 16) + (((int)(buf[3] & 0xff)) << 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a String value.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param subKeyName key name
|
||||
* @param name value name
|
||||
* @throws java.io.UnsupportedEncodingException on error
|
||||
* @return String or null
|
||||
*/
|
||||
public static String getStringValue(REGISTRY_ROOT_KEY rootKey, String subKeyName, String name) throws UnsupportedEncodingException {
|
||||
Advapi32 advapi32;
|
||||
IntByReference pType, lpcbData;
|
||||
byte[] lpData = new byte[1];
|
||||
int handle = 0;
|
||||
String ret = null;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
pType = new IntByReference();
|
||||
lpcbData = new IntByReference();
|
||||
handle = openKey(rootKey, subKeyName, WINNT.KEY_READ);
|
||||
|
||||
if(handle != 0) {
|
||||
|
||||
if(advapi32.RegQueryValueEx(handle, name, null, pType, lpData, lpcbData) == WINERROR.ERROR_MORE_DATA) {
|
||||
lpData = new byte[lpcbData.getValue()];
|
||||
|
||||
if(advapi32.RegQueryValueEx(handle, name, null, pType, lpData, lpcbData) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = convertBufferToString(lpData);
|
||||
}
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an int value.
|
||||
*
|
||||
*
|
||||
* @return int or 0
|
||||
* @param rootKey root key
|
||||
* @param subKeyName key name
|
||||
* @param name value name
|
||||
*/
|
||||
public static int getIntValue(REGISTRY_ROOT_KEY rootKey, String subKeyName, String name) {
|
||||
Advapi32 advapi32;
|
||||
IntByReference pType, lpcbData;
|
||||
byte[] lpData = new byte[1];
|
||||
int handle = 0;
|
||||
int ret = 0;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
pType = new IntByReference();
|
||||
lpcbData = new IntByReference();
|
||||
handle = openKey(rootKey, subKeyName, WINNT.KEY_READ);
|
||||
|
||||
if(handle != 0) {
|
||||
|
||||
if(advapi32.RegQueryValueEx(handle, name, null, pType, lpData, lpcbData) == WINERROR.ERROR_MORE_DATA) {
|
||||
lpData = new byte[lpcbData.getValue()];
|
||||
|
||||
if(advapi32.RegQueryValueEx(handle, name, null, pType, lpData, lpcbData) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = convertBufferToInt(lpData);
|
||||
}
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a value.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param subKeyName key name
|
||||
* @param name value name
|
||||
* @return true on success
|
||||
*/
|
||||
public static boolean deleteValue(REGISTRY_ROOT_KEY rootKey, String subKeyName, String name) {
|
||||
Advapi32 advapi32;
|
||||
int handle;
|
||||
boolean ret = true;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
|
||||
handle = openKey(rootKey, subKeyName, WINNT.KEY_READ | WINNT.KEY_WRITE);
|
||||
|
||||
if(handle != 0) {
|
||||
if(advapi32.RegDeleteValue(handle, name) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = true;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a String value.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param subKeyName key name
|
||||
* @param name value name
|
||||
* @param value value
|
||||
* @throws java.io.UnsupportedEncodingException on error
|
||||
* @return true on success
|
||||
*/
|
||||
public static boolean setStringValue(REGISTRY_ROOT_KEY rootKey, String subKeyName, String name, String value) throws UnsupportedEncodingException {
|
||||
Advapi32 advapi32;
|
||||
int handle;
|
||||
byte[] data;
|
||||
boolean ret = false;
|
||||
|
||||
// appears to be Java 1.6 syntax, removing [fry]
|
||||
//data = Arrays.copyOf(value.getBytes("UTF-16LE"), value.length() * 2 + 2);
|
||||
data = new byte[value.length() * 2 + 2];
|
||||
byte[] src = value.getBytes("UTF-16LE");
|
||||
System.arraycopy(src, 0, data, 0, src.length);
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
handle = openKey(rootKey, subKeyName, WINNT.KEY_READ | WINNT.KEY_WRITE);
|
||||
|
||||
if(handle != 0) {
|
||||
if(advapi32.RegSetValueEx(handle, name, 0, WINNT.REG_SZ, data, data.length) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = true;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an int value.
|
||||
*
|
||||
*
|
||||
* @return true on success
|
||||
* @param rootKey root key
|
||||
* @param subKeyName key name
|
||||
* @param name value name
|
||||
* @param value value
|
||||
*/
|
||||
public static boolean setIntValue(REGISTRY_ROOT_KEY rootKey, String subKeyName, String name, int value) {
|
||||
Advapi32 advapi32;
|
||||
int handle;
|
||||
byte[] data;
|
||||
boolean ret = false;
|
||||
|
||||
data = new byte[4];
|
||||
data[0] = (byte)(value & 0xff);
|
||||
data[1] = (byte)((value >> 8) & 0xff);
|
||||
data[2] = (byte)((value >> 16) & 0xff);
|
||||
data[3] = (byte)((value >> 24) & 0xff);
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
handle = openKey(rootKey, subKeyName, WINNT.KEY_READ | WINNT.KEY_WRITE);
|
||||
|
||||
if(handle != 0) {
|
||||
|
||||
if(advapi32.RegSetValueEx(handle, name, 0, WINNT.REG_DWORD, data, data.length) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = true;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for existence of a value.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param subKeyName key name
|
||||
* @param name value name
|
||||
* @return true if exists
|
||||
*/
|
||||
public static boolean valueExists(REGISTRY_ROOT_KEY rootKey, String subKeyName, String name) {
|
||||
Advapi32 advapi32;
|
||||
IntByReference pType, lpcbData;
|
||||
byte[] lpData = new byte[1];
|
||||
int handle = 0;
|
||||
boolean ret = false;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
pType = new IntByReference();
|
||||
lpcbData = new IntByReference();
|
||||
handle = openKey(rootKey, subKeyName, WINNT.KEY_READ);
|
||||
|
||||
if(handle != 0) {
|
||||
|
||||
if(advapi32.RegQueryValueEx(handle, name, null, pType, lpData, lpcbData) != WINERROR.ERROR_FILE_NOT_FOUND) {
|
||||
ret = true;
|
||||
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new key.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param parent name of parent key
|
||||
* @param name key name
|
||||
* @return true on success
|
||||
*/
|
||||
public static boolean createKey(REGISTRY_ROOT_KEY rootKey, String parent, String name) {
|
||||
Advapi32 advapi32;
|
||||
IntByReference hkResult, dwDisposition;
|
||||
int handle = 0;
|
||||
boolean ret = false;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
hkResult = new IntByReference();
|
||||
dwDisposition = new IntByReference();
|
||||
handle = openKey(rootKey, parent, WINNT.KEY_READ);
|
||||
|
||||
if(handle != 0) {
|
||||
|
||||
if(advapi32.RegCreateKeyEx(handle, name, 0, null, WINNT.REG_OPTION_NON_VOLATILE, WINNT.KEY_READ, null,
|
||||
hkResult, dwDisposition) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = true;
|
||||
advapi32.RegCloseKey(hkResult.getValue());
|
||||
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a key.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param parent name of parent key
|
||||
* @param name key name
|
||||
* @return true on success
|
||||
*/
|
||||
public static boolean deleteKey(REGISTRY_ROOT_KEY rootKey, String parent, String name) {
|
||||
Advapi32 advapi32;
|
||||
int handle = 0;
|
||||
boolean ret = false;
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
handle = openKey(rootKey, parent, WINNT.KEY_READ);
|
||||
|
||||
if(handle != 0) {
|
||||
|
||||
if(advapi32.RegDeleteKey(handle, name) == WINERROR.ERROR_SUCCESS) {
|
||||
ret = true;
|
||||
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all sub keys of a key.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param parent key name
|
||||
* @return array with all sub key names
|
||||
*/
|
||||
public static String[] getSubKeys(REGISTRY_ROOT_KEY rootKey, String parent) {
|
||||
Advapi32 advapi32;
|
||||
int handle = 0, dwIndex;
|
||||
char[] lpName;
|
||||
IntByReference lpcName;
|
||||
WINBASE.FILETIME lpftLastWriteTime;
|
||||
TreeSet<String> subKeys = new TreeSet<String>();
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
handle = openKey(rootKey, parent, WINNT.KEY_READ);
|
||||
lpName = new char[256];
|
||||
lpcName = new IntByReference(256);
|
||||
lpftLastWriteTime = new WINBASE.FILETIME();
|
||||
|
||||
if(handle != 0) {
|
||||
dwIndex = 0;
|
||||
|
||||
while(advapi32.RegEnumKeyEx(handle, dwIndex, lpName, lpcName, null,
|
||||
null, null, lpftLastWriteTime) == WINERROR.ERROR_SUCCESS) {
|
||||
subKeys.add(new String(lpName, 0, lpcName.getValue()));
|
||||
lpcName.setValue(256);
|
||||
dwIndex++;
|
||||
}
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
|
||||
return(subKeys.toArray(new String[]{}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all values under a key.
|
||||
*
|
||||
* @param rootKey root key
|
||||
* @param key jey name
|
||||
* @throws java.io.UnsupportedEncodingException on error
|
||||
* @return TreeMap with name and value pairs
|
||||
*/
|
||||
public static TreeMap<String, Object> getValues(REGISTRY_ROOT_KEY rootKey, String key) throws UnsupportedEncodingException {
|
||||
Advapi32 advapi32;
|
||||
int handle = 0, dwIndex, result = 0;
|
||||
char[] lpValueName;
|
||||
byte[] lpData;
|
||||
IntByReference lpcchValueName, lpType, lpcbData;
|
||||
String name;
|
||||
TreeMap<String, Object> values = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
advapi32 = Advapi32.INSTANCE;
|
||||
handle = openKey(rootKey, key, WINNT.KEY_READ);
|
||||
lpValueName = new char[16384];
|
||||
lpcchValueName = new IntByReference(16384);
|
||||
lpType = new IntByReference();
|
||||
lpData = new byte[1];
|
||||
lpcbData = new IntByReference();
|
||||
|
||||
if(handle != 0) {
|
||||
dwIndex = 0;
|
||||
|
||||
do {
|
||||
lpcbData.setValue(0);
|
||||
result = advapi32.RegEnumValue(handle, dwIndex, lpValueName, lpcchValueName, null,
|
||||
lpType, lpData, lpcbData);
|
||||
|
||||
if(result == WINERROR.ERROR_MORE_DATA) {
|
||||
lpData = new byte[lpcbData.getValue()];
|
||||
lpcchValueName = new IntByReference(16384);
|
||||
result = advapi32.RegEnumValue(handle, dwIndex, lpValueName, lpcchValueName, null,
|
||||
lpType, lpData, lpcbData);
|
||||
|
||||
if(result == WINERROR.ERROR_SUCCESS) {
|
||||
name = new String(lpValueName, 0, lpcchValueName.getValue());
|
||||
|
||||
switch(lpType.getValue()) {
|
||||
case WINNT.REG_SZ:
|
||||
values.put(name, convertBufferToString(lpData));
|
||||
break;
|
||||
case WINNT.REG_DWORD:
|
||||
values.put(name, convertBufferToInt(lpData));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dwIndex++;
|
||||
} while(result == WINERROR.ERROR_SUCCESS);
|
||||
|
||||
advapi32.RegCloseKey(handle);
|
||||
}
|
||||
return(values);
|
||||
}
|
||||
}
|
43
app/src/processing/app/windows/WINBASE.java
Normal file
43
app/src/processing/app/windows/WINBASE.java
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* WINBASE.java
|
||||
*
|
||||
* Created on 5. September 2007, 11:24
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TB
|
||||
*/
|
||||
public interface WINBASE {
|
||||
/*
|
||||
typedef struct _SECURITY_ATTRIBUTES {
|
||||
DWORD nLength;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
BOOL bInheritHandle;
|
||||
} SECURITY_ATTRIBUTES,
|
||||
*PSECURITY_ATTRIBUTES,
|
||||
*LPSECURITY_ATTRIBUTES;*/
|
||||
public static class SECURITY_ATTRIBUTES extends Structure {
|
||||
public int nLength;
|
||||
public Pointer lpSecurityDescriptor;
|
||||
public boolean bInheritHandle;
|
||||
}
|
||||
|
||||
/*
|
||||
typedef struct _FILETIME {
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME, *PFILETIME, *LPFILETIME;*/
|
||||
public static class FILETIME extends Structure {
|
||||
public int dwLowDateTime;
|
||||
public int dwHighDateTime;
|
||||
}
|
||||
}
|
22
app/src/processing/app/windows/WINERROR.java
Normal file
22
app/src/processing/app/windows/WINERROR.java
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* WINERROR.java
|
||||
*
|
||||
* Created on 7. August 2007, 08:09
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TB
|
||||
*/
|
||||
public interface WINERROR {
|
||||
public final static int ERROR_SUCCESS = 0;
|
||||
public final static int NO_ERROR = 0;
|
||||
public final static int ERROR_FILE_NOT_FOUND = 2;
|
||||
public final static int ERROR_MORE_DATA = 234;
|
||||
}
|
73
app/src/processing/app/windows/WINNT.java
Normal file
73
app/src/processing/app/windows/WINNT.java
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* WINNT.java
|
||||
*
|
||||
* Created on 8. August 2007, 13:41
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TB
|
||||
*/
|
||||
public interface WINNT {
|
||||
public final static int DELETE = 0x00010000;
|
||||
public final static int READ_CONTROL = 0x00020000;
|
||||
public final static int WRITE_DAC = 0x00040000;
|
||||
public final static int WRITE_OWNER = 0x00080000;
|
||||
public final static int SYNCHRONIZE = 0x00100000;
|
||||
|
||||
public final static int STANDARD_RIGHTS_REQUIRED = 0x000F0000;
|
||||
|
||||
public final static int STANDARD_RIGHTS_READ = READ_CONTROL;
|
||||
public final static int STANDARD_RIGHTS_WRITE = READ_CONTROL;
|
||||
public final static int STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
|
||||
|
||||
public final static int STANDARD_RIGHTS_ALL = 0x001F0000;
|
||||
|
||||
public final static int SPECIFIC_RIGHTS_ALL = 0x0000FFFF;
|
||||
|
||||
public final static int GENERIC_EXECUTE = 0x20000000;
|
||||
|
||||
public final static int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
|
||||
|
||||
public final static int KEY_QUERY_VALUE = 0x0001;
|
||||
public final static int KEY_SET_VALUE = 0x0002;
|
||||
public final static int KEY_CREATE_SUB_KEY = 0x0004;
|
||||
public final static int KEY_ENUMERATE_SUB_KEYS = 0x0008;
|
||||
public final static int KEY_NOTIFY = 0x0010;
|
||||
public final static int KEY_CREATE_LINK = 0x0020;
|
||||
|
||||
public final static int KEY_READ = ((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE));
|
||||
public final static int KEY_WRITE = ((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE));
|
||||
|
||||
public final static int REG_NONE = 0; // No value type
|
||||
public final static int REG_SZ = 1; // Unicode nul terminated string
|
||||
public final static int REG_EXPAND_SZ = 2; // Unicode nul terminated string
|
||||
// (with environment variable references)
|
||||
public final static int REG_BINARY = 3; // Free form binary
|
||||
public final static int REG_DWORD = 4; // 32-bit number
|
||||
public final static int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD)
|
||||
public final static int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number
|
||||
public final static int REG_LINK = 6; // Symbolic Link (unicode)
|
||||
public final static int REG_MULTI_SZ = 7; // Multiple Unicode strings
|
||||
public final static int REG_RESOURCE_LIST = 8; // Resource list in the resource map
|
||||
public final static int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description
|
||||
public final static int REG_RESOURCE_REQUIREMENTS_LIST = 10;
|
||||
|
||||
public final static int REG_OPTION_RESERVED = 0x00000000; // Parameter is reserved
|
||||
public final static int REG_OPTION_NON_VOLATILE = 0x00000000; // Key is preserved
|
||||
// when system is rebooted
|
||||
public final static int REG_OPTION_VOLATILE = 0x00000001; // Key is not preserved
|
||||
// when system is rebooted
|
||||
public final static int REG_OPTION_CREATE_LINK = 0x00000002; // Created key is a
|
||||
// symbolic link
|
||||
public final static int REG_OPTION_BACKUP_RESTORE = 0x00000004; // open for backup or restore
|
||||
// special access rules
|
||||
// privilege required
|
||||
public final static int REG_OPTION_OPEN_LINK = 0x00000008; // Open symbolic link
|
||||
|
||||
}
|
21
app/src/processing/app/windows/WINREG.java
Normal file
21
app/src/processing/app/windows/WINREG.java
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* WINREG.java
|
||||
*
|
||||
* Created on 17. August 2007, 14:32
|
||||
*
|
||||
* To change this template, choose Tools | Template Manager
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package processing.app.windows;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author TB
|
||||
*/
|
||||
public interface WINREG {
|
||||
public final static int HKEY_CLASSES_ROOT = 0x80000000;
|
||||
public final static int HKEY_CURRENT_USER = 0x80000001;
|
||||
public final static int HKEY_LOCAL_MACHINE = 0x80000002;
|
||||
public final static int HKEY_USERS = 0x80000003;
|
||||
}
|
70
build/cmd/dist.sh
Executable file
70
build/cmd/dist.sh
Executable file
@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
|
||||
# only needed for core.jar and pde.jar, hmm
|
||||
ARCH=`uname`
|
||||
if [ $ARCH == "Darwin" ]
|
||||
then
|
||||
BUILD=../macosx
|
||||
REVISION=`head -1 ../../todo.txt | cut -c 1-4`
|
||||
elif [ $ARCH == "Cygwin" ]
|
||||
then
|
||||
BUILD=../windows
|
||||
REVISION=`head -c 4 ../../todo.txt`
|
||||
else
|
||||
BUILD=../linux
|
||||
REVISION=`head -c 4 ../../todo.txt`
|
||||
fi
|
||||
|
||||
echo Creating command-line distribution for revision $REVISION...
|
||||
|
||||
# remove any old boogers
|
||||
rm -rf processing
|
||||
rm -rf processing-*
|
||||
|
||||
mkdir processing
|
||||
cp -r ../shared/lib processing/
|
||||
cp -r ../shared/libraries processing/
|
||||
cp ../../app/lib/antlr.jar processing/lib/
|
||||
cp ../../app/lib/ecj.jar processing/lib/
|
||||
cp ../../app/lib/jna.jar processing/lib/
|
||||
cp ../shared/revisions.txt processing/
|
||||
|
||||
# add the libraries folder with source
|
||||
cp -r ../../net processing/libraries/
|
||||
cp -r ../../opengl processing/libraries/
|
||||
cp -r ../../serial processing/libraries/
|
||||
cp -r ../../pdf processing/libraries/
|
||||
cp -r ../../dxf processing/libraries/
|
||||
cp -r ../../xml processing/libraries/
|
||||
cp -r ../../candy processing/libraries/
|
||||
cp -r ../../video processing/libraries/
|
||||
|
||||
# grab pde.jar and export from the working dir
|
||||
cp $BUILD/work/lib/pde.jar processing/lib/
|
||||
cp $BUILD/work/lib/core.jar processing/lib/
|
||||
|
||||
# get platform-specific goodies from the dist dir
|
||||
install -m 755 dist/processing processing/processing
|
||||
|
||||
# remove boogers
|
||||
find processing -name "*~" -exec rm -f {} ';'
|
||||
find processing -name ".DS_Store" -exec rm -f {} ';'
|
||||
find processing -name "._*" -exec rm -f {} ';'
|
||||
find processing -name "Thumbs.db" -exec rm -f {} ';'
|
||||
|
||||
# clean out the cvs entries
|
||||
find processing -name "CVS" -exec rm -rf {} ';' 2> /dev/null
|
||||
find processing -name ".cvsignore" -exec rm -rf {} ';'
|
||||
find processing -name ".svn" -exec rm -rf {} 2> /dev/null ';'
|
||||
|
||||
# zip it all up for release
|
||||
echo Creating tarball and finishing...
|
||||
P5=processing-cmd-$REVISION
|
||||
mv processing $P5
|
||||
|
||||
zip -rq $P5.zip $P5
|
||||
#tar cfz $P5.tgz $P5
|
||||
# nah, keep the new directory around
|
||||
#rm -rf $P5
|
||||
|
||||
#echo Done.
|
20
build/cmd/dist/processing
vendored
Normal file
20
build/cmd/dist/processing
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
APPDIR="$(dirname -- "${0}")"
|
||||
|
||||
# includes java/* in case a Java install is available
|
||||
for LIB in \
|
||||
java/lib/rt.jar \
|
||||
java/lib/tools.jar \
|
||||
lib/*.jar \
|
||||
;
|
||||
do
|
||||
CLASSPATH="${CLASSPATH}:${APPDIR}/${LIB}"
|
||||
done
|
||||
export CLASSPATH
|
||||
|
||||
export PATH="${APPDIR}/java/bin:${PATH}"
|
||||
|
||||
#java processing.app.Commander $*
|
||||
# if you know a better way to do this, submit it to dev.processing.org/bugs
|
||||
java processing.app.Commander "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"
|
167
build/howto.txt
Executable file
167
build/howto.txt
Executable file
@ -0,0 +1,167 @@
|
||||
HOW TO BUILD PROCESSING ON YOUR FAVORITE PLATFORM
|
||||
|
||||
If you have questions about the contents of this document,
|
||||
ask questions at the discourse section of the site:
|
||||
http://processing.org/discourse/yabb_beta/YaBB.cgi?board=os_core_pde
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// Steps for First Time Setup
|
||||
|
||||
|
||||
1. INSTALL DEVELOPMENT TOOLS
|
||||
|
||||
1a. On Windows, install Cygwin. It's downloadable from
|
||||
www.cygwin.com or specifically: www.cygwin.com/setup.exe
|
||||
|
||||
** of the packages, begin with the defaults, and add:
|
||||
|
||||
+ subversion - used for version control
|
||||
|
||||
+ make, gcc-mingw, and g++ - used to build processing.exe
|
||||
(this will also pull in gcc-core)
|
||||
|
||||
+ perl - use this version from cygwin, activestate or other windows
|
||||
perl distributions have trouble
|
||||
|
||||
+ unzip, zip - for dealing with archives
|
||||
|
||||
+ included in the defaults, but make sure: coreutils, gzip, tar
|
||||
|
||||
+ not required but useful:
|
||||
openssh - command line ssh client
|
||||
nano - handy/simple text editor (gnu pico ripoff)
|
||||
|
||||
** and be sure to leave the option selected for 'unix line endings'
|
||||
|
||||
the cygwin installer is sometimes a little flakey, so it may take more
|
||||
than one try to get everything in there. in fact, it's often best to
|
||||
run the installer once, and let it install all its defaults, then run
|
||||
it again, and select the items above. it's also useful to run the
|
||||
installer every few months to keep things fresh.
|
||||
|
||||
|
||||
1b. On Mac OS X, install Apple's Developer Tools (Xcode).
|
||||
|
||||
You'll also need subversion: http://subversion.tigris.org/
|
||||
Install it from Fink, Darwinports, or download as a package:
|
||||
http://metissian.com/projects/macosx/subversion/
|
||||
|
||||
|
||||
1c. On Linux, you're pretty much on your own.. You need a pretty
|
||||
standard development setup along with Subversion.
|
||||
|
||||
|
||||
2. GRAB THE CODE FROM DEV.PROCESSING.ORG
|
||||
|
||||
As of August 12, 2005, we're no longer using CVS and have moved on to
|
||||
the brave new world of Subversion. This is scary but hopefully will
|
||||
alleviate some of the CVS annoyances.
|
||||
|
||||
To get the code, type this from a prompt:
|
||||
svn co svn://processing.org/trunk/processing
|
||||
|
||||
That part may take a while, especially for people outside the US or
|
||||
who have a slow internet connection. (The JRE binaries are stored in
|
||||
SVN so that we can properly test on the exact platform/runtime setup
|
||||
that we'll be releasing.)
|
||||
|
||||
|
||||
3. INSTALL QUICKTIME FOR JAVA (Windows users only)
|
||||
|
||||
* You'll also need to install QuickTime for Java. Grab the QuickTime
|
||||
(and iTunes) installer from: http://www.apple.com/quicktime/download/
|
||||
or a version that doesn't include iTunes from here:
|
||||
http://www.apple.com/quicktime/download/standalone.html
|
||||
As of QuickTime 7 (iTunes 6), QuickTime for Java is mercifully
|
||||
included by default.
|
||||
|
||||
* QuickTime 6 is no longer supported. QuickTime Alternative has
|
||||
never been supported. Just use QuickTime 7.
|
||||
|
||||
|
||||
4. BUILD IT
|
||||
|
||||
# now to build for the first time:
|
||||
cd /path/to/processing/build/windows
|
||||
|
||||
# or if you're on linux
|
||||
cd /path/to/processing/build/linux
|
||||
|
||||
# let's say you're into black turtlenecks and jeans
|
||||
cd /path/to/processing/build/macosx
|
||||
|
||||
# and then..
|
||||
./make.sh
|
||||
|
||||
# if everything went well, you'll have no errors. (feel free to make
|
||||
# suggestions for things to include here for common problems)
|
||||
|
||||
# then to run it
|
||||
./run.sh
|
||||
|
||||
# each time you make a change, use make to build the thing
|
||||
# and run to get it up and running.
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// Updating to the Latest Version
|
||||
|
||||
|
||||
5a. Each time you want to update to latest version:
|
||||
|
||||
cd /path/to/processing
|
||||
svn update
|
||||
|
||||
|
||||
5b. If you're getting strange errors when you try to build, especially
|
||||
if new folders have been added to the Processing repository, remove
|
||||
your 'work' folder and rebuild. Generally, this is a good idea to
|
||||
do whenever a new release has been made, since that will involve
|
||||
files that may have been changed (or folders that have been moved).
|
||||
|
||||
# get to the processing folder
|
||||
cd /path/to/processing
|
||||
|
||||
# remove the work directory
|
||||
cd build/yourplatform
|
||||
rm -rf work
|
||||
|
||||
# and try again
|
||||
./make.sh
|
||||
|
||||
Unfortunately there isn't a way to know if new folders have
|
||||
since been added. but if you're getting "class not found" errors
|
||||
while building, then that's a good indicator that something is
|
||||
missing from a subfolder.
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// The Frequently Asked Question
|
||||
|
||||
- What about Eclipse? What about Ant? Command line sucks.
|
||||
|
||||
The command line stuff isn't as scary as it might initially
|
||||
seem. Hopefully it's just a matter of following the instructions above
|
||||
(and being patient). If not, let us know (via the discourse board)
|
||||
where you have trouble so we can fix things.
|
||||
|
||||
We're slowly moving development over to Eclipse, which will probably
|
||||
include Ant because of cross-platform dependencies. As of release 0140,
|
||||
major changes are being implemented to simplify the build process,
|
||||
which should mean that we're pretty close. The environment and all
|
||||
the libraries build properly with Eclipse, however we won't be
|
||||
documenting it until the dust has settled.
|
||||
|
||||
Some progress has been made by John Houck to get the scripts working
|
||||
under ANT, progress can be tracked here:
|
||||
http://dev.processing.org/bugs/show_bug.cgi?id=151
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Ben Fry - Updated 10 June 2008
|
87
build/javadoc/core/allclasses-frame.html
Normal file
87
build/javadoc/core/allclasses-frame.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!--NewPage-->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>
|
||||
All Classes
|
||||
</TITLE>
|
||||
|
||||
|
||||
<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
|
||||
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="white">
|
||||
<FONT size="+1" CLASS="FrameHeadingFont">
|
||||
<B>All Classes</B></FONT>
|
||||
<BR>
|
||||
|
||||
<TABLE BORDER="0" WIDTH="100%" SUMMARY="">
|
||||
<TR>
|
||||
<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="processing/core/PApplet.html" title="class in processing.core" target="classFrame">PApplet</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PApplet.RendererChangeException.html" title="class in processing.core" target="classFrame">PApplet.RendererChangeException</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PConstants.html" title="interface in processing.core" target="classFrame"><I>PConstants</I></A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PFont.html" title="class in processing.core" target="classFrame">PFont</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphics.html" title="class in processing.core" target="classFrame">PGraphics</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphics2D.html" title="class in processing.core" target="classFrame">PGraphics2D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphics3D.html" title="class in processing.core" target="classFrame">PGraphics3D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphicsJava2D.html" title="class in processing.core" target="classFrame">PGraphicsJava2D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PImage.html" title="class in processing.core" target="classFrame">PImage</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PLine.html" title="class in processing.core" target="classFrame">PLine</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PMatrix.html" title="interface in processing.core" target="classFrame"><I>PMatrix</I></A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PMatrix2D.html" title="class in processing.core" target="classFrame">PMatrix2D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PMatrix3D.html" title="class in processing.core" target="classFrame">PMatrix3D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PPolygon.html" title="class in processing.core" target="classFrame">PPolygon</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PShape.html" title="class in processing.core" target="classFrame">PShape</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PShapeSVG.html" title="class in processing.core" target="classFrame">PShapeSVG</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PSmoothTriangle.html" title="class in processing.core" target="classFrame">PSmoothTriangle</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PStyle.html" title="class in processing.core" target="classFrame">PStyle</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PTriangle.html" title="class in processing.core" target="classFrame">PTriangle</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PVector.html" title="class in processing.core" target="classFrame">PVector</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/StdXMLBuilder.html" title="class in processing.xml" target="classFrame">StdXMLBuilder</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/StdXMLParser.html" title="class in processing.xml" target="classFrame">StdXMLParser</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/StdXMLReader.html" title="class in processing.xml" target="classFrame">StdXMLReader</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLElement.html" title="class in processing.xml" target="classFrame">XMLElement</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLEntityResolver.html" title="class in processing.xml" target="classFrame">XMLEntityResolver</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLException.html" title="class in processing.xml" target="classFrame">XMLException</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLParseException.html" title="class in processing.xml" target="classFrame">XMLParseException</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLValidationException.html" title="class in processing.xml" target="classFrame">XMLValidationException</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLValidator.html" title="class in processing.xml" target="classFrame">XMLValidator</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLWriter.html" title="class in processing.xml" target="classFrame">XMLWriter</A>
|
||||
<BR>
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
87
build/javadoc/core/allclasses-noframe.html
Normal file
87
build/javadoc/core/allclasses-noframe.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!--NewPage-->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>
|
||||
All Classes
|
||||
</TITLE>
|
||||
|
||||
|
||||
<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
|
||||
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="white">
|
||||
<FONT size="+1" CLASS="FrameHeadingFont">
|
||||
<B>All Classes</B></FONT>
|
||||
<BR>
|
||||
|
||||
<TABLE BORDER="0" WIDTH="100%" SUMMARY="">
|
||||
<TR>
|
||||
<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="processing/core/PApplet.html" title="class in processing.core">PApplet</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PApplet.RendererChangeException.html" title="class in processing.core">PApplet.RendererChangeException</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PConstants.html" title="interface in processing.core"><I>PConstants</I></A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PFont.html" title="class in processing.core">PFont</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphics.html" title="class in processing.core">PGraphics</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphics2D.html" title="class in processing.core">PGraphics2D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphics3D.html" title="class in processing.core">PGraphics3D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PGraphicsJava2D.html" title="class in processing.core">PGraphicsJava2D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PImage.html" title="class in processing.core">PImage</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PLine.html" title="class in processing.core">PLine</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PMatrix.html" title="interface in processing.core"><I>PMatrix</I></A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PMatrix2D.html" title="class in processing.core">PMatrix2D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PMatrix3D.html" title="class in processing.core">PMatrix3D</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PPolygon.html" title="class in processing.core">PPolygon</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PShape.html" title="class in processing.core">PShape</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PShapeSVG.html" title="class in processing.core">PShapeSVG</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PSmoothTriangle.html" title="class in processing.core">PSmoothTriangle</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PStyle.html" title="class in processing.core">PStyle</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PTriangle.html" title="class in processing.core">PTriangle</A>
|
||||
<BR>
|
||||
<A HREF="processing/core/PVector.html" title="class in processing.core">PVector</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/StdXMLBuilder.html" title="class in processing.xml">StdXMLBuilder</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/StdXMLParser.html" title="class in processing.xml">StdXMLParser</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/StdXMLReader.html" title="class in processing.xml">StdXMLReader</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLElement.html" title="class in processing.xml">XMLElement</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLEntityResolver.html" title="class in processing.xml">XMLEntityResolver</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLException.html" title="class in processing.xml">XMLException</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLParseException.html" title="class in processing.xml">XMLParseException</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLValidationException.html" title="class in processing.xml">XMLValidationException</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLValidator.html" title="class in processing.xml">XMLValidator</A>
|
||||
<BR>
|
||||
<A HREF="processing/xml/XMLWriter.html" title="class in processing.xml">XMLWriter</A>
|
||||
<BR>
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
1605
build/javadoc/core/constant-values.html
Normal file
1605
build/javadoc/core/constant-values.html
Normal file
File diff suppressed because it is too large
Load Diff
194
build/javadoc/core/deprecated-list.html
Normal file
194
build/javadoc/core/deprecated-list.html
Normal file
@ -0,0 +1,194 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!--NewPage-->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>
|
||||
Deprecated List
|
||||
</TITLE>
|
||||
|
||||
|
||||
<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
|
||||
|
||||
<SCRIPT type="text/javascript">
|
||||
function windowTitle()
|
||||
{
|
||||
parent.document.title="Deprecated List";
|
||||
}
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
</NOSCRIPT>
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="white" onload="windowTitle();">
|
||||
|
||||
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<A NAME="navbar_top"><!-- --></A>
|
||||
<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
|
||||
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
|
||||
<TR>
|
||||
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
|
||||
<A NAME="navbar_top_firstrow"><!-- --></A>
|
||||
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
|
||||
<TR ALIGN="center" VALIGN="top">
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
|
||||
</EM>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
PREV
|
||||
NEXT</FONT></TD>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
<A HREF="index.html?deprecated-list.html" target="_top"><B>FRAMES</B></A>
|
||||
<A HREF="deprecated-list.html" target="_top"><B>NO FRAMES</B></A>
|
||||
<SCRIPT type="text/javascript">
|
||||
<!--
|
||||
if(window==top) {
|
||||
document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
|
||||
}
|
||||
//-->
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
<A HREF="allclasses-noframe.html"><B>All Classes</B></A>
|
||||
</NOSCRIPT>
|
||||
|
||||
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="skip-navbar_top"></A>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
|
||||
<HR>
|
||||
<CENTER>
|
||||
<H2>
|
||||
<B>Deprecated API</B></H2>
|
||||
</CENTER>
|
||||
<HR SIZE="4" NOSHADE>
|
||||
<B>Contents</B><UL>
|
||||
<LI><A HREF="#field">Deprecated Fields</A>
|
||||
<LI><A HREF="#method">Deprecated Methods</A>
|
||||
</UL>
|
||||
|
||||
<A NAME="field"><!-- --></A>
|
||||
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
||||
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
|
||||
<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
|
||||
<B>Deprecated Fields</B></FONT></TH>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PConstants.html#CENTER_DIAMETER">processing.core.PConstants.CENTER_DIAMETER</A>
|
||||
<BR>
|
||||
<I>Use DIAMETER instead.</I> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PConstants.html#CENTER_RADIUS">processing.core.PConstants.CENTER_RADIUS</A>
|
||||
<BR>
|
||||
<I>Use RADIUS instead.</I> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PConstants.html#NORMALIZED">processing.core.PConstants.NORMALIZED</A>
|
||||
<BR>
|
||||
<I>use NORMAL instead</I> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<P>
|
||||
<A NAME="method"><!-- --></A>
|
||||
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
||||
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
|
||||
<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
|
||||
<B>Deprecated Methods</B></FONT></TH>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PApplet.html#arraycopy(java.lang.Object, int, java.lang.Object, int, int)">processing.core.PApplet.arraycopy(Object, int, Object, int, int)</A>
|
||||
<BR>
|
||||
<I>Use arrayCopy() instead.</I> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PApplet.html#arraycopy(java.lang.Object, java.lang.Object)">processing.core.PApplet.arraycopy(Object, Object)</A>
|
||||
<BR>
|
||||
<I>Use arrayCopy() instead.</I> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PApplet.html#arraycopy(java.lang.Object, java.lang.Object, int)">processing.core.PApplet.arraycopy(Object, Object, int)</A>
|
||||
<BR>
|
||||
<I>Use arrayCopy() instead.</I> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><A HREF="processing/core/PApplet.html#openStream(java.lang.String)">processing.core.PApplet.openStream(String)</A>
|
||||
<BR>
|
||||
<I>As of release 0136, use createInput() instead.</I> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<P>
|
||||
<HR>
|
||||
|
||||
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<A NAME="navbar_bottom"><!-- --></A>
|
||||
<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
|
||||
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
|
||||
<TR>
|
||||
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
|
||||
<A NAME="navbar_bottom_firstrow"><!-- --></A>
|
||||
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
|
||||
<TR ALIGN="center" VALIGN="top">
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
|
||||
</EM>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
PREV
|
||||
NEXT</FONT></TD>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
<A HREF="index.html?deprecated-list.html" target="_top"><B>FRAMES</B></A>
|
||||
<A HREF="deprecated-list.html" target="_top"><B>NO FRAMES</B></A>
|
||||
<SCRIPT type="text/javascript">
|
||||
<!--
|
||||
if(window==top) {
|
||||
document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
|
||||
}
|
||||
//-->
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
<A HREF="allclasses-noframe.html"><B>All Classes</B></A>
|
||||
</NOSCRIPT>
|
||||
|
||||
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="skip-navbar_bottom"></A>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
212
build/javadoc/core/help-doc.html
Normal file
212
build/javadoc/core/help-doc.html
Normal file
@ -0,0 +1,212 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!--NewPage-->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>
|
||||
API Help
|
||||
</TITLE>
|
||||
|
||||
|
||||
<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
|
||||
|
||||
<SCRIPT type="text/javascript">
|
||||
function windowTitle()
|
||||
{
|
||||
parent.document.title="API Help";
|
||||
}
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
</NOSCRIPT>
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="white" onload="windowTitle();">
|
||||
|
||||
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<A NAME="navbar_top"><!-- --></A>
|
||||
<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
|
||||
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
|
||||
<TR>
|
||||
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
|
||||
<A NAME="navbar_top_firstrow"><!-- --></A>
|
||||
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
|
||||
<TR ALIGN="center" VALIGN="top">
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
|
||||
</EM>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
PREV
|
||||
NEXT</FONT></TD>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
<A HREF="index.html?help-doc.html" target="_top"><B>FRAMES</B></A>
|
||||
<A HREF="help-doc.html" target="_top"><B>NO FRAMES</B></A>
|
||||
<SCRIPT type="text/javascript">
|
||||
<!--
|
||||
if(window==top) {
|
||||
document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
|
||||
}
|
||||
//-->
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
<A HREF="allclasses-noframe.html"><B>All Classes</B></A>
|
||||
</NOSCRIPT>
|
||||
|
||||
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="skip-navbar_top"></A>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
|
||||
<HR>
|
||||
<CENTER>
|
||||
<H1>
|
||||
How This API Document Is Organized</H1>
|
||||
</CENTER>
|
||||
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.<H3>
|
||||
Overview</H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
The <A HREF="overview-summary.html">Overview</A> page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.</BLOCKQUOTE>
|
||||
<H3>
|
||||
Package</H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:<UL>
|
||||
<LI>Interfaces (italic)<LI>Classes<LI>Enums<LI>Exceptions<LI>Errors<LI>Annotation Types</UL>
|
||||
</BLOCKQUOTE>
|
||||
<H3>
|
||||
Class/Interface</H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:<UL>
|
||||
<LI>Class inheritance diagram<LI>Direct Subclasses<LI>All Known Subinterfaces<LI>All Known Implementing Classes<LI>Class/interface declaration<LI>Class/interface description
|
||||
<P>
|
||||
<LI>Nested Class Summary<LI>Field Summary<LI>Constructor Summary<LI>Method Summary
|
||||
<P>
|
||||
<LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL>
|
||||
Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
<H3>
|
||||
Annotation Type</H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
Each annotation type has its own separate page with the following sections:<UL>
|
||||
<LI>Annotation Type declaration<LI>Annotation Type description<LI>Required Element Summary<LI>Optional Element Summary<LI>Element Detail</UL>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
<H3>
|
||||
Enum</H3>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
Each enum has its own separate page with the following sections:<UL>
|
||||
<LI>Enum declaration<LI>Enum description<LI>Enum Constant Summary<LI>Enum Constant Detail</UL>
|
||||
</BLOCKQUOTE>
|
||||
<H3>
|
||||
Tree (Class Hierarchy)</H3>
|
||||
<BLOCKQUOTE>
|
||||
There is a <A HREF="overview-tree.html">Class Hierarchy</A> page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with <code>java.lang.Object</code>. The interfaces do not inherit from <code>java.lang.Object</code>.<UL>
|
||||
<LI>When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.<LI>When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.</UL>
|
||||
</BLOCKQUOTE>
|
||||
<H3>
|
||||
Deprecated API</H3>
|
||||
<BLOCKQUOTE>
|
||||
The <A HREF="deprecated-list.html">Deprecated API</A> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</BLOCKQUOTE>
|
||||
<H3>
|
||||
Index</H3>
|
||||
<BLOCKQUOTE>
|
||||
The <A HREF="index-all.html">Index</A> contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.</BLOCKQUOTE>
|
||||
<H3>
|
||||
Prev/Next</H3>
|
||||
These links take you to the next or previous class, interface, package, or related page.<H3>
|
||||
Frames/No Frames</H3>
|
||||
These links show and hide the HTML frames. All pages are available with or without frames.
|
||||
<P>
|
||||
<H3>
|
||||
Serialized Form</H3>
|
||||
Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
|
||||
<P>
|
||||
<H3>
|
||||
Constant Field Values</H3>
|
||||
The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.
|
||||
<P>
|
||||
<FONT SIZE="-1">
|
||||
<EM>
|
||||
This help file applies to API documentation generated using the standard doclet.</EM>
|
||||
</FONT>
|
||||
<BR>
|
||||
<HR>
|
||||
|
||||
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<A NAME="navbar_bottom"><!-- --></A>
|
||||
<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
|
||||
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
|
||||
<TR>
|
||||
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
|
||||
<A NAME="navbar_bottom_firstrow"><!-- --></A>
|
||||
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
|
||||
<TR ALIGN="center" VALIGN="top">
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
|
||||
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
|
||||
</EM>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
PREV
|
||||
NEXT</FONT></TD>
|
||||
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
||||
<A HREF="index.html?help-doc.html" target="_top"><B>FRAMES</B></A>
|
||||
<A HREF="help-doc.html" target="_top"><B>NO FRAMES</B></A>
|
||||
<SCRIPT type="text/javascript">
|
||||
<!--
|
||||
if(window==top) {
|
||||
document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
|
||||
}
|
||||
//-->
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
<A HREF="allclasses-noframe.html"><B>All Classes</B></A>
|
||||
</NOSCRIPT>
|
||||
|
||||
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="skip-navbar_bottom"></A>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
5954
build/javadoc/core/index-all.html
Normal file
5954
build/javadoc/core/index-all.html
Normal file
File diff suppressed because it is too large
Load Diff
38
build/javadoc/core/index.html
Normal file
38
build/javadoc/core/index.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
|
||||
<!--NewPage-->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>
|
||||
Generated Documentation (Untitled)
|
||||
</TITLE>
|
||||
<SCRIPT type="text/javascript">
|
||||
targetPage = "" + window.location.search;
|
||||
if (targetPage != "" && targetPage != "undefined")
|
||||
targetPage = targetPage.substring(1);
|
||||
if (targetPage.indexOf(":") != -1)
|
||||
targetPage = "undefined";
|
||||
function loadFrames() {
|
||||
if (targetPage != "" && targetPage != "undefined")
|
||||
top.classFrame.location = top.targetPage;
|
||||
}
|
||||
</SCRIPT>
|
||||
<NOSCRIPT>
|
||||
</NOSCRIPT>
|
||||
</HEAD>
|
||||
<FRAMESET cols="20%,80%" title="" onLoad="top.loadFrames()">
|
||||
<FRAMESET rows="30%,70%" title="" onLoad="top.loadFrames()">
|
||||
<FRAME src="overview-frame.html" name="packageListFrame" title="All Packages">
|
||||
<FRAME src="allclasses-frame.html" name="packageFrame" title="All classes and interfaces (except non-static nested types)">
|
||||
</FRAMESET>
|
||||
<FRAME src="overview-summary.html" name="classFrame" title="Package, class and interface descriptions" scrolling="yes">
|
||||
<NOFRAMES>
|
||||
<H2>
|
||||
Frame Alert</H2>
|
||||
|
||||
<P>
|
||||
This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
|
||||
<BR>
|
||||
Link to<A HREF="overview-summary.html">Non-frame version.</A>
|
||||
</NOFRAMES>
|
||||
</FRAMESET>
|
||||
</HTML>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user