diff --git a/.classpath b/.classpath
new file mode 100644
index 000000000..71e8cc144
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 000000000..0b76a40ba
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ processing-head
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..ef277e5a2
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -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
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..677b9819b
--- /dev/null
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -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=
diff --git a/app/.classpath b/app/.classpath
new file mode 100644
index 000000000..26775c499
--- /dev/null
+++ b/app/.classpath
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/.classpath_macosx b/app/.classpath_macosx
new file mode 100644
index 000000000..26775c499
--- /dev/null
+++ b/app/.classpath_macosx
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/.classpath_vista b/app/.classpath_vista
new file mode 100755
index 000000000..c7ec5acb9
--- /dev/null
+++ b/app/.classpath_vista
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/.project b/app/.project
new file mode 100644
index 000000000..69a82c3d0
--- /dev/null
+++ b/app/.project
@@ -0,0 +1,17 @@
+
+
+ processing
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/app/.settings/org.eclipse.jdt.core.prefs b/app/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..d6676cc6b
--- /dev/null
+++ b/app/.settings/org.eclipse.jdt.core.prefs
@@ -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
diff --git a/app/.settings/org.eclipse.jdt.ui.prefs b/app/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..4ce979da4
--- /dev/null
+++ b/app/.settings/org.eclipse.jdt.ui.prefs
@@ -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
diff --git a/app/ArduinoMessageSiphon.java b/app/ArduinoMessageSiphon.java
deleted file mode 100644
index ab40d51c4..000000000
--- a/app/ArduinoMessageSiphon.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- Part of the Arduino project - http://arduino.berlios.de
-
- This class reads from an input stream
- and flushes out everything to the System.out
- It can report interrupts back to the parent process
-
- @author DojoDave
- @www http://www.0j0.org
-
-
- 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
-*/
-
-// TODO migrate codebase to arduino.app
-package processing.app;
-
-import java.io.*;
-
-class ArduinoMessageSiphon extends Thread
-{
- /** Stream to read from */
- InputStream is;
-
- /** Process' parent in execution */
- Thread parent;
-
- /** Output message from System.error */
- public String theMsg ="";
-
- /** Result value to be sent back */
- public int result = -1;
-
- /** Count errors and warnings to be sent back */
- public int totalErrors = 0;
-
- /** Debug Errors and Warnings */
- public boolean debugWarning = false;
- public boolean debugError = false;
- public boolean logAllOutput = false;
-
- /**
- * Creates the stream to flush
- * @param theIS is the input stream we will monitor
- * process is the parent process that called this
- */
- public ArduinoMessageSiphon(InputStream theIS, Thread process)
- {
- // Assign to member variables
- is = theIS;
- parent = process;
-
- }
-
- /**
- * Creates the stream to flush
- * @param theIS is the input stream we will monitor
- * process is the parent process that called this
- * warnings will debug warnings when calling commands
- * errors will debug errors when calling commands
- */
-
- /**
- * The errors it will report are in the ranges
- * 49 - 0 for the programmer's errors
- * 99 - 50 for the compiler's errors
- */
- public ArduinoMessageSiphon(InputStream theIS, Thread process, boolean warnings, boolean errors)
- {
- // Assign to member variables
- is = theIS;
- parent = process;
- debugWarning = warnings;
- debugError = errors;
-
- }
-
- /**
- * The errors it will report are in the ranges
- * 49 - 0 for the programmer's errors
- * 99 - 50 for the compiler's errors
- */
- public ArduinoMessageSiphon(InputStream theIS, Thread process, boolean outlog)
- {
- // Assign to member variables
- is = theIS;
- parent = process;
- logAllOutput = outlog;
-
- }
-
- /** Performs system call specific code */
- public void run()
- {
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
-
- try {
- String theLine;
- while ((theLine = br.readLine()) != null) {
- if (logAllOutput) {
- theMsg += theLine + "\r\n";
- //System.out.println(theMsg);
- }
- if ((theLine.indexOf("warning:") != -1) && (theLine.indexOf("prog.c:") != -1) && (debugWarning)) {
- theMsg += theLine + "\r\n";
- totalErrors++;
- }
- if ((theLine.indexOf("error:") != -1) && (theLine.indexOf("prog.c:") != -1) && (debugError)) {
- result = 97;
- theMsg += theLine + "\r\n";
- totalErrors++;
- }
- if (theLine.indexOf("Errors: none") != -1) {
- result = 0;
- }
- if (theLine.indexOf("bytes transferred") != -1) {
- result = 0;
- }
- if (theLine.toLowerCase().indexOf("not responding") != -1) {
- result = 49;
- }
- }
- br.close();
-
- // waits 20 secs until being killed by the
- // parent process or just dies, no zombies wanted!!
- try {
- Thread.currentThread().sleep(20000);
- } catch (InterruptedException ie) {
- }
- } catch (Exception err) {
- err.printStackTrace();
- result = 96;
- }
- }
-}
-
diff --git a/app/Base.java b/app/Base.java
deleted file mode 100644
index 8efbc7f90..000000000
--- a/app/Base.java
+++ /dev/null
@@ -1,1111 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Arduino project - http://arduino.berlios.de
-
-
-
- Based on processing http://www.processing.org
- Copyright (c) 2004-05 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.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-import javax.swing.text.*;
-import javax.swing.undo.*;
-
-import com.apple.mrj.*;
-import com.ice.jni.registry.*;
-
-import processing.core.*;
-
-
-/**
- * The base class for the main Arduino application.
- *
- * Primary role of this class is for platform identification and
- * general interaction with the system (launching URLs, loading
- * files and images, etc) that comes from that.
- */
-public class Base {
- static final int VERSION = 16;
- static final String VERSION_NAME = "0016";
-
- /**
- * Path of filename opened on the command line,
- * or via the MRJ open document handler.
- */
- static String openedAtStartup;
-
- Editor editor;
-
-
- static public void main(String args[]) {
-
- // make sure that this is running on java 1.4
-
- if (PApplet.javaVersion < 1.4f) {
- //System.err.println("no way man");
- Base.showError("Need to install Java 1.4",
- "This version of Processing requires \n" +
- "Java 1.4 or later to run properly.\n" +
- "Please visit java.com to upgrade.", null);
- }
-
-
- // grab any opened file from the command line
-
- if (args.length == 1) {
- Base.openedAtStartup = args[0];
- }
-
-
- // register a temporary/early version of the mrj open document handler,
- // because the event may be lost (sometimes, not always) by the time
- // that Editor is properly constructed.
-
- MRJOpenDocumentHandler startupOpen = new MRJOpenDocumentHandler() {
- public void handleOpenFile(File file) {
- // this will only get set once.. later will be handled
- // by the Editor version of this fella
- if (Base.openedAtStartup == null) {
- //System.out.println("handling outside open file: " + file);
- Base.openedAtStartup = file.getAbsolutePath();
- }
- }
- };
- MRJApplicationUtils.registerOpenDocumentHandler(startupOpen);
-
- Base app = new Base();
- }
-
-
- public Base() {
-
- // set the look and feel before opening the window
-
- try {
- if (Base.isMacOS()) {
- // 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));
-
- } else if (Base.isLinux()) {
- //Tweaks to the Linux LookAndFeel should go here
- //Currently the GTK-LnF is set as the default theme
- //in the arduino startup shell script
- } else {
- //All other platforms (should be only Windows left) use the
- //standard theme
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- // use native popups so they don't look so crappy on osx
- JPopupMenu.setDefaultLightWeightPopupEnabled(false);
-
- // build the editor object
- editor = new Editor();
-
- // get things rawkin
- editor.pack();
-
- // has to be here to set window size properly
- editor.restorePreferences();
-
- // show the window
- editor.show();
-
- // attempt to build libraries
- editor.prepareLibraries();
-
- // check for updates
- if (Preferences.getBoolean("update.check")) {
- new UpdateCheck(editor);
- }
- }
-
-
- // .................................................................
-
-
- /**
- * returns true if the Arduino is running on a Mac OS machine,
- * specifically a Mac OS X machine because it doesn't run on OS 9 anymore.
- */
- static public boolean isMacOS() {
- return PApplet.platform == PConstants.MACOSX;
- }
-
-
- /**
- * returns true if running on windows.
- */
- static public boolean isWindows() {
- return PApplet.platform == PConstants.WINDOWS;
- }
-
-
- /**
- * true if running on linux.
- */
- static public boolean isLinux() {
- return PApplet.platform == PConstants.LINUX;
- }
-
-
- // .................................................................
-
-
- 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;
-
-
- static public File getSettingsFolder() {
- File dataFolder = null;
-
- String pref = Preferences.get("settings.path");
- if (pref != null) {
- dataFolder = new File(pref);
-
- } else if (Base.isMacOS()) {
- // 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/
-
- // this is the 1.4 version.. but using 1.3 since i have the stubs
- // import com.apple.eio.*
- //println(FileManager.findFolder(kUserDomain,
- // kDomainLibraryFolderType));
-
- // not clear if i can write to this folder tho..
- try {
- /*
- if (false) {
- // this is because the mrjtoolkit stubs don't have the
- // thows exception around them
- new FileInputStream("ignored");
- }
- */
-
- // this method has to be dynamically loaded, because
- MRJOSType domainLibrary = new MRJOSType("dlib");
- Method findFolderMethod =
- MRJFileUtils.class.getMethod("findFolder",
- new Class[] { Short.TYPE,
- MRJOSType.class });
- File libraryFolder = (File)
- findFolderMethod.invoke(null, new Object[] { new Short(kUserDomain),
- domainLibrary });
-
- dataFolder = new File(libraryFolder, "Arduino");
-
- } catch (Exception e) {
- // this could be FileNotFound or NoSuchMethod
- //} catch (FileNotFoundException e) {
- //e.printStackTrace();
- //System.exit(1);
- showError("Problem getting data folder",
- "Error getting the Arduino data folder.", e);
- }
-
- } else if (Base.isWindows()) {
- // looking for Documents and Settings/blah/Application Data/Arduino
-
- // this is just based on the other documentation, and eyeballing
- // that part of the registry.. not confirmed by any msft/msdn docs.
- // HKEY_CURRENT_USER\Software\Microsoft
- // \Windows\CurrentVersion\Explorer\Shell Folders
- // Value Name: AppData
- // Value Type: REG_SZ
- // Value Data: path
-
- try {
- //RegistryKey topKey = Registry.getTopLevelKey("HKCU");
- RegistryKey topKey = Registry.HKEY_CURRENT_USER;
-
- String localKeyPath =
- "Software\\Microsoft\\Windows\\CurrentVersion" +
- "\\Explorer\\Shell Folders";
- RegistryKey localKey = topKey.openSubKey(localKeyPath);
- String appDataPath = cleanKey(localKey.getStringValue("AppData"));
- //System.out.println("app data path is " + appDataPath);
- //System.exit(0);
- //topKey.closeKey(); // necessary?
- //localKey.closeKey();
-
- dataFolder = new File(appDataPath, "Arduino");
-
- } catch (Exception e) {
- showError("Problem getting data folder",
- "Error getting the Arduino data folder.", e);
- }
- //return null;
-
- } else {
- // otherwise make a .arduino directory int the user's home dir
- File home = new File(System.getProperty("user.home"));
- dataFolder = new File(home, ".arduino");
- }
-
- // create the folder if it doesn't exist already
- boolean result = true;
- if (!dataFolder.exists()) {
- result = dataFolder.mkdirs();
- }
-
- if (!result) {
- // try the fallback location
- System.out.println("Using fallback path for settings.");
- String fallback = Preferences.get("settings.path.fallback");
- dataFolder = new File(fallback);
- if (!dataFolder.exists()) {
- result = dataFolder.mkdirs();
- }
- }
-
- if (!result) {
- showError("Settings issues",
- "Arduino cannot run because it could not\n" +
- "create a folder to store your settings.", null);
- }
-
- return dataFolder;
- }
-
-
- static public File getSettingsFile(String filename) {
- return new File(getSettingsFolder(), filename);
- }
-
-
- static File buildFolder;
-
- static public File getBuildFolder() {
- if (buildFolder == null) {
- String buildPath = Preferences.get("build.path");
- if (buildPath != null) {
- buildFolder = new File(buildPath);
-
- } else {
- //File folder = new File(getTempFolder(), "build");
- //if (!folder.exists()) folder.mkdirs();
- buildFolder = createTempFolder("build");
- buildFolder.deleteOnExit();
- }
- }
- return buildFolder;
- }
-
-
- /**
- * Get the path to the platform's temporary folder, by creating
- * a temporary temporary file and getting its parent folder.
- *
- * Modified for revision 0094 to actually make the folder randomized
- * to avoid conflicts in multi-user environments. (Bug 177)
- */
- static public File createTempFolder(String name) {
- try {
- File folder = File.createTempFile(name, null);
- //String tempPath = ignored.getParent();
- //return new File(tempPath);
- folder.delete();
- folder.mkdirs();
- return folder;
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null; // TODO could we *really* ever reach this?
- }
-
-
- /*
- static public void addBuildFolderToClassPath() {
- String path = getBuildFolder().getAbsolutePath();
- String jcp = System.getProperty("java.class.path");
- if (jcp.indexOf(path) == -1) {
- System.setProperty("java.class.path", path + File.pathSeparator + jcp);
- //return new File(getProcessingDataFolder(), "build");
- System.out.println("jcp is now " +
- System.getProperty("java.class.path"));
- }
- }
- */
-
-
- static public File getDefaultSketchbookFolder() {
- File sketchbookFolder = null;
-
- if (Base.isMacOS()) {
- // looking for /Users/blah/Documents/Arduino
-
- // 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/
-
- // this is the 1.4 version.. but using 1.3 since i have the stubs
- // import com.apple.eio.*
- //println(FileManager.findFolder(kUserDomain,
- // kDomainLibraryFolderType));
-
- // not clear if i can write to this folder tho..
- try {
- MRJOSType domainDocuments = new MRJOSType("docs");
- //File libraryFolder = MRJFileUtils.findFolder(domainDocuments);
-
- // for 77, try switching this to the user domain, just to be sure
- Method findFolderMethod =
- MRJFileUtils.class.getMethod("findFolder",
- new Class[] { Short.TYPE,
- MRJOSType.class });
- File documentsFolder = (File)
- findFolderMethod.invoke(null, new Object[] { new Short(kUserDomain),
- domainDocuments });
- sketchbookFolder = new File(documentsFolder, "Arduino");
-
- } catch (Exception e) {
- //showError("Could not find folder",
- // "Could not locate the Documents folder.", e);
- sketchbookFolder = promptSketchbookLocation();
- }
-
- } else if (isWindows()) {
- // looking for Documents and Settings/blah/My Documents/Arduino
- // (though using a reg key since it's different on other platforms)
-
- // http://support.microsoft.com/?kbid=221837&sd=RMVP
- // 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
-
- try {
- RegistryKey topKey = Registry.HKEY_CURRENT_USER;
-
- String localKeyPath =
- "Software\\Microsoft\\Windows\\CurrentVersion" +
- "\\Explorer\\Shell Folders";
- RegistryKey localKey = topKey.openSubKey(localKeyPath);
- String personalPath = cleanKey(localKey.getStringValue("Personal"));
- //topKey.closeKey(); // necessary?
- //localKey.closeKey();
- sketchbookFolder = new File(personalPath, "Arduino");
-
- } catch (Exception e) {
- //showError("Problem getting folder",
- // "Could not locate the Documents folder.", e);
- sketchbookFolder = promptSketchbookLocation();
- }
-
- } else {
- sketchbookFolder = promptSketchbookLocation();
-
- /*
- // on linux (or elsewhere?) prompt the user for the location
- JFileChooser fc = new JFileChooser();
- fc.setDialogTitle("Select the folder where " +
- "Arduino programs should be stored...");
- //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());
- sketchbookFolder = fc.getSelectedFile();
-
- } else {
- System.exit(0);
- }
- */
- }
-
- // create the folder if it doesn't exist already
- boolean result = true;
- if (!sketchbookFolder.exists()) {
- result = sketchbookFolder.mkdirs();
- }
-
- if (!result) {
- // try the fallback location
- System.out.println("Using fallback path for sketchbook.");
- String fallback = Preferences.get("sketchbook.path.fallback");
- sketchbookFolder = new File(fallback);
- if (!sketchbookFolder.exists()) {
- result = sketchbookFolder.mkdirs();
- }
- }
-
- if (!result) {
- showError("error",
- "Arduino cannot run because it could not\n" +
- "create a folder to store your sketchbook.", null);
- }
-
- return sketchbookFolder;
- }
-
-
- /**
- * Check for a new sketchbook location.
- */
- static protected File promptSketchbookLocation() {
- File folder = null;
-
- folder = new File(System.getProperty("user.home"), "sketchbook");
- if (!folder.exists()) {
- folder.mkdirs();
- return folder;
- }
-
- folder = Base.selectFolder("Select (or create new) folder for sketches...",
- null, null);
- if (folder == null) {
- System.exit(0);
- }
- return folder;
- }
-
-
- /**
- * Implementation for choosing directories that handles both the
- * Mac OS X hack to allow the native AWT file dialog, or uses
- * the JFileChooser on other platforms. Mac AWT trick obtained from
- * this post
- * on the OS X Java dev archive which explains the cryptic note in
- * Apple's Java 1.4 release docs about the special System property.
- */
- static public File selectFolder(String prompt, File folder, Frame frame) {
- if (Base.isMacOS()) {
- if (frame == null) frame = new Frame(); //.pack();
- FileDialog fd = new FileDialog(frame, prompt, FileDialog.LOAD);
- if (folder != null) {
- fd.setDirectory(folder.getParent());
- //fd.setFile(folder.getName());
- }
- System.setProperty("apple.awt.fileDialogForDirectories", "true");
- fd.show();
- System.setProperty("apple.awt.fileDialogForDirectories", "false");
- if (fd.getFile() == null) {
- return null;
- }
- return new File(fd.getDirectory(), fd.getFile());
-
- } else {
- JFileChooser fc = new JFileChooser();
- fc.setDialogTitle(prompt);
- if (folder != null) {
- fc.setSelectedFile(folder);
- }
- fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-
- int returned = fc.showOpenDialog(new JDialog());
- if (returned == JFileChooser.APPROVE_OPTION) {
- return fc.getSelectedFile();
- }
- }
- return null;
- }
-
-
- static public String cleanKey(String what) {
- // jnireg seems to be reading the chars as bytes
- // so maybe be as simple as & 0xff and then running through decoder
-
- char c[] = what.toCharArray();
-
- // if chars are in the tooHigh range, it's prolly because
- // a byte from the jni registry was turned into a char
- // and there was a sign extension.
- // e.g. 0xFC (252, umlaut u) became 0xFFFC (65532).
- // but on a japanese system, maybe this is two-byte and ok?
- int tooHigh = 65536 - 128;
- for (int i = 0; i < c.length; i++) {
- if (c[i] >= tooHigh) c[i] &= 0xff;
-
- /*
- if ((c[i] >= 32) && (c[i] < 128)) {
- System.out.print(c[i]);
- } else {
- System.out.print("[" + PApplet.hex(c[i]) + "]");
- }
- */
- }
- //System.out.println();
- return new String(c);
- }
-
-
- // .................................................................
-
-
- // someone needs to be slapped
- //static KeyStroke closeWindowKeyStroke;
-
- /**
- * Return true if the key event was a Ctrl-W or an ESC,
- * both indicators to close the window.
- * Use as part of a keyPressed() event handler for frames.
- */
- /*
- static public boolean isCloseWindowEvent(KeyEvent e) {
- if (closeWindowKeyStroke == null) {
- int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- closeWindowKeyStroke = KeyStroke.getKeyStroke('W', modifiers);
- }
- return ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
- KeyStroke.getKeyStrokeForEvent(e).equals(closeWindowKeyStroke));
- }
- */
-
-
- /**
- * Registers key events for a Ctrl-W and ESC with an ActionListener
- * that will take care of disposing the window.
- */
- static public void registerWindowCloseKeys(JRootPane root, //Window window,
- ActionListener disposer) {
- /*
- JRootPane root = null;
- if (window instanceof JFrame) {
- root = ((JFrame)window).getRootPane();
- } else if (window instanceof JDialog) {
- root = ((JDialog)window).getRootPane();
- }
- */
-
- KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
- root.registerKeyboardAction(disposer, stroke,
- JComponent.WHEN_IN_FOCUSED_WINDOW);
-
- int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- stroke = KeyStroke.getKeyStroke('W', modifiers);
- root.registerKeyboardAction(disposer, stroke,
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- }
-
-
- // .................................................................
-
-
- static public void showReference(String referenceFile) {
- openURL(Base.getContents("reference" + File.separator + referenceFile));
- }
-
-
- static public void showReference() {
- showReference("index.html");
- }
-
-
- static public void showEnvironment() {
- showReference("Guide_Environment.html");
- }
-
-
- static public void showTroubleshooting() {
- showReference("Guide_Troubleshooting.html");
- }
-
-
- /**
- * Opens the local copy of the FAQ that's included
- * with the Processing download.
- */
- static public void showFAQ() {
- showReference("faq.html");
- }
-
-
- // .................................................................
-
-
- /**
- * Implements the cross-platform headache of opening URLs
- * TODO This code should be replaced by PApplet.link(),
- * however that's not a static method (because it requires
- * an AppletContext when used as an applet), so it's mildly
- * trickier than just removing this method.
- */
- static public void openURL(String url) {
- //System.out.println("opening url " + url);
- try {
- if (Base.isWindows()) {
- // 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 + "\"");
- }
-
- } else if (Base.isMacOS()) {
- //com.apple.eio.FileManager.openURL(url);
-
- if (!url.startsWith("http://")) {
- // 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.mrj.MRJFileUtils.openURL(url);
-
- } else if (Base.isLinux()) {
- // how's mozilla sound to ya, laddie?
- //Runtime.getRuntime().exec(new String[] { "mozilla", url });
- //String browser = Preferences.get("browser");
- //Runtime.getRuntime().exec(new String[] { browser, url });
- String launcher = Preferences.get("launcher.linux");
- if (launcher != null) {
- Runtime.getRuntime().exec(new String[] { launcher, url });
- }
- } else {
- String launcher = Preferences.get("launcher");
- if (launcher != null) {
- Runtime.getRuntime().exec(new String[] { launcher, url });
- } else {
- System.err.println("Unspecified platform, no launcher available.");
- }
- }
-
- } catch (IOException e) {
- Base.showWarning("Could not open URL",
- "An error occurred while trying to open\n" + url, e);
- }
- }
-
-
- static boolean openFolderAvailable() {
- if (Base.isWindows() || Base.isMacOS()) return true;
-
- if (Base.isLinux()) {
- // Assume that this is set to something valid
- if (Preferences.get("launcher.linux") != 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.linux", "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.linux", "kde-open");
- return true;
- } catch (Exception e) { }
- }
- return false;
- }
-
-
- /**
- * Implements the other cross-platform headache of opening
- * a folder in the machine's native file browser.
- */
- static public void openFolder(File file) {
- try {
- String folder = file.getAbsolutePath();
-
- if (Base.isWindows()) {
- // 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 + "\"");
-
- } else if (Base.isMacOS()) {
- openURL(folder); // handles char replacement, etc
-
- } else if (Base.isLinux()) {
- String launcher = Preferences.get("launcher.linux");
- if (launcher != null) {
- Runtime.getRuntime().exec(new String[] { launcher, folder });
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
-
- /**
- * "No cookie for you" type messages. Nothing fatal or all that
- * much of a bummer, but something to notify the user about.
- */
- static public void showMessage(String title, String message) {
- if (title == null) title = "Message";
- JOptionPane.showMessageDialog(new Frame(), message, title,
- JOptionPane.INFORMATION_MESSAGE);
- }
-
-
- /**
- * Non-fatal error message with optional stack trace side dish.
- */
- static public void showWarning(String title, String message,
- Exception e) {
- if (title == null) title = "Warning";
- JOptionPane.showMessageDialog(new Frame(), message, title,
- JOptionPane.WARNING_MESSAGE);
-
- //System.err.println(e.toString());
- if (e != null) e.printStackTrace();
- }
-
-
- /**
- * Show an error message that's actually fatal to the program.
- * This is an error that can't be recovered. Use showWarning()
- * for errors that allow P5 to continue running.
- */
- static public void showError(String title, String message,
- Throwable e) {
- if (title == null) title = "Error";
- JOptionPane.showMessageDialog(new Frame(), message, title,
- JOptionPane.ERROR_MESSAGE);
-
- if (e != null) e.printStackTrace();
- System.exit(1);
- }
-
-
- // ...................................................................
-
-
- static public String getContents(String what) {
- String basePath = System.getProperty("user.dir");
- return basePath + File.separator + what;
- }
-
- static public String getLibContents(String what) {
- /* On MacOSX, the arduino.app-resources property points to the
- * resources directory inside the app bundle. On other platforms
- * it's not set.
- */
- String appResources = System.getProperty("arduino.app-resources");
- if (appResources != null) {
- return appResources + File.separator + what;
- } else {
- return getContents("lib" + File.separator + what);
- }
- }
-
-
- static public Image getImage(String name, Component who) {
- Image image = null;
- Toolkit tk = Toolkit.getDefaultToolkit();
-
- image = tk.getImage(getLibContents(name));
- MediaTracker tracker = new MediaTracker(who);
- tracker.addImage(image, 0);
- try {
- tracker.waitForAll();
- } catch (InterruptedException e) { }
- return image;
- }
-
-
- static public InputStream getStream(String filename) throws IOException {
- return new FileInputStream(getLibContents(filename));
- }
-
-
- // ...................................................................
-
-
- static public byte[] grabFile(File file) throws IOException {
- int size = (int) file.length();
- FileInputStream input = new FileInputStream(file);
- byte buffer[] = new byte[size];
- int offset = 0;
- int bytesRead;
- while ((bytesRead = input.read(buffer, offset, size-offset)) != -1) {
- offset += bytesRead;
- if (bytesRead == 0) break;
- }
- input.close(); // weren't properly being closed
- input = null;
- return buffer;
- }
-
-
- static public void copyFile(File afile, File bfile) throws IOException {
- InputStream from = new BufferedInputStream(new FileInputStream(afile));
- OutputStream to = new BufferedOutputStream(new FileOutputStream(bfile));
- byte[] buffer = new byte[16 * 1024];
- int bytesRead;
- while ((bytesRead = from.read(buffer)) != -1) {
- to.write(buffer, 0, bytesRead);
- }
- to.flush();
- from.close(); // ??
- from = null;
- to.close(); // ??
- to = null;
-
- bfile.setLastModified(afile.lastModified()); // jdk13+ required
- //} catch (IOException e) {
- // e.printStackTrace();
- //}
- }
-
-
- /**
- * Grab the contents of a file as a string.
- */
- static public String loadFile(File file) throws IOException {
- // empty code file.. no worries, might be getting filled up later
- if (file.length() == 0) return "";
-
- InputStreamReader isr = new InputStreamReader(new FileInputStream(file));
- BufferedReader reader = new BufferedReader(isr);
-
- StringBuffer buffer = new StringBuffer();
- String line = null;
- while ((line = reader.readLine()) != null) {
- buffer.append(line);
- buffer.append('\n');
- }
- reader.close();
- return buffer.toString();
- }
-
-
- /**
- * Spew the contents of a String object out to a file.
- */
- static public void saveFile(String str,
- File file) throws IOException {
-
- ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
- InputStreamReader isr = new InputStreamReader(bis);
- BufferedReader reader = new BufferedReader(isr);
-
- FileWriter fw = new FileWriter(file);
- PrintWriter writer = new PrintWriter(new BufferedWriter(fw));
-
- String line = null;
- while ((line = reader.readLine()) != null) {
- writer.println(line);
- }
- writer.flush();
- writer.close();
- }
-
-
- static public void copyDir(File sourceDir,
- File targetDir) throws IOException {
- targetDir.mkdirs();
- String files[] = sourceDir.list();
- for (int i = 0; i < files.length; i++) {
- if (files[i].equals(".") || files[i].equals("..")) continue;
- File source = new File(sourceDir, files[i]);
- File target = new File(targetDir, files[i]);
- if (source.isDirectory()) {
- //target.mkdirs();
- copyDir(source, target);
- target.setLastModified(source.lastModified());
- } else {
- copyFile(source, target);
- }
- }
- }
-
-
- /**
- * Remove all files in a directory and the directory itself.
- */
- static public void removeDir(File dir) {
- if (dir.exists()) {
- removeDescendants(dir);
- if (!dir.delete()) {
- System.err.println("Could not delete " + dir);
- }
- }
- }
-
-
- /**
- * Recursively remove all files within a directory,
- * used with removeDir(), or when the contents of a dir
- * should be removed, but not the directory itself.
- * (i.e. when cleaning temp files from lib/build)
- */
- static public void removeDescendants(File dir) {
- if (!dir.exists()) return;
-
- String files[] = dir.list();
- for (int i = 0; i < files.length; i++) {
- if (files[i].equals(".") || files[i].equals("..")) continue;
- File dead = new File(dir, files[i]);
- if (!dead.isDirectory()) {
- if (!Preferences.getBoolean("compiler.save_build_files")) {
- if (!dead.delete()) {
- // temporarily disabled
- System.err.println("Could not delete " + dead);
- }
- }
- } else {
- removeDir(dead);
- //dead.delete();
- }
- }
- }
-
-
- /**
- * Calculate the size of the contents of a folder.
- * Used to determine whether sketches are empty or not.
- * Note that the function calls itself recursively.
- */
- static public int calcFolderSize(File folder) {
- int size = 0;
-
- String files[] = folder.list();
- // null if folder doesn't exist, happens when deleting sketch
- if (files == null) return -1;
-
- for (int i = 0; i < files.length; i++) {
- if (files[i].equals(".") || (files[i].equals("..")) ||
- files[i].equals(".DS_Store")) continue;
- File fella = new File(folder, files[i]);
- if (fella.isDirectory()) {
- size += calcFolderSize(fella);
- } else {
- size += (int) fella.length();
- }
- }
- return size;
- }
-
-
- /**
- * Gets a list of all files within the specified folder,
- * and returns a list of their relative paths.
- * Ignores any files/folders prefixed with a dot.
- */
- static public String[] listFiles(String path, boolean relative) {
- return listFiles(new File(path), relative);
- }
-
- static public String[] listFiles(File folder, boolean relative) {
- String path = folder.getAbsolutePath();
- Vector vector = new Vector();
- listFiles(relative ? (path + File.separator) : "", path, vector);
- String outgoing[] = new String[vector.size()];
- vector.copyInto(outgoing);
- return outgoing;
- }
-
- static protected void listFiles(String basePath,
- String path, Vector vector) {
- File folder = new File(path);
- String list[] = folder.list();
- if (list == null) return;
-
- for (int i = 0; i < list.length; i++) {
- if (list[i].charAt(0) == '.') continue;
-
- File file = new File(path, list[i]);
- String newPath = file.getAbsolutePath();
- if (newPath.startsWith(basePath)) {
- newPath = newPath.substring(basePath.length());
- }
- vector.add(newPath);
- if (file.isDirectory()) {
- listFiles(basePath, newPath, vector);
- }
- }
- }
-}
diff --git a/app/Command.java b/app/Command.java
deleted file mode 100644
index 30da3835d..000000000
--- a/app/Command.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- Part of the Arduino project - http://arduino.berlios.de
-
- This class creates a compilation thread
- this is needed for detecting time-outs
- in system calls. It may happen in
- windows whenever there is a syntax error
- that the compilation may hang the IDE
-
- @author DojoDave
- @www http://www.0j0.org
-
- 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
-*/
-
-// TODO migrate codebase to arduino.app
-package processing.app;
-
-import java.io.*;
-
-class Command extends Thread
-{
- /** Command to execute on command line */
- String command;
-
- /** Process in execution */
- Process process;
-
- /** Output message from System.out */
- public String outMsg ="";
-
- /** Error message from System.error */
- public String errorMsg ="";
-
- /** Result value to be sent back */
- public int outResult = -1;
- public int errorResult = -1;
-
- /** Total errors and warnings to be sent back */
- public int totalErrors = 0;
-
- /** Waiting value */
- public int waitResult = -1;
-
- /** Debug Errors and Warnings */
- public boolean debugWarning = false;
- public boolean debugError = false;
- public boolean logAllOutput = false;
-
- /**
- * Creates the compiler object with the
- * gnumake line to call
- * @param command name of the command line to call
- */
- public Command (String co)
- {
- // Assign to member variable
- command = co;
-
- }
-
- /**
- * Creates the compiler object with the
- * gnumake line to call
- * @param command name of the command line to call
- * outlog will debug warnings when calling commands
- */
- public Command (String co, boolean outlog)
- {
- // Assign to member variable
- command = co;
- logAllOutput = outlog;
- }
-
- /**
- * Creates the compiler object with the
- * gnumake line to call
- * @param command name of the command line to call
- * warnings will debug warnings when calling commands
- * errors will debug errors when calling commands
- */
- public Command (String co, boolean warnings, boolean errors)
- {
- // Assign to member variable
- command = co;
- debugWarning = warnings;
- debugError = errors;
- }
-
- /** Performs system call specific code */
- public void run()
- {
- try {
- process = Runtime.getRuntime().exec(command);
- ArduinoMessageSiphon input;
- ArduinoMessageSiphon error;
- if (logAllOutput) {
- input = new ArduinoMessageSiphon(process.getInputStream(), this, logAllOutput);
- error = new ArduinoMessageSiphon(process.getErrorStream(), this, logAllOutput);
- } else {
- input = new ArduinoMessageSiphon(process.getInputStream(), this, debugWarning, debugError);
- error = new ArduinoMessageSiphon(process.getErrorStream(), this, debugWarning, debugError);
- }
- input.start();
- error.start();
-
- // wait for the process to finish. if interrupted
- // before waitFor returns, continue waiting
- //
- boolean compiling = true;
- while (compiling) {
- try {
- waitResult = process.waitFor();
- outResult = input.result;
- errorResult = error.result;
- compiling = false;
- } catch (InterruptedException ignored) { }
- }
-
- try {
- waitResult = process.exitValue();
- } catch (IllegalThreadStateException ignored) { }
-
- // trace the error and outout
- outMsg = input.theMsg;
- errorMsg = error.theMsg;
- totalErrors = error.totalErrors;
-
- // waits 20 secs until being killed by the
- // parent process or just dies, no zombies wanted!!
- try {
- Thread.currentThread().sleep(20000);
- } catch (InterruptedException ie) {
- }
-
- } catch (IOException ioe) {
- outResult = 99;
- }
-
- }
-}
\ No newline at end of file
diff --git a/app/Compiler.java b/app/Compiler.java
deleted file mode 100644
index 9bf9b1670..000000000
--- a/app/Compiler.java
+++ /dev/null
@@ -1,600 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Compiler - default compiler class that connects to avr-gcc
- Part of the Arduino project - http://www.arduino.cc/
-
- Modified by David A. Mellis
-
- Copyright (c) 2004-05 Hernando Barragan
-
- Processing version
- Copyright (c) 2004-05 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
-
- $Id$
-*/
-
-package processing.app;
-
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-import javax.swing.*;
-
-public class Compiler implements MessageConsumer {
- static final String BUGS_URL =
- "https://developer.berlios.de/bugs/?group_id=3590";
- static final String SUPER_BADNESS =
- "Compiler error, please submit this code to " + BUGS_URL;
-
- Sketch sketch;
- String buildPath;
-
- //String buildPath;
- //String className;
- //File includeFolder;
- RunnerException exception;
- //Editor editor;
-
- /*
- public Compiler(String buildPath, String className,
- File includeFolder, Editor editor) {
- this.buildPath = buildPath;
- this.includeFolder = includeFolder;
- this.className = className;
- this.editor = editor;
- }
-
-
- public boolean compile(PrintStream leechErr) {
- */
-
- public Compiler() { } // consider this a warning, you werkin soon.
-
-
- public boolean compile(Sketch sketch, String buildPath, Target target)
- throws RunnerException {
-
- this.sketch = sketch;
- this.buildPath = buildPath;
-
- // the pms object isn't used for anything but storage
- MessageStream pms = new MessageStream(this);
-
- String userdir = System.getProperty("user.dir") + File.separator;
-
-// LibraryManager libraryManager;
-//
-// try {
-// libraryManager = new LibraryManager();
-// } catch (IOException e) {
-// throw new RunnerException(e.getMessage());
-// }
- String avrBasePath;
- if(Base.isMacOS()) {
- avrBasePath = new String("hardware/tools/avr/bin/");
- }
- else if(Base.isLinux()) {
- avrBasePath = new String("");
- }
- else {
- avrBasePath = new String(userdir + "hardware/tools/avr/bin/");
- }
-
- List includePaths = new ArrayList();
- includePaths.add(target.getPath());
- // use lib directories as include paths
- for (int i = 0; i < sketch.importedLibraries.size(); i++) {
- includePaths.add(
- ((Library) sketch.importedLibraries.get(i)).getFolder().getPath());
- }
-
- List baseCommandLinker = new ArrayList(Arrays.asList(new String[] {
- avrBasePath + "avr-gcc",
- "-Os",
- "-Wl,--gc-sections",
- "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
- "-o",
- buildPath + File.separator + sketch.name + ".elf"
- }));
-
- String runtimeLibraryName = buildPath + File.separator + "core.a";
-
- List baseCommandAR = new ArrayList(Arrays.asList(new String[] {
- avrBasePath + "avr-ar",
- "rcs",
- runtimeLibraryName
- }));
-
- // use lib object files
- for (Iterator i = sketch.importedLibraries.iterator(); i.hasNext(); ) {
- Library library = (Library) i.next();
- File[] objectFiles = library.getObjectFiles();
- for (int j = 0; j < objectFiles.length; j++)
- baseCommandLinker.add(objectFiles[j].getPath());
- }
-
- List baseCommandObjcopy = new ArrayList(Arrays.asList(new String[] {
- avrBasePath + "avr-objcopy",
- "-O",
- "-R",
- }));
-
- // make list of code files that need to be compiled and the object files
- // that they will be compiled to (includes code from the sketch and the
- // library for the target platform)
- List sourceNames = new ArrayList();
- List sourceNamesCPP = new ArrayList();
- List objectNames = new ArrayList();
- List objectNamesCPP = new ArrayList();
- List targetObjectNames = new ArrayList();
- List sketchObjectNames = new ArrayList();
- for (int i = 0; i < sketch.codeCount; i++) {
- if (sketch.code[i].preprocName != null) {
- if (sketch.code[i].preprocName.endsWith(".c")) {
- sourceNames.add(buildPath + File.separator + sketch.code[i].preprocName);
- objectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
- sketchObjectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
- } else if (sketch.code[i].preprocName.endsWith(".cpp")) {
- sourceNamesCPP.add(buildPath + File.separator + sketch.code[i].preprocName);
- objectNamesCPP.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
- sketchObjectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
- }
- }
- }
- for (Iterator iter = target.getSourceFilenames().iterator(); iter.hasNext(); ) {
- String filename = (String) iter.next();
- if (filename != null) {
- targetObjectNames.add(buildPath + File.separator + filename + ".o");
- if (filename.endsWith(".c")) {
- sourceNames.add(target.getPath() + File.separator + filename);
- objectNames.add(buildPath + File.separator + filename + ".o");
- } else if (filename.endsWith(".cpp")) {
- sourceNamesCPP.add(target.getPath() + File.separator + filename);
- objectNamesCPP.add(buildPath + File.separator + filename + ".o");
- }
- }
- }
-
- baseCommandLinker.addAll(sketchObjectNames);
- //baseCommandLinker.addAll(targetObjectNames);
- baseCommandLinker.add(runtimeLibraryName);
- baseCommandLinker.add("-L" + buildPath);
- baseCommandLinker.add("-lm");
-
- firstErrorFound = false; // haven't found any errors yet
- secondErrorFound = false;
-
- int result = 0; // pre-initialized to quiet a bogus warning from jikes
- try {
- // execute the compiler, and create threads to deal
- // with the input and error streams
- //
-
- Process process;
- boolean compiling = true;
- for(int i = 0; i < sourceNames.size(); i++) {
- if (execAsynchronously(getCommandCompilerC(avrBasePath, includePaths,
- (String) sourceNames.get(i), (String) objectNames.get(i))) != 0)
- return false;
- }
-
- for(int i = 0; i < sourceNamesCPP.size(); i++) {
- if (execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths,
- (String) sourceNamesCPP.get(i), (String) objectNamesCPP.get(i))) != 0)
- return false;
- }
-
- for(int i = 0; i < targetObjectNames.size(); i++) {
- List commandAR = new ArrayList(baseCommandAR);
- commandAR.add(targetObjectNames.get(i));
- if (execAsynchronously(commandAR) != 0)
- return false;
- }
-
- if (execAsynchronously(baseCommandLinker) != 0)
- return false;
-
- List commandObjcopy;
-
- // Extract EEPROM data (from EEMEM directive) to .eep file.
- commandObjcopy = new ArrayList(baseCommandObjcopy);
- commandObjcopy.add(2, "ihex");
- commandObjcopy.set(3, "-j");
- commandObjcopy.add(".eeprom");
- commandObjcopy.add("--set-section-flags=.eeprom=alloc,load");
- commandObjcopy.add("--no-change-warnings");
- commandObjcopy.add("--change-section-lma");
- commandObjcopy.add(".eeprom=0");
- commandObjcopy.add(buildPath + File.separator + sketch.name + ".elf");
- commandObjcopy.add(buildPath + File.separator + sketch.name + ".eep");
- if (execAsynchronously(commandObjcopy) != 0)
- return false;
-
- commandObjcopy = new ArrayList(baseCommandObjcopy);
- commandObjcopy.add(2, "ihex");
- commandObjcopy.add(".eeprom"); // remove eeprom data
- commandObjcopy.add(buildPath + File.separator + sketch.name + ".elf");
- commandObjcopy.add(buildPath + File.separator + sketch.name + ".hex");
- if (execAsynchronously(commandObjcopy) != 0)
- return false;
- } catch (Exception e) {
- String msg = e.getMessage();
- if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
- //System.err.println("jikes is missing");
- Base.showWarning("Compiler error",
- "Could not find the compiler.\n" +
- "avr-gcc is missing from your PATH.", null);
- return false;
-
- } else {
- e.printStackTrace();
- result = -1;
- }
- }
-
- // an error was queued up by message(), barf this back to build()
- // which will barf it back to Editor. if you're having trouble
- // discerning the imagery, consider how cows regurgitate their food
- // to digest it, and the fact that they have five stomaches.
- //
- //System.out.println("throwing up " + exception);
- if (exception != null) throw exception;
-
- // if the result isn't a known, expected value it means that something
- // is fairly wrong, one possibility is that jikes has crashed.
- //
- if (result != 0 && result != 1 ) {
- //exception = new RunnerException(SUPER_BADNESS);
- //editor.error(exception); // this will instead be thrown
- Base.openURL(BUGS_URL);
- throw new RunnerException(SUPER_BADNESS);
- }
-
- // success would mean that 'result' is set to zero
- return (result == 0); // ? true : false;
- }
-
- public int execAsynchronously(List commandList)
- throws RunnerException, IOException {
- String[] command = new String[commandList.size()];
- commandList.toArray(command);
- int result = 0;
-
- if (Preferences.getBoolean("build.verbose")) {
- for(int j = 0; j < command.length; j++) {
- System.out.print(command[j] + " ");
- }
- System.out.println();
- }
-
- Process process = Runtime.getRuntime().exec(command);
-
- new MessageSiphon(process.getInputStream(), this);
- new MessageSiphon(process.getErrorStream(), this);
-
- // wait for the process to finish. if interrupted
- // before waitFor returns, continue waiting
- boolean compiling = true;
- while (compiling) {
- try {
- result = process.waitFor();
- //System.out.println("result is " + result);
- compiling = false;
- } catch (InterruptedException ignored) { }
- }
-
- if (exception != null) {
- exception.hideStackTrace = true;
- throw exception;
- }
-
- return result;
- }
-
-
- boolean firstErrorFound;
- boolean secondErrorFound;
-
- /**
- * Part of the MessageConsumer interface, this is called
- * whenever a piece (usually a line) of error message is spewed
- * out from the compiler. The errors are parsed for their contents
- * and line number, which is then reported back to Editor.
- */
- public void message(String s) {
- // This receives messages as full lines, so a newline needs
- // to be added as they're printed to the console.
- //System.err.print(s);
-
- // ignore cautions
- if (s.indexOf("warning") != -1) return;
-
- // jikes always uses a forward slash character as its separator,
- // so replace any platform-specific separator characters before
- // attemping to compare
- //
- //String buildPathSubst = buildPath.replace(File.separatorChar, '/') + "/";
- String buildPathSubst = buildPath.replace(File.separatorChar,File.separatorChar) + File.separatorChar;
-
- String partialTempPath = null;
- int partialStartIndex = -1; //s.indexOf(partialTempPath);
- int fileIndex = -1; // use this to build a better exception
-
- // iterate through the project files to see who's causing the trouble
- for (int i = 0; i < sketch.codeCount; i++) {
- if (sketch.code[i].preprocName == null) continue;
-
- partialTempPath = buildPathSubst + sketch.code[i].preprocName;
- partialStartIndex = s.indexOf(partialTempPath);
- if (partialStartIndex != -1) {
- fileIndex = i;
- //System.out.println("fileIndex is " + fileIndex);
- break;
- }
- }
- //+ className + ".java";
-
- // if the partial temp path appears in the error message...
- //
- //int partialStartIndex = s.indexOf(partialTempPath);
- if (partialStartIndex != -1) {
-
- // skip past the path and parse the int after the first colon
- //
- String s1 = s.substring(partialStartIndex +
- partialTempPath.length() + 1);
- //System.out.println(s1);
- int colon = s1.indexOf(':');
-
- if (s1.indexOf("In function") != -1 || colon == -1) {
- System.err.print(s1);
- //firstErrorFound = true;
- return;
- }
-
- int lineNumber;
- try {
- lineNumber = Integer.parseInt(s1.substring(0, colon));
- } catch (NumberFormatException e) {
- System.err.print(s1);
- return;
- }
-
- // the "1" corresponds to the amount of lines written to the main code
- // file by PdePreprocessor's writeHeader() routine before prototypes
- if (fileIndex == 0)
- lineNumber -= 1;
-
- //System.out.println("pde / line number: " + lineNumber);
-
- if (fileIndex == 0) { // main class, figure out which tab
- for (int i = 1; i < sketch.codeCount; i++) {
- if (sketch.code[i].flavor == Sketch.PDE) {
- //System.out.println("preprocOffset "+ sketch.code[i].preprocOffset);
- if (sketch.code[i].preprocOffset < lineNumber) {
- fileIndex = i;
- //System.out.println("i'm thinkin file " + i);
- }
- }
- }
- if (fileIndex != 0) { // if found another culprit
- lineNumber -= sketch.code[fileIndex].preprocOffset;
- //System.out.println("i'm sayin line " + lineNumber);
- }
- }
-
- //String s2 = s1.substring(colon + 2);
- int err = s1.indexOf(":");
- if (err != -1) {
-
- // if the first error has already been found, then this must be
- // (at least) the second error found
- if (firstErrorFound) {
- secondErrorFound = true;
- return;
- }
-
- // if executing at this point, this is *at least* the first error
- firstErrorFound = true;
-
- err += ":".length();
- String description = s1.substring(err);
- description = description.trim();
- System.err.print(description);
-
-/* String hasLoop = "The method \"void loop();\" with default access";
- if (description.indexOf(hasLoop) != -1) {
- description =
- "Rename loop() to draw() in Processing 0070 and higher";
- }
-*/
-/* String constructorProblem =
- "No applicable overload was found for a constructor of type";
- if (description.indexOf(constructorProblem) != -1) {
- //"simong.particles.ParticleSystem". Perhaps you wanted the overloaded version "ParticleSystem();" instead?
- int nextSentence = description.indexOf("\".") + 3;
- description = description.substring(nextSentence);
- }
-*/
-/* String overloadProblem = "No applicable overload";
- if (description.indexOf(overloadProblem) != -1) {
- int nextSentence = description.indexOf("\".") + 3;
- description = description.substring(nextSentence);
- }
-*/
- // c:/fry/processing/build/windows/work/lib/build/Temporary_6858_2476.java:1:34:1:41: Semantic Error: You need to modify your classpath, sourcepath, bootclasspath, and/or extdirs setup. Package "poo/shoe" could not be found in:
-/* String classpathProblem = "You need to modify your classpath";
- if (description.indexOf(classpathProblem) != -1) {
- if (description.indexOf("quicktime/std") != -1) {
- // special case for the quicktime libraries
- description =
- "To run sketches that use the Processing video library, " +
- "you must first install QuickTime for Java.";
-
- } else {
- int nextSentence = description.indexOf(". Package") + 2;
- description =
- description.substring(nextSentence, description.indexOf(':')) +
- " the code folder or in any libraries.";
- }
- }
-*/
- //System.out.println("description = " + description);
- //System.out.println("creating exception " + exception);
- exception = new RunnerException(description, fileIndex, lineNumber-1, -1);
-
- // NOTE!! major change here, this exception will be queued
- // here to be thrown by the compile() function
- //editor.error(exception);
-
- } else {
- System.err.println("i suck: " + s);
- }
-
- } else {
- // this isn't the start of an error line, so don't attempt to parse
- // a line number out of it.
-
- // if the second error hasn't been discovered yet, these lines
- // are probably associated with the first error message,
- // which is already in the status bar, and are likely to be
- // of interest to the user, so spit them to the console.
- //
- if (!secondErrorFound) {
- System.err.println(s);
- }
- }
- }
-
- static private List getCommandCompilerC(String avrBasePath, List includePaths,
- String sourceName, String objectName) {
- List baseCommandCompiler = new ArrayList(Arrays.asList(new String[] {
- avrBasePath + "avr-gcc",
- "-c", // compile, don't link
- "-g", // include debugging info (so errors include line numbers)
- "-Os", // optimize for size
- "-w", // surpress all warnings
- "-ffunction-sections", // place each function in its own section
- "-fdata-sections",
- "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
- "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
- }));
-
- for (int i = 0; i < includePaths.size(); i++) {
- baseCommandCompiler.add("-I" + (String) includePaths.get(i));
- }
-
- baseCommandCompiler.add(sourceName);
- baseCommandCompiler.add("-o"+ objectName);
-
- return baseCommandCompiler;
- }
-
-
- static private List getCommandCompilerCPP(String avrBasePath,
- List includePaths, String sourceName, String objectName) {
- List baseCommandCompilerCPP = new ArrayList(Arrays.asList(new String[] {
- avrBasePath + "avr-g++",
- "-c", // compile, don't link
- "-g", // include debugging info (so errors include line numbers)
- "-Os", // optimize for size
- "-w", // surpress all warnings
- "-fno-exceptions",
- "-ffunction-sections", // place each function in its own section
- "-fdata-sections",
- "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
- "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
- }));
-
- for (int i = 0; i < includePaths.size(); i++) {
- baseCommandCompilerCPP.add("-I" + (String) includePaths.get(i));
- }
-
- baseCommandCompilerCPP.add(sourceName);
- baseCommandCompilerCPP.add("-o"+ objectName);
-
- return baseCommandCompilerCPP;
- }
-
-
-
-
-
- static String bootClassPath;
-
- static public String calcBootClassPath() {
- if (bootClassPath == null) {
- String additional = "";
- if (Base.isMacOS()) {
- additional =
- contentsToClassPath(new File("/System/Library/Java/Extensions/"));
- }
- bootClassPath = System.getProperty("sun.boot.class.path") + additional;
- }
- return bootClassPath;
- }
-
-
- ///
-
-
- /**
- * Return the path for a folder, with appended paths to
- * any .jar or .zip files inside that folder.
- * This will prepend a colon (or whatever the path separator is)
- * so that it can be directly appended to another path string.
- *
- * This will always add the root folder as well, and 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 {
- // add the folder itself in case any unzipped files
- String path = folder.getCanonicalPath();
- abuffer.append(sep);
- abuffer.append(path);
-
- if (!path.endsWith(File.separator)) {
- path += File.separator;
- }
- //System.out.println("path is " + path);
-
- String list[] = folder.list();
- for (int i = 0; i < list.length; i++) {
- if (list[i].toLowerCase().endsWith(".o") ||
- list[i].toLowerCase().endsWith(".a")) {
- 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();
- }
-}
diff --git a/app/Editor.java b/app/Editor.java
deleted file mode 100644
index 7284241cf..000000000
--- a/app/Editor.java
+++ /dev/null
@@ -1,2422 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Editor - main editor panel for the processing development environment
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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
-
- $Id$
-*/
-
-package processing.app;
-
-import processing.app.syntax.*;
-import processing.app.tools.*;
-import processing.core.*;
-
-import java.awt.*;
-import java.awt.datatransfer.*;
-import java.awt.dnd.*;
-import java.awt.event.*;
-import java.awt.print.*;
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.event.*;
-import javax.swing.text.*;
-import javax.swing.undo.*;
-
-import com.apple.mrj.*;
-import com.oroinc.text.regex.*;
-//import de.hunsicker.jalopy.*;
-
-import com.apple.mrj.*;
-import gnu.io.*;
-
-public class Editor extends JFrame
- implements MRJAboutHandler, MRJQuitHandler, MRJPrefsHandler,
- MRJOpenDocumentHandler //, MRJOpenApplicationHandler
-{
- // yeah
- static final String WINDOW_TITLE = "Arduino" + " - " + Base.VERSION_NAME;
-
- // p5 icon for the window
- Image icon;
-
- // otherwise, if the window is resized with the message label
- // set to blank, it's preferredSize() will be fukered
- static public final String EMPTY =
- " " +
- " " +
- " ";
-
- static public final KeyStroke WINDOW_CLOSE_KEYSTROKE =
- KeyStroke.getKeyStroke('W', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
-
- static final int HANDLE_NEW = 1;
- static final int HANDLE_OPEN = 2;
- static final int HANDLE_QUIT = 3;
- int checkModifiedMode;
- String handleOpenPath;
- boolean handleNewShift;
- boolean handleNewLibrary;
-
- PageFormat pageFormat;
- PrinterJob printerJob;
-
- EditorButtons buttons;
- EditorHeader header;
- EditorStatus status;
- EditorConsole console;
- Serial serialPort;
- JSplitPane splitPane;
- JPanel consolePanel;
-
- JLabel lineNumberComponent;
-
- // currently opened program
- public Sketch sketch;
-
- EditorLineStatus lineStatus;
-
- public JEditTextArea textarea;
- EditorListener listener;
-
- // runtime information and window placement
- Point appletLocation;
- //Point presentLocation;
- //Window presentationWindow;
- RunButtonWatcher watcher;
- //Runner runtime;
-
-
- JMenuItem exportAppItem;
- JMenuItem saveMenuItem;
- JMenuItem saveAsMenuItem;
-
- JMenuItem burnBootloader8Item = null;
- JMenuItem burnBootloader8ParallelItem = null;
- JMenuItem burnBootloader168DiecimilaItem = null;
- JMenuItem burnBootloader168DiecimilaParallelItem = null;
- JMenuItem burnBootloader168NGItem = null;
- JMenuItem burnBootloader168NGParallelItem = null;
-
- JMenu serialMenu;
- JMenu serialRateMenu;
- JMenu mcuMenu;
-
- SerialMenuListener serialMenuListener;
-
- boolean running;
- boolean presenting;
- boolean debugging;
-
- // undo fellers
- JMenuItem undoItem, redoItem;
- protected UndoAction undoAction;
- protected RedoAction redoAction;
- UndoManager undo;
- // used internally, and only briefly
- CompoundEdit compoundEdit;
-
- //
-
- //SketchHistory history; // TODO re-enable history
- Sketchbook sketchbook;
- //Preferences preferences;
- FindReplace find;
-
- //static Properties keywords; // keyword -> reference html lookup
-
-
- public Editor() {
- super(WINDOW_TITLE);
-
- // #@$*(@#$ apple.. always gotta think different
- MRJApplicationUtils.registerAboutHandler(this);
- MRJApplicationUtils.registerPrefsHandler(this);
- MRJApplicationUtils.registerQuitHandler(this);
- MRJApplicationUtils.registerOpenDocumentHandler(this);
-
- // run static initialization that grabs all the prefs
- Preferences.init();
-
- // set the window icon
- try {
- icon = Base.getImage("icon.gif", this);
- setIconImage(icon);
- } catch (Exception e) { } // fail silently, no big whup
-
-
- // add listener to handle window close box hit event
- addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- handleQuitInternal();
- }
- });
- // don't close the window when clicked, the app will take care
- // of that via the handleQuitInternal() methods
- // http://dev.processing.org/bugs/show_bug.cgi?id=440
- setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
-
- PdeKeywords keywords = new PdeKeywords();
- sketchbook = new Sketchbook(this);
-
- JMenuBar menubar = new JMenuBar();
- menubar.add(buildFileMenu());
- menubar.add(buildEditMenu());
- menubar.add(buildSketchMenu());
- menubar.add(buildToolsMenu());
- // what platform has their help menu way on the right? motif?
- //menubar.add(Box.createHorizontalGlue());
- menubar.add(buildHelpMenu());
-
- setJMenuBar(menubar);
-
- // doesn't matter when this is created, just make it happen at some point
- //find = new FindReplace(Editor.this);
-
- //Container pain = getContentPane();
- //pain.setLayout(new BorderLayout());
- // for rev 0120, placing things inside a JPanel because
- Container contentPain = getContentPane();
- contentPain.setLayout(new BorderLayout());
- JPanel pain = new JPanel();
- pain.setLayout(new BorderLayout());
- contentPain.add(pain, BorderLayout.CENTER);
-
- Box box = Box.createVerticalBox();
- Box upper = Box.createVerticalBox();
-
- buttons = new EditorButtons(this);
- upper.add(buttons);
-
- header = new EditorHeader(this);
- //header.setBorder(null);
- upper.add(header);
-
- textarea = new JEditTextArea(new PdeTextAreaDefaults());
- textarea.setRightClickPopup(new TextAreaPopup());
- //textarea.setTokenMarker(new PdeKeywords());
- textarea.setHorizontalOffset(6);
-
- // assemble console panel, consisting of status area and the console itself
- consolePanel = new JPanel();
- consolePanel.setLayout(new BorderLayout());
-
- status = new EditorStatus(this);
- consolePanel.add(status, BorderLayout.NORTH);
-
- console = new EditorConsole(this);
- // windows puts an ugly border on this guy
- console.setBorder(null);
- consolePanel.add(console, BorderLayout.CENTER);
-
- lineStatus = new EditorLineStatus(textarea);
- consolePanel.add(lineStatus, BorderLayout.SOUTH);
-
- upper.add(textarea);
- splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
- upper, consolePanel);
- //textarea, consolePanel);
-
- splitPane.setOneTouchExpandable(true);
- // repaint child panes while resizing
- splitPane.setContinuousLayout(true);
- // if window increases in size, give all of increase to
- // the textarea in the uppper pane
- splitPane.setResizeWeight(1D);
-
- // to fix ugliness.. normally macosx java 1.3 puts an
- // ugly white border around this object, so turn it off.
- splitPane.setBorder(null);
-
- // the default size on windows is too small and kinda ugly
- int dividerSize = Preferences.getInteger("editor.divider.size");
- if (dividerSize != 0) {
- splitPane.setDividerSize(dividerSize);
- }
-
- splitPane.setMinimumSize(new Dimension(600, 600));
- box.add(splitPane);
-
- // hopefully these are no longer needed w/ swing
- // (har har har.. that was wishful thinking)
- listener = new EditorListener(this, textarea);
- pain.add(box);
-
- pain.setTransferHandler(new TransferHandler() {
-
- public boolean canImport(JComponent dest, DataFlavor[] flavors) {
- // claim that we can import everything
- return true;
- }
-
- public boolean importData(JComponent src, Transferable transferable) {
- DataFlavor[] flavors = transferable.getTransferDataFlavors();
-
- /*
- DropTarget dt = new DropTarget(this, new DropTargetListener() {
-
- public void dragEnter(DropTargetDragEvent event) {
- // debug messages for diagnostics
- //System.out.println("dragEnter " + event);
- event.acceptDrag(DnDConstants.ACTION_COPY);
- }
-
- public void dragExit(DropTargetEvent event) {
- //System.out.println("dragExit " + event);
- }
-
- public void dragOver(DropTargetDragEvent event) {
- //System.out.println("dragOver " + event);
- event.acceptDrag(DnDConstants.ACTION_COPY);
- }
-
- public void dropActionChanged(DropTargetDragEvent event) {
- //System.out.println("dropActionChanged " + event);
- }
-
- public void drop(DropTargetDropEvent event) {
- //System.out.println("drop " + event);
- event.acceptDrop(DnDConstants.ACTION_COPY);
-
- Transferable transferable = event.getTransferable();
- DataFlavor flavors[] = transferable.getTransferDataFlavors();
- */
- int successful = 0;
-
- for (int i = 0; i < flavors.length; i++) {
- try {
- //System.out.println(flavors[i]);
- //System.out.println(transferable.getTransferData(flavors[i]));
- Object stuff = transferable.getTransferData(flavors[i]);
- if (!(stuff instanceof java.util.List)) continue;
- java.util.List list = (java.util.List) stuff;
-
- for (int j = 0; j < list.size(); j++) {
- Object item = list.get(j);
- if (item instanceof File) {
- File file = (File) item;
-
- // see if this is a .pde file to be opened
- String filename = file.getName();
- if (filename.endsWith(".pde")) {
- String name = filename.substring(0, filename.length() - 4);
- File parent = file.getParentFile();
- if (name.equals(parent.getName())) {
- handleOpenFile(file);
- return true;
- }
- }
-
- if (sketch.addFile(file)) {
- successful++;
- }
- }
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
-
- if (successful == 0) {
- error("No files were added to the sketch.");
-
- } else if (successful == 1) {
- message("One file added to the sketch.");
-
- } else {
- message(successful + " files added to the sketch.");
- }
- return true;
- }
- });
- }
-
-
- /**
- * Hack for #@#)$(* Mac OS X 10.2.
- *
- * This appears to only be required on OS X 10.2, and is not
- * even being called on later versions of OS X or Windows.
- */
- public Dimension getMinimumSize() {
- //System.out.println("getting minimum size");
- return new Dimension(500, 550);
- }
-
-
- // ...................................................................
-
- /**
- * Builds any unbuilt buildable libraries
- * Adds syntax coloring from those libraries (if exists)
- * Rebuilds sketchbook menu with library examples (if they exist)
- */
- public void prepareLibraries() {
- // build any unbuilt libraries
- try {
- LibraryManager libraryManager = new LibraryManager();
- libraryManager.buildAllUnbuilt();
- // update syntax coloring table
- libraryManager.addSyntaxColoring(new PdeKeywords());
- } catch (RunnerException re) {
- message("Error compiling library ...");
- error(re);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- // update sketchbook menu, this adds examples of any built libs
- sketchbook.rebuildMenus();
- }
-
- // ...................................................................
-
- /**
- * Post-constructor setup for the editor area. Loads the last
- * sketch that was used (if any), and restores other Editor settings.
- * The complement to "storePreferences", this is called when the
- * application is first launched.
- */
- public void restorePreferences() {
- // figure out window placement
-
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- boolean windowPositionValid = true;
-
- if (Preferences.get("last.screen.height") != null) {
- // if screen size has changed, the window coordinates no longer
- // make sense, so don't use them unless they're identical
- int screenW = Preferences.getInteger("last.screen.width");
- int screenH = Preferences.getInteger("last.screen.height");
-
- if ((screen.width != screenW) || (screen.height != screenH)) {
- windowPositionValid = false;
- }
- int windowX = Preferences.getInteger("last.window.x");
- int windowY = Preferences.getInteger("last.window.y");
- if ((windowX < 0) || (windowY < 0) ||
- (windowX > screenW) || (windowY > screenH)) {
- windowPositionValid = false;
- }
-
- } else {
- windowPositionValid = false;
- }
-
- if (!windowPositionValid) {
- //System.out.println("using default size");
- int windowH = Preferences.getInteger("default.window.height");
- int windowW = Preferences.getInteger("default.window.width");
- setBounds((screen.width - windowW) / 2,
- (screen.height - windowH) / 2,
- windowW, windowH);
- // this will be invalid as well, so grab the new value
- Preferences.setInteger("last.divider.location",
- splitPane.getDividerLocation());
- } else {
- setBounds(Preferences.getInteger("last.window.x"),
- Preferences.getInteger("last.window.y"),
- Preferences.getInteger("last.window.width"),
- Preferences.getInteger("last.window.height"));
- }
-
-
- // last sketch that was in use, or used to launch the app
-
- if (Base.openedAtStartup != null) {
- handleOpen2(Base.openedAtStartup);
-
- } else {
- //String sketchName = Preferences.get("last.sketch.name");
- String sketchPath = Preferences.get("last.sketch.path");
- //Sketch sketchTemp = new Sketch(sketchPath);
-
- if ((sketchPath != null) && (new File(sketchPath)).exists()) {
- // don't check modified because nothing is open yet
- handleOpen2(sketchPath);
-
- } else {
- handleNew2(true);
- }
- }
-
-
- // location for the console/editor area divider
-
- int location = Preferences.getInteger("last.divider.location");
- splitPane.setDividerLocation(location);
-
-
- // read the preferences that are settable in the preferences window
-
- applyPreferences();
- }
-
-
- /**
- * Read and apply new values from the preferences, either because
- * the app is just starting up, or the user just finished messing
- * with things in the Preferences window.
- */
- public void applyPreferences() {
-
- // apply the setting for 'use external editor'
- boolean external = Preferences.getBoolean("editor.external");
-
- textarea.setEditable(!external);
- saveMenuItem.setEnabled(!external);
- saveAsMenuItem.setEnabled(!external);
- //beautifyMenuItem.setEnabled(!external);
-
- TextAreaPainter painter = textarea.getPainter();
- if (external) {
- // disable line highlight and turn off the caret when disabling
- Color color = Preferences.getColor("editor.external.bgcolor");
- painter.setBackground(color);
- painter.setLineHighlightEnabled(false);
- textarea.setCaretVisible(false);
-
- } else {
- Color color = Preferences.getColor("editor.bgcolor");
- painter.setBackground(color);
- boolean highlight = Preferences.getBoolean("editor.linehighlight");
- painter.setLineHighlightEnabled(highlight);
- textarea.setCaretVisible(true);
- }
-
- // apply changes to the font size for the editor
- //TextAreaPainter painter = textarea.getPainter();
- painter.setFont(Preferences.getFont("editor.font"));
- //Font font = painter.getFont();
- //textarea.getPainter().setFont(new Font("Courier", Font.PLAIN, 36));
-
- // in case tab expansion stuff has changed
- listener.applyPreferences();
-
- // in case moved to a new location
- // For 0125, changing to async version (to be implemented later)
- //sketchbook.rebuildMenus();
- sketchbook.rebuildMenusAsync();
- }
-
-
- /**
- * Store preferences about the editor's current state.
- * Called when the application is quitting.
- */
- public void storePreferences() {
- //System.out.println("storing preferences");
-
- // window location information
- Rectangle bounds = getBounds();
- Preferences.setInteger("last.window.x", bounds.x);
- Preferences.setInteger("last.window.y", bounds.y);
- Preferences.setInteger("last.window.width", bounds.width);
- Preferences.setInteger("last.window.height", bounds.height);
-
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- Preferences.setInteger("last.screen.width", screen.width);
- Preferences.setInteger("last.screen.height", screen.height);
-
- // last sketch that was in use
- //Preferences.set("last.sketch.name", sketchName);
- //Preferences.set("last.sketch.name", sketch.name);
- Preferences.set("last.sketch.path", sketch.getMainFilePath());
-
- // location for the console/editor area divider
- int location = splitPane.getDividerLocation();
- Preferences.setInteger("last.divider.location", location);
- }
-
-
- // ...................................................................
-
-
- protected JMenu buildFileMenu() {
- JMenuItem item;
- JMenu menu = new JMenu("File");
-
- item = newJMenuItem("New", 'N');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleNew(false);
- }
- });
- menu.add(item);
- menu.add(sketchbook.getOpenMenu());
-
- saveMenuItem = newJMenuItem("Save", 'S');
- saveMenuItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleSave(false);
- }
- });
- menu.add(saveMenuItem);
-
- saveAsMenuItem = newJMenuItem("Save As...", 'S', true);
- saveAsMenuItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleSaveAs();
- }
- });
- menu.add(saveAsMenuItem);
-
- item = newJMenuItem("Upload to I/O Board", 'U');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleExport();
- }
- });
- menu.add(item);
-
- /*exportAppItem = newJMenuItem("Export Application", 'E', true);
- exportAppItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- //buttons.activate(EditorButtons.EXPORT);
- //SwingUtilities.invokeLater(new Runnable() {
- //public void run() {
- handleExportApplication();
- //}});
- }
- });
- menu.add(exportAppItem);
- */
- menu.addSeparator();
-
- item = newJMenuItem("Page Setup", 'P', true);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handlePageSetup();
- }
- });
- menu.add(item);
-
- item = newJMenuItem("Print", 'P');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handlePrint();
- }
- });
- menu.add(item);
-
- // macosx already has its own preferences and quit menu
- if (!Base.isMacOS()) {
- menu.addSeparator();
-
- item = newJMenuItem("Preferences", ',');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handlePrefs();
- }
- });
- menu.add(item);
-
- menu.addSeparator();
-
- item = newJMenuItem("Quit", 'Q');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleQuitInternal();
- }
- });
- menu.add(item);
- }
- return menu;
- }
-
-
- protected JMenu buildSketchMenu() {
- JMenuItem item;
- JMenu menu = new JMenu("Sketch");
-
- item = newJMenuItem("Verify/Compile", 'R');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleRun(false);
- }
- });
- menu.add(item);
-
- /*item = newJMenuItem("Present", 'R', true);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleRun(true);
- }
- });
- menu.add(item);
- */
- item = new JMenuItem("Stop");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleStop();
- }
- });
- menu.add(item);
-
- menu.addSeparator();
-
- menu.add(sketchbook.getImportMenu());
-
- //if (Base.isWindows() || Base.isMacOS()) {
- // no way to do an 'open in file browser' on other platforms
- // since there isn't any sort of standard
- item = newJMenuItem("Show Sketch Folder", 'K', false);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- //Base.openFolder(sketchDir);
- Base.openFolder(sketch.folder);
- }
- });
- menu.add(item);
- if (!Base.openFolderAvailable()) {
- item.setEnabled(false);
- }
-
- //menu.addSeparator();
-
- item = new JMenuItem("Add File...");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- sketch.addFile();
- }
- });
- menu.add(item);
-
- // TODO re-enable history
- //history.attachMenu(menu);
- return menu;
- }
-
-
- protected JMenu buildToolsMenu() {
- JMenuItem item;
- JMenuItem rbMenuItem;
- JMenuItem cbMenuItem;
-
- serialMenuListener = new SerialMenuListener();
-
- JMenu menu = new JMenu("Tools");
-
- item = newJMenuItem("Auto Format", 'T', false);
- item.addActionListener(new ActionListener() {
- synchronized public void actionPerformed(ActionEvent e) {
- new AutoFormat(Editor.this).show();
-
- /*
- Jalopy jalopy = new Jalopy();
- jalopy.setInput(getText(), sketch.current.file.getAbsolutePath());
- StringBuffer buffer = new StringBuffer();
- jalopy.setOutput(buffer);
- jalopy.setInspect(false);
- jalopy.format();
- setText(buffer.toString(), 0, 0);
-
- if (jalopy.getState() == Jalopy.State.OK)
- System.out.println("successfully formatted");
- else if (jalopy.getState() == Jalopy.State.WARN)
- System.out.println(" formatted with warnings");
- else if (jalopy.getState() == Jalopy.State.ERROR)
- System.out.println(" could not be formatted");
- */
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Copy for Forum");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- new DiscourseFormat(Editor.this, false).show();
- }
- });
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Copy as HTML");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- new DiscourseFormat(Editor.this, true).show();
- }
- });
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Archive Sketch");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- new Archiver(Editor.this).show();
- //Archiver archiver = new Archiver();
- //archiver.setup(Editor.this);
- //archiver.show();
- }
- });
- menu.add(item);
-
- /*
- item = new JMenuItem("Export Folder...");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- new ExportFolder(Editor.this).show();
- }
- });
- menu.add(item);
- */
- menu.addSeparator();
-
- JMenu boardsMenu = new JMenu("Board");
- ButtonGroup boardGroup = new ButtonGroup();
- for (Iterator i = Preferences.getSubKeys("boards"); i.hasNext(); ) {
- String board = (String) i.next();
- Action action = new BoardMenuAction(board);
- item = new JRadioButtonMenuItem(action);
- if (board.equals(Preferences.get("board")))
- item.setSelected(true);
- boardGroup.add(item);
- boardsMenu.add(item);
- }
- menu.add(boardsMenu);
-
- serialMenu = new JMenu("Serial Port");
- populateSerialMenu();
- menu.add(serialMenu);
-
- menu.addSeparator();
-
- JMenu bootloaderMenu = new JMenu("Burn Bootloader");
- for (Iterator i = Preferences.getSubKeys("programmers"); i.hasNext(); ) {
- String programmer = (String) i.next();
- Action action = new BootloaderMenuAction(programmer);
- item = new JMenuItem(action);
- bootloaderMenu.add(item);
- }
- menu.add(bootloaderMenu);
-
- menu.addMenuListener(new MenuListener() {
- public void menuCanceled(MenuEvent e) {}
- public void menuDeselected(MenuEvent e) {}
- public void menuSelected(MenuEvent e) {
- //System.out.println("Tools menu selected.");
- populateSerialMenu();
- }
- });
-
-
- return menu;
- }
-
- class SerialMenuListener implements ActionListener {
- //public SerialMenuListener() { }
-
- public void actionPerformed(ActionEvent e) {
- if(serialMenu == null) {
- System.out.println("serialMenu is null");
- return;
- }
- int count = serialMenu.getItemCount();
- for (int i = 0; i < count; i++) {
- ((JCheckBoxMenuItem)serialMenu.getItem(i)).setState(false);
- }
- JCheckBoxMenuItem item = (JCheckBoxMenuItem)e.getSource();
- item.setState(true);
- String name = item.getText();
- //System.out.println(item.getLabel());
- Preferences.set("serial.port", name);
- //System.out.println("set to " + get("serial.port"));
- }
-
- /*
- public void actionPerformed(ActionEvent e) {
- System.out.println(e.getSource());
- String name = e.getActionCommand();
- PdeBase.properties.put("serial.port", name);
- System.out.println("set to " + get("serial.port"));
- //editor.skOpen(path + File.separator + name, name);
- // need to push "serial.port" into PdeBase.properties
- }
- */
- }
-
- class BoardMenuAction extends AbstractAction {
- private String board;
- public BoardMenuAction(String board) {
- super(Preferences.get("boards." + board + ".name"));
- this.board = board;
- }
- public void actionPerformed(ActionEvent actionevent) {
- //System.out.println("Switching to " + board);
- Preferences.set("board", board);
- try {
- LibraryManager libraryManager = new LibraryManager();
- libraryManager.rebuildAllBuilt();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (RunnerException e) {
- message("Error rebuilding libraries...");
- error(e);
- }
- }
- }
-
- class BootloaderMenuAction extends AbstractAction {
- private String programmer;
- public BootloaderMenuAction(String programmer) {
- super("w/ " + Preferences.get("programmers." + programmer + ".name"));
- this.programmer = programmer;
- }
- public void actionPerformed(ActionEvent actionevent) {
- handleBurnBootloader(programmer);
- }
- }
-
- protected void populateSerialMenu() {
- // getting list of ports
-
- JMenuItem rbMenuItem;
-
- //System.out.println("Clearing serial port menu.");
-
- serialMenu.removeAll();
- boolean empty = true;
-
- try
- {
- for (Enumeration enumeration = CommPortIdentifier.getPortIdentifiers(); enumeration.hasMoreElements();)
- {
- CommPortIdentifier commportidentifier = (CommPortIdentifier)enumeration.nextElement();
- //System.out.println("Found communication port: " + commportidentifier);
- if (commportidentifier.getPortType() == CommPortIdentifier.PORT_SERIAL)
- {
- //System.out.println("Adding port to serial port menu: " + commportidentifier);
- String curr_port = commportidentifier.getName();
- rbMenuItem = new JCheckBoxMenuItem(curr_port, curr_port.equals(Preferences.get("serial.port")));
- rbMenuItem.addActionListener(serialMenuListener);
- //serialGroup.add(rbMenuItem);
- serialMenu.add(rbMenuItem);
- empty = false;
- }
- }
- if (!empty) {
- //System.out.println("enabling the serialMenu");
- serialMenu.setEnabled(true);
- }
-
- }
-
- catch (Exception exception)
- {
- System.out.println("error retrieving port list");
- exception.printStackTrace();
- }
-
- if (serialMenu.getItemCount() == 0) {
- serialMenu.setEnabled(false);
- }
-
- //serialMenu.addSeparator();
- //serialMenu.add(item);
- }
-
- protected JMenu buildHelpMenu() {
- JMenu menu = new JMenu("Help");
- JMenuItem item;
-
- if (!Base.isLinux()) {
- item = new JMenuItem("Getting Started");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (Base.isWindows())
- Base.openURL(System.getProperty("user.dir") + File.separator +
- "reference" + File.separator + "Guide_Windows.html");
- else
- Base.openURL(System.getProperty("user.dir") + File.separator +
- "reference" + File.separator + "Guide_MacOSX.html");
- }
- });
- menu.add(item);
- }
-
- item = new JMenuItem("Environment");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Base.showEnvironment();
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Troubleshooting");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Base.showTroubleshooting();
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Reference");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Base.showReference();
- }
- });
- menu.add(item);
-
- item = newJMenuItem("Find in Reference", 'F', true);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (textarea.isSelectionActive()) {
- handleReference();
- }
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Frequently Asked Questions");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Base.showFAQ();
- }
- });
- menu.add(item);
-
- item = newJMenuItem("Visit www.arduino.cc", '5');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Base.openURL("http://www.arduino.cc/");
- }
- });
- menu.add(item);
-
- // macosx already has its own about menu
- if (!Base.isMacOS()) {
- menu.addSeparator();
- item = new JMenuItem("About Arduino");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- handleAbout();
- }
- });
- menu.add(item);
- }
-
- return menu;
- }
-
-
- public JMenu buildEditMenu() {
- JMenu menu = new JMenu("Edit");
- JMenuItem item;
-
- undoItem = newJMenuItem("Undo", 'Z');
- undoItem.addActionListener(undoAction = new UndoAction());
- menu.add(undoItem);
-
- redoItem = newJMenuItem("Redo", 'Y');
- redoItem.addActionListener(redoAction = new RedoAction());
- menu.add(redoItem);
-
- menu.addSeparator();
-
- // TODO "cut" and "copy" should really only be enabled
- // if some text is currently selected
- item = newJMenuItem("Cut", 'X');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.cut();
- sketch.setModified(true);
- }
- });
- menu.add(item);
-
- item = newJMenuItem("Copy", 'C');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.copy();
- }
- });
- menu.add(item);
-
- item = newJMenuItem("Paste", 'V');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.paste();
- sketch.setModified(true);
- }
- });
- menu.add(item);
-
- item = newJMenuItem("Select All", 'A');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.selectAll();
- }
- });
- menu.add(item);
-
- menu.addSeparator();
-
- item = newJMenuItem("Find...", 'F');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (find == null) {
- find = new FindReplace(Editor.this);
- }
- //new FindReplace(Editor.this).show();
- find.show();
- //find.setVisible(true);
- }
- });
- menu.add(item);
-
- // TODO find next should only be enabled after a
- // search has actually taken place
- item = newJMenuItem("Find Next", 'G');
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (find != null) {
- //find.find(true);
- //FindReplace find = new FindReplace(Editor.this); //.show();
- find.find(true);
- }
- }
- });
- menu.add(item);
-
- return menu;
- }
-
-
- /**
- * Convenience method, see below.
- */
- static public JMenuItem newJMenuItem(String title, int what) {
- return newJMenuItem(title, what, false);
- }
-
-
- /**
- * A software engineer, somewhere, needs to have his abstraction
- * taken away. In some countries they jail or beat people for writing
- * the sort of API that would require a five line helper function
- * just to set the command key for a menu item.
- */
- static public JMenuItem newJMenuItem(String title,
- int what, boolean shift) {
- JMenuItem menuItem = new JMenuItem(title);
- int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- if (shift) modifiers |= ActionEvent.SHIFT_MASK;
- menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers));
- return menuItem;
- }
-
-
- // ...................................................................
-
-
- class UndoAction extends AbstractAction {
- public UndoAction() {
- super("Undo");
- this.setEnabled(false);
- }
-
- public void actionPerformed(ActionEvent e) {
- try {
- undo.undo();
- } catch (CannotUndoException ex) {
- //System.out.println("Unable to undo: " + ex);
- //ex.printStackTrace();
- }
- updateUndoState();
- redoAction.updateRedoState();
- }
-
- protected void updateUndoState() {
- if (undo.canUndo()) {
- this.setEnabled(true);
- undoItem.setEnabled(true);
- undoItem.setText(undo.getUndoPresentationName());
- putValue(Action.NAME, undo.getUndoPresentationName());
- if (sketch != null) {
- sketch.setModified(true); // 0107
- }
- } else {
- this.setEnabled(false);
- undoItem.setEnabled(false);
- undoItem.setText("Undo");
- putValue(Action.NAME, "Undo");
- if (sketch != null) {
- sketch.setModified(false); // 0107
- }
- }
- }
- }
-
-
- class RedoAction extends AbstractAction {
- public RedoAction() {
- super("Redo");
- this.setEnabled(false);
- }
-
- public void actionPerformed(ActionEvent e) {
- try {
- undo.redo();
- } catch (CannotRedoException ex) {
- //System.out.println("Unable to redo: " + ex);
- //ex.printStackTrace();
- }
- updateRedoState();
- undoAction.updateUndoState();
- }
-
- protected void updateRedoState() {
- if (undo.canRedo()) {
- redoItem.setEnabled(true);
- redoItem.setText(undo.getRedoPresentationName());
- putValue(Action.NAME, undo.getRedoPresentationName());
- } else {
- this.setEnabled(false);
- redoItem.setEnabled(false);
- redoItem.setText("Redo");
- putValue(Action.NAME, "Redo");
- }
- }
- }
-
-
- // ...................................................................
-
-
- // interfaces for MRJ Handlers, but naming is fine
- // so used internally for everything else
-
- public void handleAbout() {
- final Image image = Base.getImage("about.jpg", this);
- int w = image.getWidth(this);
- int h = image.getHeight(this);
- final Window window = new Window(this) {
- public void paint(Graphics g) {
- g.drawImage(image, 0, 0, null);
-
- Graphics2D g2 = (Graphics2D) g;
- g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-
- g.setFont(new Font("SansSerif", Font.PLAIN, 11));
- g.setColor(Color.white);
- g.drawString(Base.VERSION_NAME, 50, 30);
- }
- };
- window.addMouseListener(new MouseAdapter() {
- public void mousePressed(MouseEvent e) {
- window.dispose();
- }
- });
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- window.setBounds((screen.width-w)/2, (screen.height-h)/2, w, h);
- window.show();
- }
-
-
- /**
- * Show the preferences window.
- */
- public void handlePrefs() {
- Preferences preferences = new Preferences();
- preferences.showFrame(this);
-
- // since this can't actually block, it'll hide
- // the editor window while the prefs are open
- //preferences.showFrame(this);
- // and then call applyPreferences if 'ok' is hit
- // and then unhide
-
- // may need to rebuild sketch and other menus
- //applyPreferences();
-
- // next have editor do its thing
- //editor.appyPreferences();
- }
-
-
- // ...................................................................
-
-
- /**
- * Get the contents of the current buffer. Used by the Sketch class.
- */
- public String getText() {
- return textarea.getText();
- }
-
-
- /**
- * Called to update the text but not switch to a different
- * set of code (which would affect the undo manager).
- */
- public void setText(String what, int selectionStart, int selectionEnd) {
- beginCompoundEdit();
- textarea.setText(what);
- endCompoundEdit();
-
- // make sure that a tool isn't asking for a bad location
- selectionStart =
- Math.max(0, Math.min(selectionStart, textarea.getDocumentLength()));
- selectionEnd =
- Math.max(0, Math.min(selectionStart, textarea.getDocumentLength()));
- textarea.select(selectionStart, selectionEnd);
-
- textarea.requestFocus(); // get the caret blinking
- }
-
-
- /**
- * Switch between tabs, this swaps out the Document object
- * that's currently being manipulated.
- */
- public void setCode(SketchCode code) {
- if (code.document == null) { // this document not yet inited
- code.document = new SyntaxDocument();
-
- // turn on syntax highlighting
- code.document.setTokenMarker(new PdeKeywords());
-
- // insert the program text into the document object
- try {
- code.document.insertString(0, code.program, null);
- } catch (BadLocationException bl) {
- bl.printStackTrace();
- }
-
- // set up this guy's own undo manager
- code.undo = new UndoManager();
-
- // connect the undo listener to the editor
- code.document.addUndoableEditListener(new UndoableEditListener() {
- public void undoableEditHappened(UndoableEditEvent e) {
- if (compoundEdit != null) {
- compoundEdit.addEdit(e.getEdit());
-
- } else if (undo != null) {
- undo.addEdit(e.getEdit());
- undoAction.updateUndoState();
- redoAction.updateRedoState();
- }
- }
- });
- }
-
- // update the document object that's in use
- textarea.setDocument(code.document,
- code.selectionStart, code.selectionStop,
- code.scrollPosition);
-
- textarea.requestFocus(); // get the caret blinking
-
- this.undo = code.undo;
- undoAction.updateUndoState();
- redoAction.updateRedoState();
- }
-
-
- public void beginCompoundEdit() {
- compoundEdit = new CompoundEdit();
- }
-
-
- public void endCompoundEdit() {
- compoundEdit.end();
- undo.addEdit(compoundEdit);
- undoAction.updateUndoState();
- redoAction.updateRedoState();
- compoundEdit = null;
- }
-
-
- // ...................................................................
-
-
- public void handleRun(final boolean present) {
- doClose();
- running = true;
- buttons.activate(EditorButtons.RUN);
- message("Compiling...");
- // do this for the terminal window / dos prompt / etc
- for (int i = 0; i < 10; i++) System.out.println();
-
- // clear the console on each run, unless the user doesn't want to
- //if (Base.getBoolean("console.auto_clear", true)) {
- //if (Preferences.getBoolean("console.auto_clear", true)) {
- if (Preferences.getBoolean("console.auto_clear")) {
- console.clear();
- }
-
- presenting = present;
- if (presenting && Base.isMacOS()) {
- // check to see if osx 10.2, if so, show a warning
- String osver = System.getProperty("os.version").substring(0, 4);
- if (osver.equals("10.2")) {
- Base.showWarning("Time for an OS Upgrade",
- "The \"Present\" feature may not be available on\n" +
- "Mac OS X 10.2, because of what appears to be\n" +
- "a bug in the Java 1.4 implementation on 10.2.\n" +
- "In case it works on your machine, present mode\n" +
- "will start, but if you get a flickering white\n" +
- "window, using Command-Q to quit the sketch", null);
- }
- }
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- try {
- if (!sketch.handleRun(new Target(
- System.getProperty("user.dir") + File.separator + "hardware" +
- File.separator + "cores",
- Preferences.get("boards." + Preferences.get("board") + ".build.core"))))
- return;
-
- //runtime = new Runner(sketch, Editor.this);
- //runtime.start(appletLocation);
- watcher = new RunButtonWatcher();
- message("Done compiling.");
- if(watcher != null) watcher.stop();
-
- } catch (RunnerException e) {
- message("Error compiling...");
- error(e);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }});
-
- // this doesn't seem to help much or at all
- /*
- final SwingWorker worker = new SwingWorker() {
- public Object construct() {
- try {
- if (!sketch.handleRun()) return null;
-
- runtime = new Runner(sketch, Editor.this);
- runtime.start(presenting ? presentLocation : appletLocation);
- watcher = new RunButtonWatcher();
- message("Done compiling.");
-
- } catch (RunnerException e) {
- message("Error compiling...");
- error(e);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null; // needn't return anything
- }
- };
- worker.start();
- */
- //sketch.cleanup(); // where does this go?
- buttons.clear();
- }
-
-
- class RunButtonWatcher implements Runnable {
- Thread thread;
-
- public RunButtonWatcher() {
- thread = new Thread(this, "run button watcher");
- thread.setPriority(Thread.MIN_PRIORITY);
- thread.start();
- }
-
- public void run() {
- while (Thread.currentThread() == thread) {
- /*if (runtime == null) {
- stop();
-
- } else {
- if (runtime.applet != null) {
- if (runtime.applet.finished) {
- stop();
- }
- //buttons.running(!runtime.applet.finished);
-
- } else if (runtime.process != null) {
- //buttons.running(true); // ??
-
- } else {
- stop();
- }
- }*/
- try {
- Thread.sleep(250);
- } catch (InterruptedException e) { }
- //System.out.println("still inside runner thread");
- }
- }
-
- public void stop() {
- buttons.running(false);
- thread = null;
- }
- }
-
-
- public void handleSerial() {
- if (!debugging) {
- try {
- serialPort = new Serial(true);
- console.clear();
- buttons.activate(EditorButtons.SERIAL);
- debugging = true;
- status.serial();
- } catch(SerialException e) {
- error(e);
- }
- } else {
- doStop();
- }
- }
-
-
- public void handleStop() { // called by menu or buttons
- if (presenting) {
- doClose();
- } else {
- doStop();
- }
- buttons.clear();
- }
-
-
- /**
- * Stop the applet but don't kill its window.
- */
- public void doStop() {
- //if (runtime != null) runtime.stop();
- if (debugging) {
- status.unserial();
- serialPort.dispose();
- debugging = false;
- }
- if (watcher != null) watcher.stop();
- message(EMPTY);
-
- // the buttons are sometimes still null during the constructor
- // is this still true? are people still hitting this error?
- /*if (buttons != null)*/ buttons.clear();
-
- running = false;
- }
-
-
- /**
- * Stop the applet and kill its window. When running in presentation
- * mode, this will always be called instead of doStop().
- */
- public void doClose() {
- //if (presenting) {
- //presentationWindow.hide();
- //} else {
- //try {
- // the window will also be null the process was running
- // externally. so don't even try setting if window is null
- // since Runner will set the appletLocation when an
- // external process is in use.
-// if (runtime.window != null) {
-// appletLocation = runtime.window.getLocation();
-// }
- //} catch (NullPointerException e) { }
- //}
-
- //if (running) doStop();
- doStop(); // need to stop if runtime error
-
- //try {
- /*if (runtime != null) {
- runtime.close(); // kills the window
- runtime = null; // will this help?
- }*/
- //} catch (Exception e) { }
- //buttons.clear(); // done by doStop
-
- sketch.cleanup();
-
- // [toxi 030903]
- // focus the PDE again after quitting presentation mode
- toFront();
- }
-
-
- /**
- * Check to see if there have been changes. If so, prompt user
- * whether or not to save first. If the user cancels, just ignore.
- * Otherwise, one of the other methods will handle calling
- * checkModified2() which will get on with business.
- */
- protected void checkModified(int checkModifiedMode) {
- this.checkModifiedMode = checkModifiedMode;
-
- if (!sketch.modified) {
- checkModified2();
- return;
- }
-
- String prompt = "Save changes to " + sketch.name + "? ";
-
- if (checkModifiedMode != HANDLE_QUIT) {
- // if the user is not quitting, then use simpler nicer
- // dialog that's actually inside the p5 window.
- status.prompt(prompt);
-
- } else {
- if (!Base.isMacOS() || PApplet.javaVersion < 1.5f) {
- int result =
- JOptionPane.showConfirmDialog(this, prompt, "Quit",
- JOptionPane.YES_NO_CANCEL_OPTION,
- JOptionPane.QUESTION_MESSAGE);
-
- if (result == JOptionPane.YES_OPTION) {
- handleSave(true);
- checkModified2();
-
- } else if (result == JOptionPane.NO_OPTION) {
- checkModified2();
- }
- // cancel is ignored altogether
-
- } else {
- // This code is disabled unless Java 1.5 is being used on Mac OS X
- // because of a Java bug that prevents the initial value of the
- // dialog from being set properly (at least on my MacBook Pro).
- // The bug causes the "Don't Save" option to be the highlighted,
- // blinking, default. This sucks. But I'll tell you what doesn't
- // suck--workarounds for the Mac and Apple's snobby attitude about it!
-
- // adapted from the quaqua guide
- // http://www.randelshofer.ch/quaqua/guide/joptionpane.html
- JOptionPane pane =
- new JOptionPane(" " +
- " " +
- "Do you want to save changes to this sketch " +
- " before closing?" +
- "
If you don't save, your changes will be lost.",
- JOptionPane.QUESTION_MESSAGE);
-
- String[] options = new String[] {
- "Save", "Cancel", "Don't Save"
- };
- pane.setOptions(options);
-
- // highlight the safest option ala apple hig
- pane.setInitialValue(options[0]);
-
- // on macosx, setting the destructive property places this option
- // away from the others at the lefthand side
- pane.putClientProperty("Quaqua.OptionPane.destructiveOption",
- new Integer(2));
-
- JDialog dialog = pane.createDialog(this, null);
- dialog.show();
-
- Object result = pane.getValue();
- if (result == options[0]) { // save (and quit)
- handleSave(true);
- checkModified2();
-
- } else if (result == options[2]) { // don't save (still quit)
- checkModified2();
- }
- }
- }
- }
-
-
- /**
- * Called by EditorStatus to complete the job and re-dispatch
- * to handleNew, handleOpen, handleQuit.
- */
- public void checkModified2() {
- switch (checkModifiedMode) {
- case HANDLE_NEW: handleNew2(false); break;
- case HANDLE_OPEN: handleOpen2(handleOpenPath); break;
- case HANDLE_QUIT: handleQuit2(); break;
- }
- checkModifiedMode = 0;
- }
-
-
- /**
- * New was called (by buttons or by menu), first check modified
- * and if things work out ok, handleNew2() will be called.
- *
- * If shift is pressed when clicking the toolbar button, then
- * force the opposite behavior from sketchbook.prompt's setting
- */
- public void handleNew(final boolean shift) {
- buttons.activate(EditorButtons.NEW);
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- doStop();
- handleNewShift = shift;
- handleNewLibrary = false;
- checkModified(HANDLE_NEW);
- }});
- }
-
-
- /**
- * Extra public method so that Sketch can call this when a sketch
- * is selected to be deleted, and it won't call checkModified()
- * to prompt for save as.
- */
- public void handleNewUnchecked() {
- doStop();
- handleNewShift = false;
- handleNewLibrary = false;
- handleNew2(true);
- }
-
-
- /**
- * User selected "New Library", this will act just like handleNew
- * but internally set a flag that the new guy is a library,
- * meaning that a "library" subfolder will be added.
- */
- public void handleNewLibrary() {
- doStop();
- handleNewShift = false;
- handleNewLibrary = true;
- checkModified(HANDLE_NEW);
- }
-
-
- /**
- * Does all the plumbing to create a new project
- * then calls handleOpen to load it up.
- *
- * @param noPrompt true to disable prompting for the sketch
- * name, used when the app is starting (auto-create a sketch)
- */
- protected void handleNew2(boolean noPrompt) {
- try {
- String pdePath =
- sketchbook.handleNew(noPrompt, handleNewShift, handleNewLibrary);
- if (pdePath != null) handleOpen2(pdePath);
-
- } catch (IOException e) {
- // not sure why this would happen, but since there's no way to
- // recover (outside of creating another new setkch, which might
- // just cause more trouble), then they've gotta quit.
- Base.showError("Problem creating a new sketch",
- "An error occurred while creating\n" +
- "a new sketch. Arduino must now quit.", e);
- }
- buttons.clear();
- }
-
-
- /**
- * This is the implementation of the MRJ open document event,
- * and the Windows XP open document will be routed through this too.
- */
- public void handleOpenFile(File file) {
- //System.out.println("handling open file: " + file);
- handleOpen(file.getAbsolutePath());
- }
-
-
- /**
- * Open a sketch given the full path to the .pde file.
- * Pass in 'null' to prompt the user for the name of the sketch.
- */
- public void handleOpen(final String ipath) {
- // haven't run across a case where i can verify that this works
- // because open is usually very fast.
- buttons.activate(EditorButtons.OPEN);
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- String path = ipath;
- if (path == null) { // "open..." selected from the menu
- path = sketchbook.handleOpen();
- if (path == null) return;
- }
- doClose();
- handleOpenPath = path;
- checkModified(HANDLE_OPEN);
- }});
- }
-
-
- /**
- * Open a sketch from a particular path, but don't check to save changes.
- * Used by Sketch.saveAs() to re-open a sketch after the "Save As"
- */
- public void handleOpenUnchecked(String path, int codeIndex,
- int selStart, int selStop, int scrollPos) {
- doClose();
- handleOpen2(path);
-
- sketch.setCurrent(codeIndex);
- textarea.select(selStart, selStop);
- //textarea.updateScrollBars();
- textarea.setScrollPosition(scrollPos);
- }
-
-
- /**
- * Second stage of open, occurs after having checked to
- * see if the modifications (if any) to the previous sketch
- * need to be saved.
- */
- protected void handleOpen2(String path) {
- if (sketch != null) {
- // if leaving an empty sketch (i.e. the default) do an
- // auto-clean right away
- try {
- // don't clean if we're re-opening the same file
- String oldPath = sketch.code[0].file.getCanonicalPath();
- String newPath = new File(path).getCanonicalPath();
- if (!oldPath.equals(newPath)) {
- if (Base.calcFolderSize(sketch.folder) == 0) {
- Base.removeDir(sketch.folder);
- //sketchbook.rebuildMenus();
- sketchbook.rebuildMenusAsync();
- }
- }
- } catch (Exception e) { } // oh well
- }
-
- try {
- // check to make sure that this .pde file is
- // in a folder of the same name
- File file = new File(path);
- File parentFile = new File(file.getParent());
- String parentName = parentFile.getName();
- String pdeName = parentName + ".pde";
- File altFile = new File(file.getParent(), pdeName);
-
- //System.out.println("path = " + file.getParent());
- //System.out.println("name = " + file.getName());
- //System.out.println("pname = " + parentName);
-
- if (pdeName.equals(file.getName())) {
- // no beef with this guy
-
- } else if (altFile.exists()) {
- // user selected a .java from the same sketch,
- // but open the .pde instead
- path = altFile.getAbsolutePath();
- //System.out.println("found alt file in same folder");
-
- } else if (!path.endsWith(".pde")) {
- Base.showWarning("Bad file selected",
- "Arduino can only open its own sketches\n" +
- "and other files ending in .pde", null);
- return;
-
- } else {
- String properParent =
- file.getName().substring(0, file.getName().length() - 4);
-
- Object[] options = { "OK", "Cancel" };
- String prompt =
- "The file \"" + file.getName() + "\" needs to be inside\n" +
- "a sketch folder named \"" + properParent + "\".\n" +
- "Create this folder, move the file, and continue?";
-
- int result = JOptionPane.showOptionDialog(this,
- prompt,
- "Moving",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE,
- null,
- options,
- options[0]);
-
- if (result == JOptionPane.YES_OPTION) {
- // create properly named folder
- File properFolder = new File(file.getParent(), properParent);
- if (properFolder.exists()) {
- Base.showWarning("Error",
- "A folder named \"" + properParent + "\" " +
- "already exists. Can't open sketch.", null);
- return;
- }
- if (!properFolder.mkdirs()) {
- throw new IOException("Couldn't create sketch folder");
- }
- // copy the sketch inside
- File properPdeFile = new File(properFolder, file.getName());
- File origPdeFile = new File(path);
- Base.copyFile(origPdeFile, properPdeFile);
-
- // remove the original file, so user doesn't get confused
- origPdeFile.delete();
-
- // update with the new path
- path = properPdeFile.getAbsolutePath();
-
- } else if (result == JOptionPane.NO_OPTION) {
- return;
- }
- }
-
- sketch = new Sketch(this, path);
- // TODO re-enable this once export application works
- //exportAppItem.setEnabled(false);
- //exportAppItem.setEnabled(false && !sketch.isLibrary());
- //buttons.disableRun(sketch.isLibrary());
- header.rebuild();
- if (Preferences.getBoolean("console.auto_clear")) {
- console.clear();
- }
-
- } catch (Exception e) {
- error(e);
- }
- }
-
-
- // there is no handleSave1 since there's never a need to prompt
- /**
- * Actually handle the save command. If 'force' is set to false,
- * this will happen in another thread so that the message area
- * will update and the save button will stay highlighted while the
- * save is happening. If 'force' is true, then it will happen
- * immediately. This is used during a quit, because invokeLater()
- * won't run properly while a quit is happening. This fixes
- * Bug 276.
- */
- public void handleSave(boolean force) {
- doStop();
- buttons.activate(EditorButtons.SAVE);
-
- if (force) {
- handleSave2();
- } else {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- handleSave2();
- }
- });
- }
- }
-
-
- public void handleSave2() {
- message("Saving...");
- try {
- if (sketch.save()) {
- message("Done Saving.");
- } else {
- message(EMPTY);
- }
- // rebuild sketch menu in case a save-as was forced
- // Disabling this for 0125, instead rebuild the menu inside
- // the Save As method of the Sketch object, since that's the
- // only one who knows whether something was renamed.
- //sketchbook.rebuildMenus();
- //sketchbook.rebuildMenusAsync();
-
- } catch (Exception e) {
- // show the error as a message in the window
- error(e);
-
- // zero out the current action,
- // so that checkModified2 will just do nothing
- checkModifiedMode = 0;
- // this is used when another operation calls a save
- }
- buttons.clear();
- }
-
-
- public void handleSaveAs() {
- doStop();
- buttons.activate(EditorButtons.SAVE);
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- message("Saving...");
- try {
- if (sketch.saveAs()) {
- message("Done Saving.");
- // Disabling this for 0125, instead rebuild the menu inside
- // the Save As method of the Sketch object, since that's the
- // only one who knows whether something was renamed.
- //sketchbook.rebuildMenusAsync();
- } else {
- message("Save Cancelled.");
- }
- } catch (Exception e) {
- // show the error as a message in the window
- error(e);
- }
- buttons.clear();
- }});
- }
-
-
- /**
- * Handles calling the export() function on sketch, and
- * queues all the gui status stuff that comes along with it.
- *
- * Made synchronized to (hopefully) avoid problems of people
- * hitting export twice, quickly, and horking things up.
- */
- synchronized public void handleExport() {
- if(debugging)
- doStop();
- buttons.activate(EditorButtons.EXPORT);
- console.clear();
- //String what = sketch.isLibrary() ? "Applet" : "Library";
- //message("Exporting " + what + "...");
- message("Uploading to I/O Board...");
-
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- try {
- //boolean success = sketch.isLibrary() ?
- //sketch.exportLibrary() : sketch.exportApplet();
- boolean success = sketch.exportApplet(new Target(
- System.getProperty("user.dir") + File.separator + "hardware" +
- File.separator + "cores",
- Preferences.get("boards." + Preferences.get("board") + ".build.core")));
- if (success) {
- message("Done uploading.");
- } else {
- // error message will already be visible
- }
- } catch (RunnerException e) {
- message("Error during upload.");
- //e.printStackTrace();
- error(e);
- } catch (Exception e) {
- e.printStackTrace();
- }
- buttons.clear();
- }});
- }
-
-
- synchronized public void handleExportApp() {
- message("Exporting application...");
- try {
- if (sketch.exportApplication()) {
- message("Done exporting.");
- } else {
- // error message will already be visible
- }
- } catch (Exception e) {
- message("Error during export.");
- e.printStackTrace();
- }
- buttons.clear();
- }
-
-
- /**
- * Checks to see if the sketch has been modified, and if so,
- * asks the user to save the sketch or cancel the export.
- * This prevents issues where an incomplete version of the sketch
- * would be exported, and is a fix for
- * Bug 157
- */
- public boolean handleExportCheckModified() {
- if (!sketch.modified) return true;
-
- Object[] options = { "OK", "Cancel" };
- int result = JOptionPane.showOptionDialog(this,
- "Save changes before export?",
- "Save",
- JOptionPane.OK_CANCEL_OPTION,
- JOptionPane.QUESTION_MESSAGE,
- null,
- options,
- options[0]);
-
- if (result == JOptionPane.OK_OPTION) {
- handleSave(true);
-
- } else {
- // why it's not CANCEL_OPTION is beyond me (at least on the mac)
- // but f-- it.. let's get this shite done..
- //} else if (result == JOptionPane.CANCEL_OPTION) {
- message("Export canceled, changes must first be saved.");
- buttons.clear();
- return false;
- }
- return true;
- }
-
-
- public void handlePageSetup() {
- //printerJob = null;
- if (printerJob == null) {
- printerJob = PrinterJob.getPrinterJob();
- }
- if (pageFormat == null) {
- pageFormat = printerJob.defaultPage();
- }
- pageFormat = printerJob.pageDialog(pageFormat);
- //System.out.println("page format is " + pageFormat);
- }
-
-
- public void handlePrint() {
- message("Printing...");
- //printerJob = null;
- if (printerJob == null) {
- printerJob = PrinterJob.getPrinterJob();
- }
- if (pageFormat != null) {
- //System.out.println("setting page format " + pageFormat);
- printerJob.setPrintable(textarea.getPainter(), pageFormat);
- } else {
- printerJob.setPrintable(textarea.getPainter());
- }
- // set the name of the job to the code name
- printerJob.setJobName(sketch.current.name);
-
- if (printerJob.printDialog()) {
- try {
- printerJob.print();
- message("Done printing.");
-
- } catch (PrinterException pe) {
- error("Error while printing.");
- pe.printStackTrace();
- }
- } else {
- message("Printing canceled.");
- }
- //printerJob = null; // clear this out?
- }
-
-
- /**
- * Quit, but first ask user if it's ok. Also store preferences
- * to disk just in case they want to quit. Final exit() happens
- * in Editor since it has the callback from EditorStatus.
- */
- public void handleQuitInternal() {
- // doStop() isn't sufficient with external vm & quit
- // instead use doClose() which will kill the external vm
- doClose();
-
- checkModified(HANDLE_QUIT);
- }
-
-
- /**
- * Method for the MRJQuitHandler, needs to be dealt with differently
- * than the regular handler because OS X has an annoying implementation
- * quirk
- * that requires an exception to be thrown in order to properly cancel
- * a quit message.
- */
- public void handleQuit() {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- handleQuitInternal();
- }
- });
-
- // Throw IllegalStateException so new thread can execute.
- // If showing dialog on this thread in 10.2, we would throw
- // upon JOptionPane.NO_OPTION
- throw new IllegalStateException("Quit Pending User Confirmation");
- }
-
-
- /**
- * Actually do the quit action.
- */
- protected void handleQuit2() {
- storePreferences();
- Preferences.save();
-
- sketchbook.clean();
- console.handleQuit();
-
- //System.out.println("exiting here");
- System.exit(0);
- }
-
-
-
- protected void handleReference() {
- String text = textarea.getSelectedText().trim();
-
- if (text.length() == 0) {
- message("First select a word to find in the reference.");
-
- } else {
- String referenceFile = PdeKeywords.getReference(text);
- //System.out.println("reference file is " + referenceFile);
- if (referenceFile == null) {
- message("No reference available for \"" + text + "\"");
- } else {
- Base.showReference(referenceFile + ".html");
- }
- }
- }
-
- protected void handleBurnBootloader(final String programmer) {
- if(debugging)
- doStop();
- console.clear();
- message("Burning bootloader to I/O Board (this may take a minute)...");
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- try {
- Uploader uploader = new AvrdudeUploader();
- if (uploader.burnBootloader(programmer)) {
- message("Done burning bootloader.");
- } else {
- // error message will already be visible
- }
- } catch (RunnerException e) {
- message("Error while burning bootloader.");
- //e.printStackTrace();
- error(e);
- } catch (Exception e) {
- e.printStackTrace();
- }
- buttons.clear();
- }});
- }
-
- public void highlightLine(int lnum) {
- if (lnum < 0) {
- textarea.select(0, 0);
- return;
- }
- //System.out.println(lnum);
- String s = textarea.getText();
- int len = s.length();
- int st = -1;
- int ii = 0;
- int end = -1;
- int lc = 0;
- if (lnum == 0) st = 0;
- for (int i = 0; i < len; i++) {
- ii++;
- //if ((s.charAt(i) == '\n') || (s.charAt(i) == '\r')) {
- boolean newline = false;
- if (s.charAt(i) == '\r') {
- if ((i != len-1) && (s.charAt(i+1) == '\n')) {
- i++; //ii--;
- }
- lc++;
- newline = true;
- } else if (s.charAt(i) == '\n') {
- lc++;
- newline = true;
- }
- if (newline) {
- if (lc == lnum)
- st = ii;
- else if (lc == lnum+1) {
- //end = ii;
- // to avoid selecting entire, because doing so puts the
- // cursor on the next line [0090]
- end = ii - 1;
- break;
- }
- }
- }
- if (end == -1) end = len;
-
- // sometimes KJC claims that the line it found an error in is
- // the last line in the file + 1. Just highlight the last line
- // in this case. [dmose]
- if (st == -1) st = len;
-
- textarea.select(st, end);
- }
-
-
- // ...................................................................
-
-
- /**
- * Show an error int the status bar.
- */
- public void error(String what) {
- status.error(what);
- }
-
-
- public void error(Exception e) {
- if (e == null) {
- System.err.println("Editor.error() was passed a null exception.");
- return;
- }
-
- // not sure if any RuntimeExceptions will actually arrive
- // through here, but gonna check for em just in case.
- String mess = e.getMessage();
- if (mess != null) {
- String rxString = "RuntimeException: ";
- if (mess.indexOf(rxString) == 0) {
- mess = mess.substring(rxString.length());
- }
- String javaLang = "java.lang.";
- if (mess.indexOf(javaLang) == 0) {
- mess = mess.substring(javaLang.length());
- }
- error(mess);
- }
- e.printStackTrace();
- }
-
-
- public void error(RunnerException e) {
- //System.out.println("file and line is " + e.file + " " + e.line);
- if (e.file >= 0) sketch.setCurrent(e.file);
- if (e.line >= 0) highlightLine(e.line);
-
- // remove the RuntimeException: message since it's not
- // really all that useful to the user
- //status.error(e.getMessage());
- String mess = e.getMessage();
- String rxString = "RuntimeException: ";
- if (mess.indexOf(rxString) == 0) {
- mess = mess.substring(rxString.length());
- //System.out.println("MESS3: " + mess);
- }
- String javaLang = "java.lang.";
- if (mess.indexOf(javaLang) == 0) {
- mess = mess.substring(javaLang.length());
- }
- error(mess);
- buttons.clear();
- }
-
-
-
- public void message(String msg) {
- status.notice(msg);
- }
-
-
-
- // ...................................................................
-
-
- /**
- * Returns the edit popup menu.
- */
- class TextAreaPopup extends JPopupMenu {
- //String currentDir = System.getProperty("user.dir");
- String referenceFile = null;
-
- JMenuItem cutItem, copyItem;
- JMenuItem referenceItem;
-
-
- public TextAreaPopup() {
- JMenuItem item;
-
- cutItem = new JMenuItem("Cut");
- cutItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.cut();
- sketch.setModified(true);
- }
- });
- this.add(cutItem);
-
- copyItem = new JMenuItem("Copy");
- copyItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.copy();
- }
- });
- this.add(copyItem);
-
- item = new JMenuItem("Paste");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.paste();
- sketch.setModified(true);
- }
- });
- this.add(item);
-
- item = new JMenuItem("Select All");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.selectAll();
- }
- });
- this.add(item);
-
- this.addSeparator();
-
- referenceItem = new JMenuItem("Find in Reference");
- referenceItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- //Base.showReference(referenceFile + ".html");
- handleReference(); //textarea.getSelectedText());
- }
- });
- this.add(referenceItem);
- }
-
- // if no text is selected, disable copy and cut menu items
- public void show(Component component, int x, int y) {
- if (textarea.isSelectionActive()) {
- cutItem.setEnabled(true);
- copyItem.setEnabled(true);
-
- String sel = textarea.getSelectedText().trim();
- referenceFile = PdeKeywords.getReference(sel);
- referenceItem.setEnabled(referenceFile != null);
-
- } else {
- cutItem.setEnabled(false);
- copyItem.setEnabled(false);
- referenceItem.setEnabled(false);
- }
- super.show(component, x, y);
- }
- }
-}
-
diff --git a/app/EditorStatus.java b/app/EditorStatus.java
deleted file mode 100644
index b7be1cdf7..000000000
--- a/app/EditorStatus.java
+++ /dev/null
@@ -1,536 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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
-
- $Id$
-*/
-
-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 SERIAL = 4;
-
- static final int YES = 1;
- static final int NO = 2;
- static final int CANCEL = 3;
- static final int OK = 4;
- static final int SEND = 5;
-
- 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;
- JButton sendButton;
- JTextField editField;
- JTextField serialField;
- JComboBox serialRates;
-
- //Thread promptThread;
- int response;
-
-
- public EditorStatus(Editor editor) {
- this.editor = editor;
- empty();
-
- if (bgcolor == null) {
- bgcolor = new Color[5];
- // Arduino 0003 switched to a blue color scheme to visually distinguish
- // itself from Processing. Because the image files for certain interface
- // elements (e.g. buttons and tabs) are distributed with the application
- // while the preference file that specifies the IDE colors is stored in
- // the user's home directory and shared across all versions of Arduino,
- // we need to hardcode certain colors here to match the images.
- // Otherwise, users who used different multiple versions of the software
- // would sometimes see colors that didn't match the interface elements.
- // This is a hack and prevents users from customizing the IDE colors,
- // however, it obviates the need to provide for version-specific
- // preferences.
- //bgcolor[0] = Preferences.getColor("status.notice.bgcolor");
- bgcolor[0] = new Color(0x54, 0x91, 0x9e);
- bgcolor[1] = Preferences.getColor("status.error.bgcolor");
- bgcolor[2] = Preferences.getColor("status.prompt.bgcolor");
- bgcolor[3] = Preferences.getColor("status.prompt.bgcolor");
- bgcolor[4] = new Color(0x54, 0x91, 0x9e);
-
- fgcolor = new Color[5];
- fgcolor[0] = Preferences.getColor("status.notice.fgcolor");
- fgcolor[1] = Preferences.getColor("status.error.fgcolor");
- fgcolor[2] = Preferences.getColor("status.prompt.fgcolor");
- fgcolor[3] = Preferences.getColor("status.prompt.fgcolor");
- fgcolor[4] = Preferences.getColor("status.notice.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 serial()
- {
- mode = SERIAL;
- this.message = NO_MESSAGE;
-
- sendButton.setVisible(true);
- serialRates.setVisible(true);
- serialField.setVisible(true);
- serialField.setText("");
- serialField.requestFocus();
-
- repaint();
- }
-
- public void unserial()
- {
- sendButton.setVisible(false);
- serialField.setVisible(false);
- serialRates.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 (yesButton == 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 = Preferences.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 (yesButton == null) {
- yesButton = new JButton(Preferences.PROMPT_YES);
- noButton = new JButton(Preferences.PROMPT_NO);
- cancelButton = new JButton(Preferences.PROMPT_CANCEL);
- okButton = new JButton(Preferences.PROMPT_OK);
- sendButton = new JButton(Preferences.PROMPT_SEND);
-
- // !@#(* 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[PROMPT]);
- noButton.setBackground(bgcolor[PROMPT]);
- cancelButton.setBackground(bgcolor[PROMPT]);
- okButton.setBackground(bgcolor[PROMPT]);
- sendButton.setBackground(bgcolor[SERIAL]);
- }
- setLayout(null);
-
- yesButton.addActionListener(this);
- noButton.addActionListener(this);
- cancelButton.addActionListener(this);
- okButton.addActionListener(this);
- sendButton.addActionListener(this);
-
- add(yesButton);
- add(noButton);
- add(cancelButton);
- add(okButton);
- add(sendButton);
-
- yesButton.setVisible(false);
- noButton.setVisible(false);
- cancelButton.setVisible(false);
- okButton.setVisible(false);
- sendButton.setVisible(false);
-
- editField = new JTextField();
- editField.addActionListener(this);
-
- //if (Base.platform != Base.MACOSX) {
- editField.addKeyListener(new KeyAdapter() {
- // no-op implemented because of a jikes bug
- //protected void noop() { }
-
- //public void keyPressed(KeyEvent event) {
- //System.out.println("pressed " + event + " " + KeyEvent.VK_SPACE);
- //}
-
- // 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 + " " +
- // KeyEvent.VK_SPACE);
- int c = event.getKeyChar();
-
- if (mode == EDIT) {
- if (c == KeyEvent.VK_ENTER) { // accept the input
- String answer = editField.getText();
- editor.sketch.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)) {
- //System.out.println("nothing to see here");
- //noop();
-
- } else if (c == KeyEvent.VK_ESCAPE) {
- unedit();
- editor.buttons.clear();
- event.consume();
-
- } else if (c == KeyEvent.VK_SPACE) {
- //System.out.println("got a space");
- // if a space, insert an underscore
- //editField.insert("_", editField.getCaretPosition());
- /* tried to play nice and see where it got me
- editField.dispatchEvent(new KeyEvent(editField,
- KeyEvent.KEY_PRESSED,
- System.currentTimeMillis(),
- 0, 45, '_'));
- */
- //System.out.println("start/end = " +
- // editField.getSelectionStart() + " " +
- // editField.getSelectionEnd());
- String t = editField.getText();
- //int p = editField.getCaretPosition();
- //editField.setText(t.substring(0, p) + "_" + t.substring(p));
- //editField.setCaretPosition(p+1);
- int start = editField.getSelectionStart();
- int end = editField.getSelectionEnd();
- editField.setText(t.substring(0, start) + "_" +
- t.substring(end));
- editField.setCaretPosition(start+1);
- //System.out.println("consuming event");
- event.consume();
-
- } else if ((c == '_') || (c == '.') || // allow .pde and .java
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= 'a') && (c <= 'z'))) {
- // everything fine, catches upper and lower
- //noop();
-
- } 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);
-
- serialField = new JTextField();
- serialField.addActionListener(this);
-
- serialField.addKeyListener(new KeyAdapter() {
- public void keyTyped(KeyEvent event) {
- int c = event.getKeyChar();
-
- if (c == KeyEvent.VK_ENTER) { // accept the input
- editor.serialPort.write(serialField.getText());
- event.consume();
- serialField.setText("");
- }
- }});
-
- add(serialField);
- serialField.setVisible(false);
-
- String[] serialRateStrings = {
- "300","1200","2400","4800","9600","14400",
- "19200","28800","38400","57600","115200"
- };
-
- serialRates = new JComboBox();
-
- if (Base.isMacOS())
- serialRates.setBackground(bgcolor[SERIAL]);
-
- for (int i = 0; i < serialRateStrings.length; i++)
- serialRates.addItem(serialRateStrings[i] + " baud");
-
- serialRates.setSelectedItem(
- Preferences.get("serial.debug_rate") + " baud");
- serialRates.addActionListener(this);
- add(serialRates);
- serialRates.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);
- editField.setLocation(yesLeft - Preferences.BUTTON_WIDTH, top);
- serialField.setLocation(yesLeft - Preferences.BUTTON_WIDTH, top);
- okButton.setLocation(noLeft, top);
- serialRates.setLocation(0, top);
- sendButton.setLocation(cancelLeft, 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);
- sendButton.setSize( Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
- serialRates.setSize( 3*Preferences.BUTTON_WIDTH/2, Preferences.BUTTON_HEIGHT);
- editField.setSize( 2*Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
- serialField.setSize( 3*Preferences.BUTTON_WIDTH, Preferences.BUTTON_HEIGHT);
- }
-
-
- 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() == noButton) {
- // shut everything down, clear status, and return
- unprompt();
- // don't need to save changes
- editor.checkModified2();
-
- } else if (e.getSource() == yesButton) {
- // answer was in response to "save changes?"
- unprompt();
- editor.handleSave(true);
- editor.checkModified2();
-
- } else if (e.getSource() == cancelButton) {
- // don't do anything, don't continue with checkModified2
- if (mode == PROMPT) unprompt();
- else if (mode == EDIT) unedit();
- editor.buttons.clear();
-
- } else if (e.getSource() == okButton) {
- // answering to "save as..." question
- String answer = editField.getText();
- //editor.handleSaveAs2(answer);
- editor.sketch.nameCode(answer);
- unedit();
- } else if (e.getSource() == sendButton) {
- editor.serialPort.write(serialField.getText());
- serialField.setText("");
- } else if (e.getSource() == serialRates) {
- String wholeString = (String) serialRates.getSelectedItem();
- String rateString = wholeString.substring(0, wholeString.indexOf(' '));
- int rate = Integer.parseInt(rateString);
- Preferences.set("serial.debug_rate", rateString);
- editor.serialPort.dispose();
- try {
- editor.serialPort = new Serial(true);
- } catch (SerialException err) {
- editor.error(err);
- }
- }
- }
-}
diff --git a/app/Library.java b/app/Library.java
deleted file mode 100755
index 8fe9865be..000000000
--- a/app/Library.java
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- Library.java - Library System for Wiring
- Copyright (c) 2006 Nicholas Zambetti. All right reserved.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-package processing.app;
-
-import processing.app.syntax.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-
-import java.awt.*;
-import java.awt.event.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-
-import processing.core.*;
-
-/*
- * Provides information about and builds a library
- */
-public class Library implements MessageConsumer{
-
- private File libFolder;
- private File utilityFolder;
- private LibraryManager libManager;
- RunnerException exception;
-
- static final String BUGS_URL = "https://developer.berlios.de/bugs/?group_id=3590";
- static final String SUPER_BADNESS = "Compiler error, please submit this code to " + BUGS_URL;
-
- /*
- * Create a Library
- */
- public Library(LibraryManager manager, File folder)
- {
- libFolder = folder;
- libManager = manager;
- utilityFolder = getUtilityFolder();
-
- // for debug output
- /*
- System.out.println("library: " + getName());
- System.out.println("folder: " + getFolder());
- System.out.println("utility: " + utilityFolder);
- System.out.println("built: " + isBuilt());
- System.out.println("buildable: " + isBuildable());
- System.out.println("o files: " + getObjectFiles().length);
- System.out.println("c files: " + getCSourceFiles().length);
- System.out.println("cpp files: " + getCPPSourceFiles().length);
- */
- }
-
- /*
- * Directory of library
- * @return File object of library's folder
- */
- public File getFolder()
- {
- return libFolder;
- }
-
- /*
- * The name of library
- * @return String with library name, derived from folder
- * note: this will be eventually taken from xml description file
- */
- public String getName()
- {
- return libFolder.getName();
- }
-
- /*
- * Tests if library is built
- * @return True if library has .o files, false otherwise
- */
- public boolean isBuilt()
- {
- if(getObjectFiles().length >= (getCSourceFiles().length + getCPPSourceFiles().length)){
- return true;
- }
- return false;
- }
-
- /*
- * Tests if library is buildable
- * @return True if library has source files, false otherwise
- */
- public boolean isBuildable()
- {
- if(0 < (getCSourceFiles().length + getCPPSourceFiles().length)){
- return true;
- }
- return false;
- }
-
- /*
- * Tests if library is unbuilt but buildable
- * @return True if library has .cpp files but no .o files, false otherwise
- */
- public boolean isUnbuiltBuildable()
- {
- if(isBuildable()){
- if(!isBuilt()){
- return true;
- }
- }
- return false;
- }
-
- /*
- * Scans for library "utility" folder
- * @return File object of library's "utility" folder, or null
- */
- private File getUtilityFolder()
- {
- FileFilter filter = new FileFilter() {
- public boolean accept(File file) {
- if(file.isDirectory()){
- if((file.getName()).equalsIgnoreCase("utility")){
- return true;
- }
- }
- return false;
- }
- };
- File[] files = libFolder.listFiles(filter);
- if(files.length > 0){
- return files[0];
- }
- return null;
- }
-
- /*
- * Finds examples folder
- * @return "examples" folder as file object or null
- */
- private File getExamplesFolder()
- {
- FileFilter filter = new FileFilter() {
- public boolean accept(File file) {
- if(file.isDirectory()){
- if((file.getName()).equalsIgnoreCase("examples")){
- return true;
- }
- }
- return false;
- }
- };
- File[] files = libFolder.listFiles(filter);
- if(files.length > 0){
- return files[0];
- }
- return null;
- }
-
- /*
- * Populates example menu or submenu with files
- */
- private void populateWithExamples(File folder, JMenu menu, ActionListener listener) {
- FileFilter onlyfolders = new FileFilter() {
- public boolean accept(File file) {
- return file.isDirectory();
- }
- };
- File[] folders = folder.listFiles(onlyfolders);
- File file;
- JMenu submenu;
- JMenuItem item;
- for(int i = 0; i < folders.length; ++i){
- file = new File(folders[i], folders[i].getName() + ".pde");
- if(file.exists()){
- item = new JMenuItem(folders[i].getName());
- item.setActionCommand(file.getAbsolutePath());
- item.addActionListener(listener);
- menu.add(item);
- }else{
- submenu = new JMenu(folders[i].getName());
- populateWithExamples(folders[i], submenu, listener);
- menu.add(submenu);
- }
- }
- }
-
- /*
- * Builds and returns an examples menu
- * @return JMenu object with example files, or null if none
- */
- public JMenu getExamplesMenu(ActionListener listener) {
- JMenu submenu;
- File examplesFolder = getExamplesFolder();
- if(null != examplesFolder){
- submenu = new JMenu("Library-" + getName());
- populateWithExamples(examplesFolder, submenu, listener);
- return submenu;
- }
- return null;
- }
-
- /*
- * List of object files for linking
- * @return Array of object files as File objects
- */
- private File[] getObjectFiles(File folder)
- {
- FileFilter onlyObjectFiles = new FileFilter() {
- public boolean accept(File file) {
- return (file.getName()).endsWith(".o");
- }
- };
- return folder.listFiles(onlyObjectFiles);
- }
- public File[] getObjectFiles()
- {
- if(null == utilityFolder){
- return getObjectFiles(libFolder);
- }
- File[] libraryObjects = getObjectFiles(libFolder);
- File[] utilityObjects = getObjectFiles(utilityFolder);
- File[] objects = new File[libraryObjects.length + utilityObjects.length];
- System.arraycopy(libraryObjects, 0, objects, 0, libraryObjects.length);
- System.arraycopy(utilityObjects, 0, objects, libraryObjects.length, utilityObjects.length);
- return objects;
- }
-
- /*
- * List of header source files for inclusion
- * @return Array of header source files as File objects
- */
- public File[] getHeaderFiles()
- {
- FileFilter onlyHFiles = new FileFilter() {
- public boolean accept(File file) {
- return (file.getName()).endsWith(".h");
- }
- };
- return libFolder.listFiles(onlyHFiles);
- }
-
- /*
- * List of library's C source files for compiling
- * @return Array of C source files as File objects
- */
- private File[] getCSourceFiles(File folder)
- {
- FileFilter onlyCFiles = new FileFilter() {
- public boolean accept(File file) {
- return (file.getName()).endsWith(".c");
- }
- };
- return folder.listFiles(onlyCFiles);
- }
- private File[] getCSourceFiles()
- {
- if(null == utilityFolder){
- return getCSourceFiles(libFolder);
- }
- File[] librarySources = getCSourceFiles(libFolder);
- File[] utilitySources = getCSourceFiles(utilityFolder);
- File[] sources = new File[librarySources.length + utilitySources.length];
- System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
- System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
- return sources;
- }
-
- /*
- * List of C++ source files for compiling
- * @return Array of C++ source files as File objects
- */
- private File[] getCPPSourceFiles(File folder)
- {
- FileFilter onlyCPPFiles = new FileFilter() {
- public boolean accept(File file) {
- return (file.getName()).endsWith(".cpp");
- }
- };
- return folder.listFiles(onlyCPPFiles);
- }
- private File[] getCPPSourceFiles()
- {
- if(null == utilityFolder){
- return getCPPSourceFiles(libFolder);
- }
- File[] librarySources = getCPPSourceFiles(libFolder);
- File[] utilitySources = getCPPSourceFiles(utilityFolder);
- File[] sources = new File[librarySources.length + utilitySources.length];
- System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
- System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
- return sources;
- }
-
- /*
- * Attempt to build library
- * @return true on successful build, false otherwise
- */
- public boolean build() throws RunnerException
- {
- // fail if library is not buildable (contains no sources)
- if(!isBuildable()){
- return false;
- }
-
- String userdir = System.getProperty("user.dir") + File.separator;
- String avrBasePath;
- if(Base.isMacOS()) {
- avrBasePath = new String("hardware/tools/avr/bin/");
- }
- else if(Base.isLinux()) {
- avrBasePath = new String("");
- }
- else {
- avrBasePath = new String(userdir + "hardware/tools/avr/bin/");
- }
-
- String[] baseCompileCommandC = new String[] {
- avrBasePath + "avr-gcc",
- "-c",
- "-g",
- "-Os",
- "-Wall",
- "-ffunction-sections", // place each function in its own section
- "-fdata-sections",
- "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
- "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
- "-I" + libManager.getTarget().getPath(),
- "-I" + getFolder(),
- };
-
- String[] baseCompileCommandCPP = new String[] {
- avrBasePath + "avr-g++",
- "-c",
- "-g",
- "-Os",
- "-Wall",
- "-fno-exceptions",
- "-ffunction-sections", // place each function in its own section
- "-fdata-sections",
- "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
- "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
- "-I" + libManager.getTarget().getPath(),
- "-I" + getFolder(),
- };
-
- // use built lib directories in include paths when searching for headers
- // this allows libs to use other libs easily
- int extraSpots = 2; // two spots for file path and -o portions
- utilityFolder = getUtilityFolder(); // refresh status of utility folder
- if(null != utilityFolder){
- extraSpots = 3; // an extra spot for utility folder as include
- }
- String[] libDirs = libManager.getFolderPaths();
- String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + extraSpots];
- String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + extraSpots];
- System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
- System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
- for (int i = 0; i < libDirs.length; ++i) {
- compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
- compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
- }
-
- // add this library's "utility" folder to inclusion paths
- if(null != utilityFolder){
- compileCommandC[compileCommandC.length - 3] = "-I" + utilityFolder.getPath();
- compileCommandCPP[compileCommandCPP.length - 3] = "-I" + utilityFolder.getPath();
- }
-
- File[] sourcesC = getCSourceFiles();
- File[] sourcesCPP = getCPPSourceFiles();
-
- // execute the compiler, and create threads to deal
- // with the input and error streams
- //
- int result = 0;
- try {
- String pathSansExtension;
- Process process;
- boolean compiling = true;
-
- // compile c sources
- for(int i = 0; i < sourcesC.length; ++i) {
- pathSansExtension = sourcesC[i].getPath();
- pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 2); // -2 because ".c"
-
- compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
- compileCommandC[compileCommandC.length - 1] = "-o" + pathSansExtension + ".o";
-
- process = Runtime.getRuntime().exec(compileCommandC);
- new MessageSiphon(process.getInputStream(), this);
- new MessageSiphon(process.getErrorStream(), this);
-
- // wait for the process to finish. if interrupted
- // before waitFor returns, continue waiting
- //
- compiling = true;
- while (compiling) {
- try {
- result = process.waitFor();
- //System.out.println("result is " + result);
- compiling = false;
- } catch (InterruptedException ignored) { }
- }
- if (exception != null) {
- exception.hideStackTrace = true;
- throw exception;
- }
- if(result != 0){
- return false;
- }
- }
-
- // compile c++ sources
- for(int i = 0; i < sourcesCPP.length; ++i) {
- pathSansExtension = sourcesCPP[i].getPath();
- pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 4); // -4 because ".cpp"
-
- compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
- compileCommandCPP[compileCommandCPP.length - 1] = "-o" + pathSansExtension + ".o";
-
- process = Runtime.getRuntime().exec(compileCommandCPP);
- new MessageSiphon(process.getInputStream(), this);
- new MessageSiphon(process.getErrorStream(), this);
-
- // wait for the process to finish. if interrupted
- // before waitFor returns, continue waiting
- //
- compiling = true;
- while (compiling) {
- try {
- result = process.waitFor();
- //System.out.println("result is " + result);
- compiling = false;
- } catch (InterruptedException ignored) { }
- }
- if (exception != null) {
- exception.hideStackTrace = true;
- throw exception;
- }
- if(result != 0){
- return false;
- }
- }
- } catch (Exception e) {
- String msg = e.getMessage();
- if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
- Base.showWarning("Compiler error",
- "Could not find the compiler.\n" +
- "avr-gcc is missing from your PATH,\n" +
- "see readme.txt for help.", null);
- return false;
-
- } else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
- Base.showWarning("Compiler error",
- "Could not find the compiler.\n" +
- "avr-g++ is missing from your PATH,\n" +
- "see readme.txt for help.", null);
- return false;
-
- } else {
- e.printStackTrace();
- result = -1;
- }
- }
-
- // an error was queued up by message()
- if (exception != null) {
- throw exception;
- }
-
- if (result != 0 && result != 1 ) {
- Base.openURL(BUGS_URL);
- throw new RunnerException(SUPER_BADNESS);
- }
-
- // success would mean that 'result' is set to zero
- return (result == 0); // ? true : false;
- }
-
- /**
- * Part of the MessageConsumer interface, this is called
- * whenever a piece (usually a line) of error message is spewed
- * out from the compiler. The errors are parsed for their contents
- * and line number, which is then reported back to Editor.
- */
- public void message(String inString) {
- // This receives messages as full lines, so a newline needs
- // to be added as they're printed to the console.
-
- // always print all compilation output for library writers!
- String outString = "";
-
- // shorten file paths so that they are friendlier
- int start = 0;
- int end = 0;
- String substring = libFolder.getPath() + File.separator;
- StringBuffer result = new StringBuffer();
- while ((end = inString.indexOf(substring, start)) >= 0) {
- result.append(inString.substring(start, end));
- start = end + substring.length();
- }
- result.append(inString.substring(start));
- outString = result.toString();
-
- System.err.print(outString);
-
- // prepare error for throwing
- if (inString.indexOf("error") != -1){
- exception = new RunnerException("Error building library \"" + getName() + "\"");
- }
- }
-
- /**
- * Handles loading of keywords file.
- * It is recommended that a # sign be used for comments
- * inside keywords.txt.
- */
- public void addSyntaxColors(PdeKeywords keywords) {
- File keywordsFile = new File(libFolder.getPath() + File.separator + "keywords.txt");
-
- // do not bother if no keywords file to read
- // should reprimand negligent library writers?!
- if(!keywordsFile.exists() || !keywordsFile.canRead()){
- return;
- }
-
- try{
- // open file stream in the verbose java way
- InputStream input = new FileInputStream(keywordsFile);
- InputStreamReader isr = new InputStreamReader(input);
- BufferedReader reader = new BufferedReader(isr);
-
- String line = null;
- while ((line = reader.readLine()) != null) {
-
- // skip empty and whitespace lines
- if (line.trim().length() == 0){
- continue;
- }
-
- // skip lines without tabs
- if (line.indexOf('\t') == -1){
- continue;
- }
-
- String pieces[] = PApplet.split(line, '\t');
-
- if (pieces.length >= 2) {
- String keyword = pieces[0].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);
-
- PdeKeywords.getKeywordColoring().add(keyword, id);
- }
- }
- }
-
- // close file stream
- reader.close();
- } catch (Exception e) {
- Base.showError("Problem Loading Keywords",
- "Could not load or interpret 'keywords.txt' in " + getName() + " library.\n" +
- "This must be corrected before distributing.", e);
- }
- }
-
-}
diff --git a/app/LibraryManager.java b/app/LibraryManager.java
deleted file mode 100755
index 871f7fb1b..000000000
--- a/app/LibraryManager.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- LibraryManager.java - Library System for Wiring
- Copyright (c) 2006-07 Nicholas Zambetti. All right reserved.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-package processing.app;
-
-import processing.app.syntax.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-
-import java.awt.event.*;
-
-import javax.swing.*;
-
-/*
- * Provides information about and builds libraries
- */
-public class LibraryManager {
-
- private File libDir;
- private List libraries = new ArrayList();
- private Target target;
-
- /*
- * Create a LibraryManager.
- */
- public LibraryManager() throws IOException
- {
- String userDir = System.getProperty("user.dir") + File.separator;
- libDir = new File(
- ((!Base.isMacOS()) ? "" : userDir) + "hardware" + File.separator +
- "libraries");
- target = new Target(
- System.getProperty("user.dir") + File.separator + "hardware" +
- File.separator + "cores",
- Preferences.get("boards." + Preferences.get("board") + ".build.core"));
- refreshLibraries();
- }
-
- public Target getTarget()
- {
- return target;
- }
-
- /*
- * Scans for libraries and refreshes internal list
- */
- private void refreshLibraries()
- {
- FileFilter onlyDirs = new FileFilter() {
- public boolean accept(File file) {
- return file.isDirectory();
- }
- };
- libraries.clear();
- File[] libs = libDir.listFiles(onlyDirs);
- for(int i = 0; i < libs.length; ++i){
- libraries.add(new Library(this, libs[i]));
- }
- }
-
- /*
- * Returns a collection of all library objects
- * @return A read-only collection of Library objects
- */
- public Collection getAll() {
- refreshLibraries();
- return Collections.unmodifiableList(libraries);
- }
-
- /*
- * Returns a collection of all built library objects
- * @return A read-only collection of built Library objects
- */
- public Collection getBuiltLibraries() {
- refreshLibraries();
- List builtLibraries = new ArrayList();
- Library library;
- ListIterator libIterator = libraries.listIterator();
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- if(library.isBuilt()){
- builtLibraries.add(library);
- }
- }
- return Collections.unmodifiableList(builtLibraries);
- }
-
- /*
- * Returns a collection of all buildable library objects
- * @return A read-only collection of built Library objects
- */
- public Collection getLibrariesToBuild() {
- refreshLibraries();
- List buildableLibraries = new ArrayList();
- Library library;
- ListIterator libIterator = libraries.listIterator();
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- if(library.isUnbuiltBuildable()){
- buildableLibraries.add(library);
- }
- }
- return Collections.unmodifiableList(buildableLibraries);
- }
-
- /*
- * Rebuilds built libraries
- * @return Number of libraries built as int, -1 & exception on error
- */
- public int rebuildAllBuilt() throws RunnerException {
- Collection builtLibraries = getBuiltLibraries();
- Library library;
- Iterator libIterator = builtLibraries.iterator();
- int countBuilt = 0;
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- //System.out.println("Building library \"" + library.getName() + "\"");
- try {
- if(library.build()){
- ++countBuilt;
- }else{
- return -1;
- }
- }catch (RunnerException re) {
- throw new RunnerException(re.getMessage());
- } catch (Exception ex) {
- throw new RunnerException(ex.toString());
- }
- }
- return countBuilt;
- }
-
- /*
- * Gathers paths to object files
- * @return Array of strings of paths to object files
- */
- public String[] getObjectFiles() {
- ArrayList filesArrayList = new ArrayList();
- Collection builtLibraries = getBuiltLibraries();
- Library library;
- File[] files;
- Iterator libIterator = builtLibraries.iterator();
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- files = library.getObjectFiles();
- for(int i = 0; i < files.length; ++i){
- filesArrayList.add(files[i].getPath());
- }
- }
- String[] filesArray = new String[filesArrayList.size()];
- filesArrayList.toArray(filesArray);
- return filesArray;
- }
-
- /*
- * Gathers filenames of header files
- * @return Array of strings of filenames of header files
- */
- public String[] getHeaderFiles() {
- ArrayList filesArrayList = new ArrayList();
- Collection builtLibraries = getBuiltLibraries();
- Library library;
- File[] files;
- Iterator libIterator = builtLibraries.iterator();
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- files = library.getHeaderFiles();
- for(int i = 0; i < files.length; ++i){
- filesArrayList.add(files[i].getName());
- }
- }
- String[] filesArray = new String[filesArrayList.size()];
- filesArrayList.toArray(filesArray);
- return filesArray;
- }
-
- /*
- * Gathers paths to library folders
- * @return Array of strings of paths to library folders
- */
- public String[] getFolderPaths() {
- ArrayList foldersArrayList = new ArrayList();
- //Collection builtLibraries = getBuiltLibraries();
- Collection libraries = getAll();
- Library library;
- //Iterator libIterator = builtLibraries.iterator();
- Iterator libIterator = libraries.iterator();
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- foldersArrayList.add(library.getFolder().getPath());
- }
- String[] foldersArray = new String[foldersArrayList.size()];
- foldersArrayList.toArray(foldersArray);
- return foldersArray;
- }
-
- /*
- * Builds unbuilt libraries
- * @return Number of libraries built as int, -1 & exception on error
- */
- public int buildAllUnbuilt() throws RunnerException {
- Collection buildableLibraries = getLibrariesToBuild();
- Library library;
- Iterator libIterator = buildableLibraries.iterator();
- int countBuilt = 0;
- while(libIterator.hasNext()){
- library = (Library)libIterator.next();
- //System.out.println("Building library \"" + library.getName() + "\"");
- try {
- if(library.build()){
- ++countBuilt;
- }else{
- return -1;
- }
- }catch (RunnerException re) {
- throw new RunnerException(re.getMessage());
- } catch (Exception ex) {
- throw new RunnerException(ex.toString());
- }
- }
- return countBuilt;
- }
-
- /*
- * Populates examples menu with library folders
- */
- public void populateExamplesMenu(JMenu examplesMenu, ActionListener listener) {
- Library library;
- Collection libraries = getBuiltLibraries();
- Iterator iterator = libraries.iterator();
- JMenu libraryExamples;
- while(iterator.hasNext()){
- library = (Library)iterator.next();
- libraryExamples = library.getExamplesMenu(listener);
- if(null != libraryExamples){
- examplesMenu.add(libraryExamples);
- }
- }
- }
-
- /*
- * Add syntax coloring
- */
- public void addSyntaxColoring(PdeKeywords keywords) {
- Library library;
- Collection libraries = getBuiltLibraries();
- Iterator iterator = libraries.iterator();
- while(iterator.hasNext()){
- library = (Library)iterator.next();
- library.addSyntaxColors(keywords);
- }
- }
-}
diff --git a/app/Runner.java b/app/Runner.java
deleted file mode 100644
index ba912f770..000000000
--- a/app/Runner.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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.core.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oroinc.text.regex.*;
-
-
-/**
- * Runs a compiled java applet, whether as an external application
- * or internally as an applet object in a window.
- */
-public class Runner implements MessageConsumer {
-
- PApplet applet;
- RunnerException exception;
- Window window;
- PrintStream leechErr;
- //String className;
-
- Editor editor;
- Sketch sketch;
-
- boolean newMessage;
- int messageLineCount;
- boolean foundMessageSource;
-
- Process process;
- SystemOutSiphon processInput;
- OutputStream processOutput;
- MessageSiphon processError;
-
-
- public Runner(Sketch sketch, Editor editor) {
- this.sketch = sketch;
- this.editor = editor;
- }
-
-
- public void start(Point windowLocation) throws RunnerException {
- //System.out.println(" externalRuntime is " + sketch.externalRuntime);
- /* this.leechErr = new PrintStream(new MessageStream(this));
-
- try {
- if (editor.presenting) {
- startPresenting();
-
- } else if (sketch.externalRuntime) {
- startExternalRuntime(windowLocation);
-
- } else {
- startInternal(windowLocation);
- }
-
- } catch (Exception e) {
- // this will pass through to the first part of message
- // this handles errors that happen inside setup()
- e.printStackTrace();
-
- // make sure applet is in use
- if (applet != null) applet.finished = true;
-
- leechErr.println(PApplet.LEECH_WAKEUP);
- e.printStackTrace(this.leechErr);
- }
-*/
- }
-
-
- public void startPresenting() throws Exception {
- Vector params = new Vector();
-
- params.add("java");
-
- String options = Preferences.get("run.options");
- /* if (options.length() > 0) {
- String pieces[] = PApplet.split(options, ' ');
- for (int i = 0; i < pieces.length; i++) {
- String p = pieces[i].trim();
- if (p.length() > 0) {
- params.add(p);
- }
- }
- }
-
- params.add("-Djava.library.path=" +
- sketch.libraryPath +
- File.pathSeparator +
- System.getProperty("java.library.path"));
-
- params.add("-cp");
- params.add(sketch.classPath + Sketchbook.librariesClassPath);
-
- params.add("processing.core.PApplet");
-
- params.add(PApplet.ARGS_EXTERNAL);
- params.add(PApplet.ARGS_PRESENT);
- params.add(PApplet.ARGS_PRESENT_STOP_COLOR + "=" +
- Preferences.get("run.present.stop.color"));
- params.add(PApplet.ARGS_BGCOLOR + "=" +
- Preferences.get("run.present.bgcolor"));
- params.add(PApplet.ARGS_DISPLAY + "=" +
- Preferences.get("run.display"));
- params.add(PApplet.ARGS_SKETCH_FOLDER + "=" +
- sketch.folder.getAbsolutePath());
- params.add(sketch.mainClassName);
-
- String command[] = new String[params.size()];
- params.copyInto(command);
- //PApplet.println(command);
-
- process = Runtime.getRuntime().exec(command);
- processInput = new SystemOutSiphon(process.getInputStream());
- processError = new MessageSiphon(process.getErrorStream(), this);
- processOutput = process.getOutputStream();
-*/
- }
-
-
- public void startExternalRuntime(Point windowLocation) throws Exception {
- // if there was a saved location (this guy has been run more than
- // once) then windowLocation will be set to the last position of
- // the sketch window. this will be passed to the PApplet runner
- // using something like --external=e30,20 where the e stands for
- // exact. otherwise --external=x,y for just the regular positioning.
-/* Point editorLocation = editor.getLocation();
- String location =
- (windowLocation != null) ?
- (PApplet.ARGS_LOCATION + "=" +
- windowLocation.x + "," + windowLocation.y) :
- (PApplet.ARGS_EDITOR_LOCATION + "=" +
- editorLocation.x + "," + editorLocation.y);
-
- // this as prefix made the code folder bug go away, but killed stdio
- //"cmd", "/c", "start",
-
- // all params have to be stored as separate items,
- // so a growable array needs to be used. i.e. -Xms128m -Xmx1024m
- // will throw an error if it's shoved into a single array element
- Vector params = new Vector();
-
- params.add("java");
-
- String options = Preferences.get("run.options");
- if (options.length() > 0) {
- String pieces[] = PApplet.split(options, ' ');
- for (int i = 0; i < pieces.length; i++) {
- String p = pieces[i].trim();
- if (p.length() > 0) {
- params.add(p);
- }
- }
- }
- // sketch.libraryPath might be ""
- // librariesClassPath will always have sep char prepended
- params.add("-Djava.library.path=" +
- sketch.libraryPath +
- File.pathSeparator +
- System.getProperty("java.library.path"));
-
- params.add("-cp");
- params.add(sketch.classPath + Sketchbook.librariesClassPath);
-
- params.add("processing.core.PApplet");
-
- params.add(location);
- params.add(PApplet.ARGS_EXTERNAL);
- params.add(PApplet.ARGS_DISPLAY + "=" +
- Preferences.get("run.display"));
- params.add(PApplet.ARGS_SKETCH_FOLDER + "=" +
- sketch.folder.getAbsolutePath());
- params.add(sketch.mainClassName);
-
- String command[] = new String[params.size()];
- params.copyInto(command);
- //PApplet.println(command);
-
- process = Runtime.getRuntime().exec(command);
- processInput = new SystemOutSiphon(process.getInputStream());
- processError = new MessageSiphon(process.getErrorStream(), this);
- processOutput = process.getOutputStream();
- */ }
-
-
- public void startInternal(Point windowLocation) throws Exception {
- /* Point editorLocation = editor.getLocation();
- //Insets editorInsets = editor.getInsets();
-
- int windowX = editorLocation.x;
- int windowY = editorLocation.y + editor.getInsets().top;
-
- RunnerClassLoader loader = new RunnerClassLoader();
- Class c = loader.loadClass(sketch.mainClassName);
- applet = (PApplet) c.newInstance();
-
- window = new Frame(sketch.name); // use ugly window
- ((Frame)window).setResizable(false);
- if (editor.icon != null) {
- ((Frame)window).setIconImage(editor.icon);
- }
- window.pack(); // to get a peer, size set later, need for insets
-
- applet.leechErr = leechErr;
- applet.folder = sketch.folder.getAbsolutePath();
- applet.frame = (Frame) window;
-
- applet.init();
- //applet.start();
-
- while ((applet.width == 0) && !applet.finished) {
- try {
- if (applet.exception != null) {
- throw new RunnerException(applet.exception.getMessage());
- }
- Thread.sleep(5);
- } catch (InterruptedException e) { }
- }
-
- window.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- stop();
- editor.doClose();
- }
- });
-
- applet.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent e) {
- if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
- stop();
- editor.doClose();
- }
- }
- });
-
- window.add(applet);
-
- Dimension screen =
- Toolkit.getDefaultToolkit().getScreenSize();
-
- window.setLayout(null);
- Insets insets = window.getInsets();
-
- int minW = Preferences.getInteger("run.window.width.minimum");
- int minH = Preferences.getInteger("run.window.height.minimum");
- int windowW =
- Math.max(applet.width, minW) + insets.left + insets.right;
- int windowH =
- Math.max(applet.height, minH) + insets.top + insets.bottom;
-
- if (windowX - windowW > 10) { // if it fits to the left of the window
- window.setBounds(windowX - windowW, windowY, windowW, windowH);
-
- } else { // if it fits inside the editor window
- windowX = editorLocation.x + Preferences.GRID_SIZE * 2; // 66
- windowY = editorLocation.y + Preferences.GRID_SIZE * 2; // 66
-
- if ((windowX + windowW > screen.width - Preferences.GRID_SIZE) ||
- (windowY + windowH > screen.height - Preferences.GRID_SIZE)) {
- // otherwise center on screen
- windowX = (screen.width - windowW) / 2;
- windowY = (screen.height - windowH) / 2;
- }
- window.setBounds(windowX, windowY, windowW, windowH); //ww, wh);
- }
-
- Color windowBgColor = Preferences.getColor("run.window.bgcolor");
- window.setBackground(windowBgColor);
-
- int usableH = windowH - insets.top - insets.bottom;
- applet.setBounds((windowW - applet.width)/2,
- insets.top + (usableH - applet.height) / 2,
- windowW, windowH);
-
- applet.setVisible(true); // no effect
- if (windowLocation != null) {
- window.setLocation(windowLocation);
- }
- window.show();
- applet.requestFocus(); // necessary for key events
-*/
- }
-
-
- public void stop() {
- /* // check for null in case stop is called during compilation
- if (applet != null) {
- applet.stop();
-
- // above avoids NullPointerExceptions
- // but still threading is too complex, and so
- // some boogers are being left behind
- applet = null;
-
- } else if (process != null) { // running externally
- try {
- processOutput.write(PApplet.EXTERNAL_STOP);
- processOutput.flush();
-
- } catch (IOException e) {
- close();
- }
- }
-
-*/
- }
-
-
- public void close() {
- /* //if (window != null) window.hide();
- if (window != null) {
- //System.err.println("disposing window");
- window.dispose();
- window = null;
- }
-
- if (process != null) {
- try {
- process.destroy();
- } catch (Exception e) {
- //System.err.println("(ignored) error while destroying");
- //e.printStackTrace();
- }
- process = null;
- }
-*/
- }
-
-
- // made synchronized for rev 87
- synchronized public void message(String s) {
- //System.out.println("M" + s.length() + ":" + s.trim()); // + "MMM" + s.length());
-
- // this eats the CRLFs on the lines.. oops.. do it later
- //if (s.trim().length() == 0) return;
-
- // this is PApplet sending a message (via System.out.println)
- // that signals that the applet has been quit.
- // if (s.indexOf(PApplet.EXTERNAL_QUIT) == 0) {
- //System.out.println("external: quit");
- // editor.doClose();
- // return;
- // }
-
- // this is the PApplet sending us a message that the applet
- // is being moved to a new window location
- // if (s.indexOf(PApplet.EXTERNAL_MOVE) == 0) {
- // String nums = s.substring(s.indexOf(' ') + 1).trim();
- // int space = nums.indexOf(' ');
- // int left = Integer.parseInt(nums.substring(0, space));
- // int top = Integer.parseInt(nums.substring(space + 1));
- // editor.appletLocation = new Point(left, top);
- // //System.out.println("external: move to " + left + " " + top);
- //// return;
- // }
-
- // this is PApplet sending a message saying "i'm about to spew
- // a stack trace because an error occurred during PApplet.run()"
-// if (s.indexOf(PApplet.LEECH_WAKEUP) == 0) {
- // newMessage being set to 'true' means that the next time
- // message() is called, expect the first line of the actual
- // // error message & stack trace to be sent from the applet.
- // newMessage = true;
- // return; // this line ignored
- // }
-
- // these are used for debugging, in case there are concerns
- // that some errors aren't coming through properly
- /*
- if (s.length() > 2) {
- System.err.println(newMessage);
- System.err.println("message " + s.length() + ":" + s);
- }
- */
- // always shove out the mesage, since it might not fall under
- // the same setup as we're expecting
- System.err.print(s);
- //System.err.println("[" + s.length() + "] " + s);
- System.err.flush();
-
- // exit here because otherwise the exception name
- // may be titled with a blank string
- if (s.trim().length() == 0) return;
-
- // annoying, because it seems as though the terminators
- // aren't being sent properly
- //System.err.println(s);
-
- //if (newMessage && s.length() > 2) {
- if (newMessage) {
- exception = new RunnerException(s); // type of java ex
- exception.hideStackTrace = true;
- //System.out.println("setting ex type to " + s);
- newMessage = false;
- foundMessageSource = false;
- messageLineCount = 0;
-
- } else {
- messageLineCount++;
-
- /*
-java.lang.NullPointerException
- at javatest.(javatest.java:5)
- at Temporary_2425_1153.draw(Temporary_2425_1153.java:11)
- at PApplet.nextFrame(PApplet.java:481)
- at PApplet.run(PApplet.java:428)
- at java.lang.Thread.run(Unknown Source)
- */
-
- if (!foundMessageSource) {
- // " at javatest.(javatest.java:5)"
- // -> "javatest.(javatest.java:5)"
- int afterAt = s.indexOf("at") + 3;
- //if (afterAt == -1) {
- if (afterAt == 2) { // means indexOf was -1
- //System.err.println(s); // stop double-printing exceptions
- return;
- }
- s = s.substring(afterAt + 1);
-
- // "javatest.(javatest.java:5)"
- // -> "javatest." and "(javatest.java:5)"
- int startParen = s.indexOf('(');
- // at javatest.(javatest.java:5)
- String pkgClassFxn = null;
- //String fileLine = null;
- int codeIndex = -1;
- int lineNumber = -1;
-
- if (startParen == -1) {
- pkgClassFxn = s;
-
- } else {
- pkgClassFxn = s.substring(0, startParen);
- // "(javatest.java:5)"
- String fileAndLine = s.substring(startParen + 1);
- int stopParen = fileAndLine.indexOf(')');
- //fileAndLine = fileAndLine.substring(0, fileAndLine.length() - 1);
- fileAndLine = fileAndLine.substring(0, stopParen);
- //System.out.println("file 'n line " + fileAndLine);
-
- //if (!fileAndLine.equals("Unknown Source")) {
- // "javatest.java:5"
- int colonIndex = fileAndLine.indexOf(':');
- if (colonIndex != -1) {
- String filename = fileAndLine.substring(0, colonIndex);
- // "javatest.java" and "5"
- //System.out.println("filename = " + filename);
- //System.out.println("pre0 = " + sketch.code[0].preprocName);
- //for (int i = 0; i < sketch.codeCount; i++) {
- //System.out.println(i + " " + sketch.code[i].lineOffset + " " +
- // sketch.code[i].preprocName);
- //}
- lineNumber =
- Integer.parseInt(fileAndLine.substring(colonIndex + 1)) - 1;
-
- for (int i = 0; i < sketch.codeCount; i++) {
- SketchCode code = sketch.code[i];
- //System.out.println(code.preprocName + " " + lineNumber + " " +
- // code.preprocOffset);
- if (((code.preprocName == null) &&
- (lineNumber >= code.preprocOffset)) ||
- ((code.preprocName != null) &&
- code.preprocName.equals(filename))) {
- codeIndex = i;
- //System.out.println("got codeindex " + codeIndex);
- //break;
- //} else if (
- }
- }
-
- if (codeIndex != -1) {
- //System.out.println("got line num " + lineNumber);
- // in case this was a tab that got embedded into the main .java
- lineNumber -= sketch.code[codeIndex].preprocOffset;
-
- // this may have a paren on the end, if so need to strip
- // down to just the digits
- /*
- int lastNumberIndex = colonIndex + 1;
- while ((lastNumberIndex < fileAndLine.length()) &&
- Character.isDigit(fileAndLine.charAt(lastNumberIndex))) {
- lastNumberIndex++;
- }
- */
-
- // lineNumber is 1-indexed, but editor wants zero-indexed
- // getMessage() will be what's shown in the editor
- exception =
- new RunnerException(exception.getMessage(),
- codeIndex, lineNumber, -1);
- exception.hideStackTrace = true;
- foundMessageSource = true;
- }
- }
- }
- editor.error(exception);
-
- /*
- int index = s.indexOf(className + ".java");
- if (index != -1) {
- int len = (className + ".java").length();
- String lineNumberStr = s.substring(index + len + 1);
- index = lineNumberStr.indexOf(')');
- lineNumberStr = lineNumberStr.substring(0, index);
- try {
- exception.line = Integer.parseInt(lineNumberStr) - 1; //2;
- } catch (NumberFormatException e) { }
- //e.printStackTrace(); // a recursive error waiting to happen?
- // if nfe occurs, who cares, still send the error on up
- editor.error(exception);
- */
-
- /*
- // WARNING THESE ARE DISABLED!!
- } else if ((index = s.indexOf(className + ".class")) != -1) {
- // code to check for:
- // at Temporary_484_3845.loop(Compiled Code)
- // would also probably get:
- // at Temporary_484_3845.loop
- // which (i believe) is used by the mac and/or jview
- String functionStr = s.substring(index +
- (className + ".class").length() + 1);
- index = functionStr.indexOf('(');
- if (index != -1) {
- functionStr = functionStr.substring(0, index);
- }
- exception = new RunnerException(//"inside \"" + functionStr + "()\": " +
- exception.getMessage() +
- " inside " + functionStr + "() " +
- "[add Compiler.disable() to setup()]");
- editor.error(exception);
- // this will fall through in tihs example:
- // at Temporary_4636_9696.pootie(Compiled Code)
- // at Temporary_4636_9696.loop(Temporary_4636_9696.java:24)
- // because pootie() (re)sets the exception title
- // and throws it, but then the line number gets set
- // because of the line that comes after
- */
-
- } else if (messageLineCount > 10) { // 5 -> 10 for 0088
- // this means the class name may not be mentioned
- // in the stack trace.. this is just a general purpose
- // error, but needs to make it through anyway.
- // so if five lines have gone past, might as well signal
- messageLineCount = -100;
- exception = new RunnerException(exception.getMessage());
- exception.hideStackTrace = true;
- editor.error(exception);
-
- } else {
- //System.err.print(s);
- }
- //System.out.println("got it " + s);
- }
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- /**
- * Siphons from an InputStream of System.out (from a Process)
- * and sends it to the real System.out.
- */
- class SystemOutSiphon implements Runnable {
- InputStream input;
- Thread thread;
-
- public SystemOutSiphon(InputStream input) {
- this.input = input;
-
- thread = new Thread(this);
- // unless this is set to min, it seems to hork the app
- // since it's in charge of stuffing the editor console with strings
- // maybe it's time to get rid of/fix that friggin console
- // ...disabled for 0075, with 0074's fix for code folder hanging
- // this only seems to make the console unresponsive
- //thread.setPriority(Thread.MIN_PRIORITY);
- thread.start();
- }
-
- public void run() {
- byte boofer[] = new byte[256];
-
- while (Thread.currentThread() == thread) {
- try {
- // can't use a buffered reader here because incremental
- // print statements are interesting too.. causes some
- // disparity with how System.err gets spewed, oh well.
- int count = input.read(boofer, 0, boofer.length);
- if (count == -1) {
- thread = null;
-
- } else {
- System.out.print(new String(boofer, 0, count));
- //System.out.flush();
- }
-
- } catch (IOException e) {
- // this is prolly because the app was quit & the stream broken
- //e.printStackTrace(System.out);
- //e.printStackTrace();
- thread = null;
-
- } catch (Exception e) {
- //System.out.println("SystemOutSiphon: i just died in your arms tonight");
- // on mac os x, this will spew a "Bad File Descriptor" ex
- // each time an external app is shut down.
- //e.printStackTrace();
- thread = null;
- //System.out.println("");
- }
- //System.out.println("SystemOutSiphon: out");
- //thread = null;
- }
- }
- }
-}
diff --git a/app/RunnerClassLoader.java b/app/RunnerClassLoader.java
deleted file mode 100644
index eda1ab14d..000000000
--- a/app/RunnerClassLoader.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Based on Simple1.2ClassLoader.java - simple Java 1.2 class loader
- Copyright (c) 1999 Ken McCrary, All Rights Reserved.
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for NON-COMMERCIAL purposes and without
- fee is hereby granted provided that this copyright notice
- appears in all copies.
-
- KEN MCCRARY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
- SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. KEN MCCRARY
- SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
- OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
- */
-package processing.app;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.jar.*;
-
-
-/**
- * Simple class loader adapted for Processing.
- *
- * Based on code from Ken McCrary.
- */
-public class RunnerClassLoader extends ClassLoader {
- String buildFolderPath;
-
- RunnerClassLoader() {
- buildFolderPath = Base.getBuildFolder().getAbsolutePath();
- }
-
- /**
- * This is the method where the task of class loading
- * is delegated to our custom loader.
- *
- * @param name the name of the class
- * @return the resulting Class object
- * @exception ClassNotFoundException if the class could not be found
- */
- protected Class findClass(String name) throws ClassNotFoundException {
- FileInputStream fi = null;
-
- try {
- String path =
- buildFolderPath + File.separator + name.replace('.', '/');
- //System.out.println("(from " + path + ")");
- fi = new FileInputStream(path + ".class");
- byte[] classBytes = new byte[fi.available()];
- fi.read(classBytes);
- //definePackage(name);
- return defineClass(name, classBytes, 0, classBytes.length);
-
- } catch (Exception e) {
- // could not find the class, so indicate the problem with an exception
- throw new ClassNotFoundException(name);
-
- } finally {
- if (fi != null) {
- try {
- fi.close();
- } catch (Exception e) { }
- }
- }
- }
-
-
- /**
- * Identify where to load a resource from, resources for
- * this simple ClassLoader are in a directory name "store"
- *
- * @param name the resource name
- * @return URL for resource or null if not found
- */
- protected URL findResource(String name) {
- String path =
- buildFolderPath + File.separator + name.replace('.', '/');
- File searchResource = new File(path, name);
- //URL result = null;
-
- if (searchResource.exists()) {
- try {
- return searchResource.toURL();
- } catch (MalformedURLException mfe) { }
- }
- //return result;
- return null;
- }
-
-
- /**
- * Used for identifying resources from multiple URLS
- * Since our simple Classloader only has one repository
- * the returned Enumeration contains 0 to 1 items
- *
- * @param name the resource name
- * @return Enumeration of one URL
- */
- protected Enumeration findResources(final String name) throws IOException {
- // Since we only have a single repository we will only have one
- // resource of a particular name, the Enumeration will just return
- // this single URL
-
- return new Enumeration() {
- URL resource = findResource(name);
-
- public boolean hasMoreElements() {
- return ( resource != null ? true : false);
- }
-
- public Object nextElement() {
- if (!hasMoreElements()) {
- throw new NoSuchElementException();
- } else {
- URL result = resource;
- resource = null;
- return result;
- }
- }
- };
- }
-}
diff --git a/app/RunnerException.java b/app/RunnerException.java
deleted file mode 100644
index 200e9abdb..000000000
--- a/app/RunnerException.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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;
-
-/**
- * An exception with a line number attached that occurs
- * during either compile time or run time.
- */
-public class RunnerException extends Exception {
- public int file = -1;
- public int line = -1;
- public int column = -1;
- public boolean hideStackTrace;
-
- public RunnerException() { }
-
- public RunnerException(String message) {
- super(massage(message));
- }
-
- public RunnerException(String message, int line) {
- super(massage(message));
- this.line = line;
- }
-
- public RunnerException(String message, int line, int column) {
- super(massage(message));
- this.line = line;
- this.column = column;
- }
-
- public RunnerException(String message, int file, int line, int column) {
- super(massage(message));
- this.file = file;
- this.line = line;
- this.column = column;
- }
-
-
- /**
- * Nix the java.lang crap out of an exception message
- * because it scares the children.
- *
- * 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 == null)
- return "";
- 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 (!hideStackTrace) {
- super.printStackTrace();
- }
- }
-}
diff --git a/app/Sketch.java b/app/Sketch.java
deleted file mode 100644
index 2e99f5468..000000000
--- a/app/Sketch.java
+++ /dev/null
@@ -1,2280 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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.preproc.*;
-import processing.core.*;
-
-import java.awt.*;
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.JOptionPane;
-
-import com.oroinc.text.regex.*;
-
-
-/**
- * Stores information about files in the current sketch
- */
-public class Sketch {
- static File tempBuildFolder;
-
- Editor editor;
-
- /**
- * Name of sketch, which is the name of main file
- * (without .pde or .java extension)
- */
- String name;
-
- /**
- * Name of 'main' file, used by load(), such as sketch_04040.pde
- */
- String mainFilename;
-
- /**
- * true if any of the files have been modified.
- */
- boolean modified;
-
- public File folder;
- public File dataFolder;
- public File codeFolder;
-
- static final int PDE = 0;
- static final int CPP = 1;
- static final int C = 2;
- static final int HEADER = 3;
-
- static final String flavorExtensionsReal[] = new String[] { ".pde", ".cpp", ".c", ".h" };
- static final String flavorExtensionsShown[] = new String[] { "", ".cpp", ".c", ".h" };
-
- public SketchCode current;
- int currentIndex;
- int codeCount;
- SketchCode code[];
-
- int hiddenCount;
- SketchCode hidden[];
-
- Hashtable zipFileContents;
-
- // all these set each time build() is called
- String mainClassName;
- String classPath;
- String libraryPath;
- boolean externalRuntime;
- public Vector importedLibraries; // vec of Library objects
-
- /**
- * path is location of the main .pde file, because this is also
- * simplest to use when opening the file from the finder/explorer.
- */
- public Sketch(Editor editor, String path) throws IOException {
- this.editor = editor;
-
- File mainFile = new File(path);
- //System.out.println("main file is " + mainFile);
-
- mainFilename = mainFile.getName();
- //System.out.println("main file is " + mainFilename);
-
- // get the name of the sketch by chopping .pde or .java
- // off of the main file name
- if (mainFilename.endsWith(".pde")) {
- name = mainFilename.substring(0, mainFilename.length() - 4);
- } else if (mainFilename.endsWith(".c")) {
- name = mainFilename.substring(0, mainFilename.length() - 2);
- } else if (mainFilename.endsWith(".h")) {
- name = mainFilename.substring(0, mainFilename.length() - 2);
- } else if (mainFilename.endsWith(".cpp")) {
- name = mainFilename.substring(0, mainFilename.length() - 4);
- }
- // lib/build must exist when the application is started
- // it is added to the CLASSPATH by default, but if it doesn't
- // exist when the application is started, then java will remove
- // the entry from the CLASSPATH, causing Runner to fail.
- //
- /*
- tempBuildFolder = new File(TEMP_BUILD_PATH);
- if (!tempBuildFolder.exists()) {
- tempBuildFolder.mkdirs();
- Base.showError("Required folder missing",
- "A required folder was missing from \n" +
- "from your installation of Processing.\n" +
- "It has now been replaced, please restart \n" +
- "the application to complete the repair.", null);
- }
- */
- tempBuildFolder = Base.getBuildFolder();
- //Base.addBuildFolderToClassPath();
-
- folder = new File(new File(path).getParent());
- //System.out.println("sketch dir is " + folder);
-
- load();
- }
-
-
- /**
- * Build the list of files.
- *
- * Generally this is only done once, rather than
- * each time a change is made, because otherwise it gets to be
- * a nightmare to keep track of what files went where, because
- * not all the data will be saved to disk.
- *
- * This also gets called when the main sketch file is renamed,
- * because the sketch has to be reloaded from a different folder.
- *
- * Another exception is when an external editor is in use,
- * in which case the load happens each time "run" is hit.
- */
- public void load() {
- codeFolder = new File(folder, "code");
- dataFolder = new File(folder, "data");
-
- // get list of files in the sketch folder
- String list[] = folder.list();
-
- for (int i = 0; i < list.length; i++) {
- if (list[i].endsWith(".pde")) codeCount++;
- else if (list[i].endsWith(".c")) codeCount++;
- else if (list[i].endsWith(".h")) codeCount++;
- else if (list[i].endsWith(".cpp")) codeCount++;
- else if (list[i].endsWith(".pde.x")) hiddenCount++;
- else if (list[i].endsWith(".c.x")) hiddenCount++;
- else if (list[i].endsWith(".h.x")) hiddenCount++;
- else if (list[i].endsWith(".cpp.x")) hiddenCount++;
- }
-
- code = new SketchCode[codeCount];
- hidden = new SketchCode[hiddenCount];
-
- int codeCounter = 0;
- int hiddenCounter = 0;
-
- for (int i = 0; i < list.length; i++) {
- if (list[i].endsWith(".pde")) {
- code[codeCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 4),
- new File(folder, list[i]),
- PDE);
-
- } else if (list[i].endsWith(".c")) {
- code[codeCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 2),
- new File(folder, list[i]),
- C);
-
- } else if (list[i].endsWith(".h")) {
- code[codeCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 2),
- new File(folder, list[i]),
- HEADER);
-
- } else if (list[i].endsWith(".cpp")) {
- code[codeCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 4),
- new File(folder, list[i]),
- CPP);
-
- } else if (list[i].endsWith(".pde.x")) {
- hidden[hiddenCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 6),
- new File(folder, list[i]),
- PDE);
-
- } else if (list[i].endsWith(".c.x")) {
- hidden[hiddenCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 4),
- new File(folder, list[i]),
- C);
- } else if (list[i].endsWith(".h.x")) {
- hidden[hiddenCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 4),
- new File(folder, list[i]),
- HEADER);
- } else if (list[i].endsWith(".cpp.x")) {
- hidden[hiddenCounter++] =
- new SketchCode(list[i].substring(0, list[i].length() - 6),
- new File(folder, list[i]),
- CPP);
- }
- }
-
- // some of the hidden files may be bad too, so use hiddenCounter
- // added for rev 0121, fixes bug found by axel
- hiddenCount = hiddenCounter;
-
- // remove any entries that didn't load properly from codeCount
- int index = 0;
- while (index < codeCount) {
- if ((code[index] == null) ||
- (code[index].program == null)) {
- for (int i = index+1; i < codeCount; i++) {
- code[i-1] = code[i];
- }
- codeCount--;
-
- } else {
- index++;
- }
- }
-
- // move the main class to the first tab
- // start at 1, if it's at zero, don't bother
- for (int i = 1; i < codeCount; i++) {
- if (code[i].file.getName().equals(mainFilename)) {
- SketchCode temp = code[0];
- code[0] = code[i];
- code[i] = temp;
- break;
- }
- }
-
- // sort the entries at the top
- sortCode();
-
- // set the main file to be the current tab
- setCurrent(0);
- }
-
-
- protected void insertCode(SketchCode newCode) {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // add file to the code/codeCount list, resort the list
- if (codeCount == code.length) {
- SketchCode temp[] = new SketchCode[codeCount+1];
- System.arraycopy(code, 0, temp, 0, codeCount);
- code = temp;
- }
- code[codeCount++] = newCode;
- }
-
-
- protected void sortCode() {
- // cheap-ass sort of the rest of the files
- // it's a dumb, slow sort, but there shouldn't be more than ~5 files
- for (int i = 1; i < codeCount; i++) {
- int who = i;
- for (int j = i + 1; j < codeCount; j++) {
- if (code[j].name.compareTo(code[who].name) < 0) {
- who = j; // this guy is earlier in the alphabet
- }
- }
- if (who != i) { // swap with someone if changes made
- SketchCode temp = code[who];
- code[who] = code[i];
- code[i] = temp;
- }
- }
- }
-
-
- boolean renamingCode;
-
- public void newCode() {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // if read-only, give an error
- if (isReadOnly()) {
- // if the files are read-only, need to first do a "save as".
- Base.showMessage("Sketch is Read-Only",
- "Some files are marked \"read-only\", so you'll\n" +
- "need to re-save the sketch in another location,\n" +
- "and try again.");
- return;
- }
-
- renamingCode = false;
- editor.status.edit("Name for new file:", "");
- }
-
-
- public void renameCode() {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // if read-only, give an error
- if (isReadOnly()) {
- // if the files are read-only, need to first do a "save as".
- Base.showMessage("Sketch is Read-Only",
- "Some files are marked \"read-only\", so you'll\n" +
- "need to re-save the sketch in another location,\n" +
- "and try again.");
- return;
- }
-
- // ask for new name of file (internal to window)
- // TODO maybe just popup a text area?
- renamingCode = true;
- String prompt = (currentIndex == 0) ?
- "New name for sketch:" : "New name for file:";
- String oldName = current.name + flavorExtensionsShown[current.flavor];
- editor.status.edit(prompt, oldName);
- }
-
-
- /**
- * This is called upon return from entering a new file name.
- * (that is, from either newCode or renameCode after the prompt)
- * This code is almost identical for both the newCode and renameCode
- * cases, so they're kept merged except for right in the middle
- * where they diverge.
- */
- public void nameCode(String newName) {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // if renaming to the same thing as before, just ignore.
- // also ignoring case here, because i don't want to write
- // a bunch of special stuff for each platform
- // (osx is case insensitive but preserving, windows insensitive,
- // *nix is sensitive and preserving.. argh)
- if (renamingCode && newName.equalsIgnoreCase(current.name)) {
- // exit quietly for the 'rename' case.
- // if it's a 'new' then an error will occur down below
- return;
- }
-
- // don't allow blank names
- if (newName.trim().equals("")) {
- return;
- }
-
- if (newName.trim().equals(".c") ||
- newName.trim().equals(".h") ||
- newName.trim().equals(".pde") ||
- newName.trim().equals(".cpp")) {
- return;
- }
-
- String newFilename = null;
- int newFlavor = 0;
-
- // separate into newName (no extension) and newFilename (with ext)
- // add .pde to file if it has no extension
- if (newName.endsWith(".pde")) {
- newFilename = newName;
- newName = newName.substring(0, newName.length() - 4);
- newFlavor = PDE;
-
- } else if (newName.endsWith(".c") || newName.endsWith(".cpp") ||
- newName.endsWith(".h")) {
- // don't show this error if creating a new tab
- if (renamingCode && (code[0] == current)) {
- Base.showWarning("Problem with rename",
- "The main .pde file cannot be .c, .cpp, or .h file.\n" +
- "(It may be time for your to graduate to a\n" +
- "\"real\" programming environment)", null);
- return;
- }
-
- newFilename = newName;
- if(newName.endsWith(".c")) {
- newName = newName.substring(0, newName.length() - 2);
- newFlavor = C;
- } if(newName.endsWith(".h")) {
- newName = newName.substring(0, newName.length() - 2);
- newFlavor = HEADER;
- } else if(newName.endsWith(".cpp")) {
- newName = newName.substring(0, newName.length() - 4);
- newFlavor = CPP;
- }
- } else {
- newFilename = newName + ".pde";
- newFlavor = PDE;
- }
-
- // dots are allowed for the .pde and .java, but not in the name
- // make sure the user didn't name things poo.time.pde
- // or something like that (nothing against poo time)
- if (newName.indexOf('.') != -1) {
- newName = Sketchbook.sanitizedName(newName);
- newFilename = newName + ((newFlavor == PDE) ? ".pde" : ".cpp");
- }
-
- // create the new file, new SketchCode object and load it
- File newFile = new File(folder, newFilename);
- if (newFile.exists()) { // yay! users will try anything
- Base.showMessage("Nope",
- "A file named \"" + newFile + "\" already exists\n" +
- "in \"" + folder.getAbsolutePath() + "\"");
- return;
- }
-
- File newFileHidden = new File(folder, newFilename + ".x");
- if (newFileHidden.exists()) {
- // don't let them get away with it if they try to create something
- // with the same name as something hidden
- Base.showMessage("No Way",
- "A hidden tab with the same name already exists.\n" +
- "Use \"Unhide\" to bring it back.");
- return;
- }
-
- if (renamingCode) {
- if (currentIndex == 0) {
- // get the new folder name/location
- File newFolder = new File(folder.getParentFile(), newName);
- if (newFolder.exists()) {
- Base.showWarning("Cannot Rename",
- "Sorry, a sketch (or folder) named " +
- "\"" + newName + "\" already exists.", null);
- return;
- }
-
- // unfortunately this can't be a "save as" because that
- // only copies the sketch files and the data folder
- // however this *will* first save the sketch, then rename
-
- // first get the contents of the editor text area
- if (current.modified) {
- current.program = editor.getText();
- try {
- // save this new SketchCode
- current.save();
- } catch (Exception e) {
- Base.showWarning("Error", "Could not rename the sketch. (0)", e);
- return;
- }
- }
-
- if (!current.file.renameTo(newFile)) {
- Base.showWarning("Error",
- "Could not rename \"" + current.file.getName() +
- "\" to \"" + newFile.getName() + "\"", null);
- return;
- }
-
- // save each of the other tabs because this is gonna be re-opened
- try {
- for (int i = 1; i < codeCount; i++) {
- //if (code[i].modified) code[i].save();
- code[i].save();
- }
- } catch (Exception e) {
- Base.showWarning("Error", "Could not rename the sketch. (1)", e);
- return;
- }
-
- // now rename the sketch folder and re-open
- boolean success = folder.renameTo(newFolder);
- if (!success) {
- Base.showWarning("Error", "Could not rename the sketch. (2)", null);
- return;
- }
- // if successful, set base properties for the sketch
-
- File mainFile = new File(newFolder, newName + ".pde");
- mainFilename = mainFile.getAbsolutePath();
-
- // having saved everything and renamed the folder and the main .pde,
- // use the editor to re-open the sketch to re-init state
- // (unfortunately this will kill positions for carets etc)
- editor.handleOpenUnchecked(mainFilename,
- currentIndex,
- editor.textarea.getSelectionStart(),
- editor.textarea.getSelectionEnd(),
- editor.textarea.getScrollPosition());
-
- // get the changes into the sketchbook menu
- // (re-enabled in 0115 to fix bug #332)
- editor.sketchbook.rebuildMenus();
-
- } else { // else if something besides code[0]
- if (!current.file.renameTo(newFile)) {
- Base.showWarning("Error",
- "Could not rename \"" + current.file.getName() +
- "\" to \"" + newFile.getName() + "\"", null);
- return;
- }
-
- // just reopen the class itself
- current.name = newName;
- current.file = newFile;
- current.flavor = newFlavor;
- }
-
- } else { // creating a new file
- try {
- newFile.createNewFile(); // TODO returns a boolean
- } catch (IOException e) {
- Base.showWarning("Error",
- "Could not create the file \"" + newFile + "\"\n" +
- "in \"" + folder.getAbsolutePath() + "\"", e);
- return;
- }
- SketchCode newCode = new SketchCode(newName, newFile, newFlavor);
- insertCode(newCode);
- }
-
- // sort the entries
- sortCode();
-
- // set the new guy as current
- setCurrent(newName + flavorExtensionsShown[newFlavor]);
-
- // update the tabs
- //editor.header.repaint();
-
- editor.header.rebuild();
-
- // force the update on the mac?
- Toolkit.getDefaultToolkit().sync();
- //editor.header.getToolkit().sync();
- }
-
-
- /**
- * Remove a piece of code from the sketch and from the disk.
- */
- public void deleteCode() {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // if read-only, give an error
- if (isReadOnly()) {
- // if the files are read-only, need to first do a "save as".
- Base.showMessage("Sketch is Read-Only",
- "Some files are marked \"read-only\", so you'll\n" +
- "need to re-save the sketch in another location,\n" +
- "and try again.");
- return;
- }
-
- // confirm deletion with user, yes/no
- Object[] options = { "OK", "Cancel" };
- String prompt = (currentIndex == 0) ?
- "Are you sure you want to delete this sketch?" :
- "Are you sure you want to delete \"" + current.name +
- flavorExtensionsShown[current.flavor] + "\"?";
- int result = JOptionPane.showOptionDialog(editor,
- prompt,
- "Delete",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE,
- null,
- options,
- options[0]);
- if (result == JOptionPane.YES_OPTION) {
- if (currentIndex == 0) {
- // need to unset all the modified flags, otherwise tries
- // to do a save on the handleNew()
-
- // delete the entire sketch
- Base.removeDir(folder);
-
- // get the changes into the sketchbook menu
- //sketchbook.rebuildMenus();
-
- // make a new sketch, and i think this will rebuild the sketch menu
- editor.handleNewUnchecked();
-
- } else {
- // delete the file
- if (!current.file.delete()) {
- Base.showMessage("Couldn't do it",
- "Could not delete \"" + current.name + "\".");
- return;
- }
-
- // remove code from the list
- removeCode(current);
-
- // just set current tab to the main tab
- setCurrent(0);
-
- // update the tabs
- editor.header.repaint();
- }
- }
- }
-
-
- protected void removeCode(SketchCode which) {
- // remove it from the internal list of files
- // resort internal list of files
- for (int i = 0; i < codeCount; i++) {
- if (code[i] == which) {
- for (int j = i; j < codeCount-1; j++) {
- code[j] = code[j+1];
- }
- codeCount--;
- return;
- }
- }
- System.err.println("removeCode: internal error.. could not find code");
- }
-
-
- public void hideCode() {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // if read-only, give an error
- if (isReadOnly()) {
- // if the files are read-only, need to first do a "save as".
- Base.showMessage("Sketch is Read-Only",
- "Some files are marked \"read-only\", so you'll\n" +
- "need to re-save the sketch in another location,\n" +
- "and try again.");
- return;
- }
-
- // don't allow hide of the main code
- // TODO maybe gray out the menu on setCurrent(0)
- if (currentIndex == 0) {
- Base.showMessage("Can't do that",
- "You cannot hide the main " +
- ".pde file from a sketch\n");
- return;
- }
-
- // rename the file
- File newFile = new File(current.file.getAbsolutePath() + ".x");
- if (!current.file.renameTo(newFile)) {
- Base.showWarning("Error",
- "Could not hide " +
- "\"" + current.file.getName() + "\".", null);
- return;
- }
- current.file = newFile;
-
- // move it to the hidden list
- if (hiddenCount == hidden.length) {
- SketchCode temp[] = new SketchCode[hiddenCount+1];
- System.arraycopy(hidden, 0, temp, 0, hiddenCount);
- hidden = temp;
- }
- hidden[hiddenCount++] = current;
-
- // remove it from the main list
- removeCode(current);
-
- // update the tabs
- setCurrent(0);
- editor.header.repaint();
- }
-
-
- public void unhideCode(String what) {
- SketchCode unhideCode = null;
- String name = what.substring(0,
- (what.indexOf(".") == -1 ? what.length() : what.indexOf(".")));
- String extension = what.indexOf(".") == -1 ? "" :
- what.substring(what.indexOf("."));
-
- for (int i = 0; i < hiddenCount; i++) {
- if (hidden[i].name.equals(name) &&
- Sketch.flavorExtensionsShown[hidden[i].flavor].equals(extension)) {
- //unhideIndex = i;
- unhideCode = hidden[i];
-
- // remove from the 'hidden' list
- for (int j = i; j < hiddenCount-1; j++) {
- hidden[j] = hidden[j+1];
- }
- hiddenCount--;
- break;
- }
- }
- //if (unhideIndex == -1) {
- if (unhideCode == null) {
- System.err.println("internal error: could find " + what + " to unhide.");
- return;
- }
- if (!unhideCode.file.exists()) {
- Base.showMessage("Can't unhide",
- "The file \"" + what + "\" no longer exists.");
- //System.out.println(unhideCode.file);
- return;
- }
- String unhidePath = unhideCode.file.getAbsolutePath();
- File unhideFile =
- new File(unhidePath.substring(0, unhidePath.length() - 2));
-
- if (!unhideCode.file.renameTo(unhideFile)) {
- Base.showMessage("Can't unhide",
- "The file \"" + what + "\" could not be" +
- "renamed and unhidden.");
- return;
- }
- unhideCode.file = unhideFile;
- insertCode(unhideCode);
- sortCode();
- setCurrent(unhideCode.name);
- editor.header.repaint();
- }
-
-
- /**
- * Sets the modified value for the code in the frontmost tab.
- */
- public void setModified(boolean state) {
- current.modified = state;
- calcModified();
- }
-
-
- public void calcModified() {
- modified = false;
- for (int i = 0; i < codeCount; i++) {
- if (code[i].modified) {
- modified = true;
- break;
- }
- }
- editor.header.repaint();
- }
-
-
- /**
- * Save all code in the current sketch.
- */
- public boolean save() throws IOException {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // first get the contents of the editor text area
- if (current.modified) {
- current.program = editor.getText();
- }
-
- // don't do anything if not actually modified
- //if (!modified) return false;
-
- if (isReadOnly()) {
- // if the files are read-only, need to first do a "save as".
- Base.showMessage("Sketch is read-only",
- "Some files are marked \"read-only\", so you'll\n" +
- "need to re-save this sketch to another location.");
- // if the user cancels, give up on the save()
- if (!saveAs()) return false;
- }
-
- for (int i = 0; i < codeCount; i++) {
- if (code[i].modified) code[i].save();
- }
- calcModified();
- return true;
- }
-
-
- /**
- * Handles 'Save As' for a sketch.
- *
- * This basically just duplicates the current sketch folder to
- * a new location, and then calls 'Save'. (needs to take the current
- * state of the open files and save them to the new folder..
- * but not save over the old versions for the old sketch..)
- *
- * Also removes the previously-generated .class and .jar files,
- * because they can cause trouble.
- */
- public boolean saveAs() throws IOException {
- // get new name for folder
- FileDialog fd = new FileDialog(editor,
- "Save sketch folder as...",
- FileDialog.SAVE);
- if (isReadOnly()) {
- // default to the sketchbook folder
- fd.setDirectory(Preferences.get("sketchbook.path"));
- } else {
- // default to the parent folder of where this was
- fd.setDirectory(folder.getParent());
- }
- fd.setFile(folder.getName());
-
- fd.show();
- String newParentDir = fd.getDirectory();
- String newName = fd.getFile();
-
- // user cancelled selection
- if (newName == null) return false;
- newName = Sketchbook.sanitizeName(newName);
-
- // make sure there doesn't exist a tab with that name already
- // (but allow it if it's just the main tab resaving itself.. oops)
- File codeAlready = new File(folder, newName + ".pde");
- if (codeAlready.exists() && (!newName.equals(name))) {
- Base.showMessage("Nope",
- "You can't save the sketch as \"" + newName + "\"\n" +
- "because the sketch already has a tab with that name.");
- return false;
- }
-
- // make sure there doesn't exist a tab with that name already
- File hiddenAlready = new File(folder, newName + ".pde.x");
- if (hiddenAlready.exists()) {
- Base.showMessage("Nope",
- "You can't save the sketch as \"" + newName + "\"\n" +
- "because the sketch already has a " +
- "hidden tab with that name.");
- return false;
- }
-
- // new sketch folder
- File newFolder = new File(newParentDir, newName);
-
- // make sure the paths aren't the same
- if (newFolder.equals(folder)) {
- Base.showWarning("You can't fool me",
- "The new sketch name and location are the same as\n" +
- "the old. I ain't not doin nuthin' not now.", null);
- return false;
- }
-
- // check to see if the user is trying to save this sketch
- // inside the same sketch
- try {
- String newPath = newFolder.getCanonicalPath() + File.separator;
- String oldPath = folder.getCanonicalPath() + File.separator;
-
- if (newPath.indexOf(oldPath) == 0) {
- Base.showWarning("How very Borges of you",
- "You cannot save the sketch into a folder\n" +
- "inside itself. This would go on forever.", null);
- return false;
- }
- } catch (IOException e) { }
-
- // if the new folder already exists, then need to remove
- // its contents before copying everything over
- // (user will have already been warned)
- if (newFolder.exists()) {
- Base.removeDir(newFolder);
- }
- // in fact, you can't do this on windows because the file dialog
- // will instead put you inside the folder, but it happens on osx a lot.
-
- // now make a fresh copy of the folder
- newFolder.mkdirs();
-
- // grab the contents of the current tab before saving
- // first get the contents of the editor text area
- if (current.modified) {
- current.program = editor.getText();
- }
-
- // save the other tabs to their new location
- for (int i = 1; i < codeCount; i++) {
- File newFile = new File(newFolder, code[i].file.getName());
- code[i].saveAs(newFile);
- }
-
- // save the hidden code to its new location
- for (int i = 0; i < hiddenCount; i++) {
- File newFile = new File(newFolder, hidden[i].file.getName());
- hidden[i].saveAs(newFile);
- }
-
- // re-copy the data folder (this may take a while.. add progress bar?)
- if (dataFolder.exists()) {
- File newDataFolder = new File(newFolder, "data");
- Base.copyDir(dataFolder, newDataFolder);
- }
-
- // re-copy the code folder
- if (codeFolder.exists()) {
- File newCodeFolder = new File(newFolder, "code");
- Base.copyDir(codeFolder, newCodeFolder);
- }
-
- // save the main tab with its new name
- File newFile = new File(newFolder, newName + ".pde");
- code[0].saveAs(newFile);
-
- editor.handleOpenUnchecked(newFile.getPath(),
- currentIndex,
- editor.textarea.getSelectionStart(),
- editor.textarea.getSelectionEnd(),
- editor.textarea.getScrollPosition());
-
- // Name changed, rebuild the sketch menus
- editor.sketchbook.rebuildMenusAsync();
-
- // let Editor know that the save was successful
- return true;
- }
-
-
- /**
- * Prompt the user for a new file to the sketch.
- * This could be .class or .jar files for the code folder,
- * .pde or .java files for the project,
- * or .dll, .jnilib, or .so files for the code folder
- */
- public void addFile() {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // if read-only, give an error
- if (isReadOnly()) {
- // if the files are read-only, need to first do a "save as".
- Base.showMessage("Sketch is Read-Only",
- "Some files are marked \"read-only\", so you'll\n" +
- "need to re-save the sketch in another location,\n" +
- "and try again.");
- return;
- }
-
- // get a dialog, select a file to add to the sketch
- String prompt =
- "Select an image or other data file to copy to your sketch";
- //FileDialog fd = new FileDialog(new Frame(), prompt, FileDialog.LOAD);
- FileDialog fd = new FileDialog(editor, prompt, FileDialog.LOAD);
- fd.show();
-
- String directory = fd.getDirectory();
- String filename = fd.getFile();
- if (filename == null) return;
-
- // copy the file into the folder. if people would rather
- // it move instead of copy, they can do it by hand
- File sourceFile = new File(directory, filename);
-
- // now do the work of adding the file
- addFile(sourceFile);
- }
-
-
- /**
- * Add a file to the sketch.
- *
- * .pde or .java files will be added to the sketch folder.
- * .jar, .class, .dll, .jnilib, and .so files will all
- * be added to the "code" folder.
- * All other files will be added to the "data" folder.
- *
- * If they don't exist already, the "code" or "data" folder
- * will be created.
- *
- * @return true if successful.
- */
- public boolean addFile(File sourceFile) {
- String filename = sourceFile.getName();
- File destFile = null;
- boolean addingCode = false;
-
- // if the file appears to be code related, drop it
- // into the code folder, instead of the data folder
- if (filename.toLowerCase().endsWith(".o") /*||
- filename.toLowerCase().endsWith(".jar") ||
- filename.toLowerCase().endsWith(".dll") ||
- filename.toLowerCase().endsWith(".jnilib") ||
- filename.toLowerCase().endsWith(".so") */ ) {
- //File codeFolder = new File(this.folder, "code");
- if (!codeFolder.exists()) codeFolder.mkdirs();
- destFile = new File(codeFolder, filename);
-
- } else if (filename.toLowerCase().endsWith(".pde") ||
- filename.toLowerCase().endsWith(".c") ||
- filename.toLowerCase().endsWith(".h") ||
- filename.toLowerCase().endsWith(".cpp")) {
- destFile = new File(this.folder, filename);
- addingCode = true;
-
- } else {
- //File dataFolder = new File(this.folder, "data");
- if (!dataFolder.exists()) dataFolder.mkdirs();
- destFile = new File(dataFolder, filename);
- }
-
- // make sure they aren't the same file
- if (!addingCode && sourceFile.equals(destFile)) {
- Base.showWarning("You can't fool me",
- "This file has already been copied to the\n" +
- "location where you're trying to add it.\n" +
- "I ain't not doin nuthin'.", null);
- return false;
- }
-
- // in case the user is "adding" the code in an attempt
- // to update the sketch's tabs
- if (!sourceFile.equals(destFile)) {
- try {
- Base.copyFile(sourceFile, destFile);
-
- } catch (IOException e) {
- Base.showWarning("Error adding file",
- "Could not add '" + filename +
- "' to the sketch.", e);
- return false;
- }
- }
-
- // make the tabs update after this guy is added
- if (addingCode) {
- String newName = destFile.getName();
- int newFlavor = -1;
- if (newName.toLowerCase().endsWith(".pde")) {
- newName = newName.substring(0, newName.length() - 4);
- newFlavor = PDE;
- } else if (newName.toLowerCase().endsWith(".c")) {
- newName = newName.substring(0, newName.length() - 2);
- newFlavor = C;
- } else if (newName.toLowerCase().endsWith(".h")) {
- newName = newName.substring(0, newName.length() - 2);
- newFlavor = HEADER;
- } else { // ".cpp"
- newName = newName.substring(0, newName.length() - 4);
- newFlavor = CPP;
- }
-
- // see also "nameCode" for identical situation
- SketchCode newCode = new SketchCode(newName, destFile, newFlavor);
- insertCode(newCode);
- sortCode();
- setCurrent(newName);
- editor.header.repaint();
- }
- return true;
- }
-
-
- public void importLibrary(String jarPath) {
- //System.out.println(jarPath);
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- //String list[] = Compiler.packageListFromClassPath(jarPath);
- FileFilter onlyHFiles = new FileFilter() {
- public boolean accept(File file) {
- return (file.getName()).endsWith(".h");
- }
- };
-
- File list[] = new File(jarPath).listFiles(onlyHFiles);
-
- // import statements into the main sketch file (code[0])
- // if the current code is a .java file, insert into current
- if (current.flavor == PDE) {
- setCurrent(0);
- }
- // could also scan the text in the file to see if each import
- // statement is already in there, but if the user has the import
- // commented out, then this will be a problem.
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < list.length; i++) {
- buffer.append("#include <");
- buffer.append(list[i].getName());
- buffer.append(">\n");
- }
- buffer.append('\n');
- buffer.append(editor.getText());
- editor.setText(buffer.toString(), 0, 0); // scroll to start
- setModified(true);
- }
-
-
- /**
- * Change what file is currently being edited.
- *
- *
store the String for the text of the current file.
- *
retrieve the String for the text of the new file.
- *
change the text that's visible in the text area
- *
- */
- public void setCurrent(int which) {
- // if current is null, then this is the first setCurrent(0)
- if ((currentIndex == which) && (current != null)) {
- return;
- }
-
- // get the text currently being edited
- if (current != null) {
- current.program = editor.getText();
- current.selectionStart = editor.textarea.getSelectionStart();
- current.selectionStop = editor.textarea.getSelectionEnd();
- current.scrollPosition = editor.textarea.getScrollPosition();
- }
-
- current = code[which];
- currentIndex = which;
- editor.setCode(current);
- //editor.setDocument(current.document,
- // current.selectionStart, current.selectionStop,
- // current.scrollPosition, current.undo);
-
- // set to the text for this file
- // 'true' means to wipe out the undo buffer
- // (so they don't undo back to the other file.. whups!)
- /*
- editor.setText(current.program,
- current.selectionStart, current.selectionStop,
- current.undo);
- */
-
- // set stored caret and scroll positions
- //editor.textarea.setScrollPosition(current.scrollPosition);
- //editor.textarea.select(current.selectionStart, current.selectionStop);
- //editor.textarea.setSelectionStart(current.selectionStart);
- //editor.textarea.setSelectionEnd(current.selectionStop);
-
- editor.header.rebuild();
- }
-
-
- /**
- * Internal helper function to set the current tab
- * based on a name (used by codeNew and codeRename).
- */
- protected void setCurrent(String findName) {
- SketchCode unhideCode = null;
- String name = findName.substring(0,
- (findName.indexOf(".") == -1 ? findName.length() : findName.indexOf(".")));
- String extension = findName.indexOf(".") == -1 ? "" :
- findName.substring(findName.indexOf("."));
-
- for (int i = 0; i < codeCount; i++) {
- if (name.equals(code[i].name) &&
- Sketch.flavorExtensionsShown[code[i].flavor].equals(extension)) {
- setCurrent(i);
- return;
- }
- }
- }
-
-
- /**
- * Cleanup temporary files used during a build/run.
- */
- protected void cleanup() {
- // if the java runtime is holding onto any files in the build dir, we
- // won't be able to delete them, so we need to force a gc here
- System.gc();
-
- // note that we can't remove the builddir itself, otherwise
- // the next time we start up, internal runs using Runner won't
- // work because the build dir won't exist at startup, so the classloader
- // will ignore the fact that that dir is in the CLASSPATH in run.sh
- Base.removeDescendants(tempBuildFolder);
- }
-
-
- /**
- * Preprocess, Compile, and Run the current code.
- *
- * There are three main parts to this process:
- *
- * (0. if not java, then use another 'engine'.. i.e. python)
- *
- * 1. do the p5 language preprocessing
- * this creates a working .java file in a specific location
- * better yet, just takes a chunk of java code and returns a
- * new/better string editor can take care of saving this to a
- * file location
- *
- * 2. compile the code from that location
- * catching errors along the way
- * placing it in a ready classpath, or .. ?
- *
- * 3. run the code
- * needs to communicate location for window
- * and maybe setup presentation space as well
- * run externally if a code folder exists,
- * or if more than one file is in the project
- *
- * X. afterwards, some of these steps need a cleanup function
- *
- */
- public boolean handleRun(Target target) throws RunnerException {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- current.program = editor.getText();
-
- // TODO record history here
- //current.history.record(program, SketchHistory.RUN);
-
- // if an external editor is being used, need to grab the
- // latest version of the code from the file.
- if (Preferences.getBoolean("editor.external")) {
- // history gets screwed by the open..
- //String historySaved = history.lastRecorded;
- //handleOpen(sketch);
- //history.lastRecorded = historySaved;
-
- // set current to null so that the tab gets updated
- // http://dev.processing.org/bugs/show_bug.cgi?id=515
- current = null;
- // nuke previous files and settings, just get things loaded
- load();
- }
-
- // in case there were any boogers left behind
- // do this here instead of after exiting, since the exit
- // can happen so many different ways.. and this will be
- // better connected to the dataFolder stuff below.
- cleanup();
-
- // make up a temporary class name to suggest.
- // name will only be used if the code is not in ADVANCED mode.
- String suggestedClassName =
- ("Temporary_" + String.valueOf((int) (Math.random() * 10000)) +
- "_" + String.valueOf((int) (Math.random() * 10000)));
-
- // handle preprocessing the main file's code
- //mainClassName = build(TEMP_BUILD_PATH, suggestedClassName);
- mainClassName =
- build(target, tempBuildFolder.getAbsolutePath(), suggestedClassName);
- size(tempBuildFolder.getAbsolutePath(), name);
- // externalPaths is magically set by build()
-
- if (!externalRuntime) { // only if not running externally already
- // copy contents of data dir into lib/build
- if (dataFolder.exists()) {
- // just drop the files in the build folder (pre-68)
- //Base.copyDir(dataDir, buildDir);
- // drop the files into a 'data' subfolder of the build dir
- try {
- Base.copyDir(dataFolder, new File(tempBuildFolder, "data"));
- } catch (IOException e) {
- e.printStackTrace();
- throw new RunnerException("Problem copying files from data folder");
- }
- }
- }
- return (mainClassName != null);
- }
-
-
- /**
- * Build all the code for this sketch.
- *
- * In an advanced program, the returned classname could be different,
- * which is why the className is set based on the return value.
- * A compilation error will burp up a RunnerException.
- *
- * @return null if compilation failed, main class name if not
- */
- protected String build(Target target, String buildPath, String suggestedClassName)
- throws RunnerException {
-
- // build unbuilt buildable libraries
- // completely independent from sketch, so run all the time
- editor.prepareLibraries();
-
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- String codeFolderPackages[] = null;
-
- String javaClassPath = System.getProperty("java.class.path");
- // remove quotes if any.. this is an annoying thing on windows
- if (javaClassPath.startsWith("\"") && javaClassPath.endsWith("\"")) {
- javaClassPath = javaClassPath.substring(1, javaClassPath.length() - 1);
- }
-
- classPath = buildPath +
- File.pathSeparator + Sketchbook.librariesClassPath +
- File.pathSeparator + javaClassPath;
- //System.out.println("cp = " + classPath);
-
- // figure out the contents of the code folder to see if there
- // are files that need to be added to the imports
- //File codeFolder = new File(folder, "code");
- if (codeFolder.exists()) {
- externalRuntime = true;
-
- //classPath += File.pathSeparator +
- //Compiler.contentsToClassPath(codeFolder);
- classPath =
- Compiler.contentsToClassPath(codeFolder) +
- File.pathSeparator + classPath;
-
- //codeFolderPackages = Compiler.packageListFromClassPath(classPath);
- //codeFolderPackages = Compiler.packageListFromClassPath(codeFolder);
- libraryPath = codeFolder.getAbsolutePath();
-
- // get a list of .jar files in the "code" folder
- // (class files in subfolders should also be picked up)
- String codeFolderClassPath =
- Compiler.contentsToClassPath(codeFolder);
- // get list of packages found in those jars
-// codeFolderPackages =
-// Compiler.packageListFromClassPath(codeFolderClassPath);
- //PApplet.println(libraryPath);
- //PApplet.println("packages:");
- //PApplet.printarr(codeFolderPackages);
-
- } else {
- // since using the special classloader,
- // run externally whenever there are extra classes defined
- //externalRuntime = (codeCount > 1);
- // this no longer appears to be true.. so scrapping for 0088
-
- // check to see if multiple files that include a .java file
- externalRuntime = false;
- for (int i = 0; i < codeCount; i++) {
- if (code[i].flavor == C || code[i].flavor == CPP) {
- externalRuntime = true;
- break;
- }
- }
-
- //codeFolderPackages = null;
- libraryPath = "";
- }
-
- // if 'data' folder is large, set to external runtime
- if (dataFolder.exists() &&
- Base.calcFolderSize(dataFolder) > 768 * 1024) { // if > 768k
- externalRuntime = true;
- }
-
-
- // 1. concatenate all .pde files to the 'main' pde
- // store line number for starting point of each code bit
-
- StringBuffer bigCode = new StringBuffer(code[0].program);
- int bigCount = countLines(code[0].program);
-
- for (int i = 1; i < codeCount; i++) {
- if (code[i].flavor == PDE) {
- code[i].preprocOffset = ++bigCount;
- bigCode.append('\n');
- bigCode.append(code[i].program);
- bigCount += countLines(code[i].program);
- code[i].preprocName = null; // don't compile me
- }
- }
-
- // since using the special classloader,
- // run externally whenever there are extra classes defined
-/* if ((bigCode.indexOf(" class ") != -1) ||
- (bigCode.indexOf("\nclass ") != -1)) {
- externalRuntime = true;
- }
-*/
- // if running in opengl mode, this is gonna be external
- //if (Preferences.get("renderer").equals("opengl")) {
- //externalRuntime = true;
- //}
-
- // 2. run preproc on that code using the sugg class name
- // to create a single .java file and write to buildpath
-
- String primaryClassName = null;
-
- PdePreprocessor preprocessor = new PdePreprocessor();
- try {
- // if (i != 0) preproc will fail if a pde file is not
- // java mode, since that's required
- String className =
- preprocessor.write(bigCode.toString(), buildPath,
- suggestedClassName, codeFolderPackages, target);
- if (className == null) {
- throw new RunnerException("Could not find main class");
- // this situation might be perfectly fine,
- // (i.e. if the file is empty)
- //System.out.println("No class found in " + code[i].name);
- //System.out.println("(any code in that file will be ignored)");
- //System.out.println();
-
- } else {
- code[0].preprocName = className + ".cpp";
- }
-
- // store this for the compiler and the runtime
- primaryClassName = className;
- //System.out.println("primary class " + primaryClassName);
-
- // check if the 'main' file is in java mode
- if ((PdePreprocessor.programType == PdePreprocessor.JAVA) ||
- (preprocessor.extraImports.length != 0)) {
- externalRuntime = true; // we in advanced mode now, boy
- }
-
- } catch (antlr.RecognitionException re) {
- // this even returns a column
- int errorFile = 0;
- int errorLine = re.getLine() - 1;
- for (int i = 1; i < codeCount; i++) {
- if ((code[i].flavor == PDE) &&
- (code[i].preprocOffset < errorLine)) {
- errorFile = i;
- }
- }
- errorLine -= code[errorFile].preprocOffset;
- errorLine -= preprocessor.prototypeCount;
- errorLine -= preprocessor.headerCount;
-
- throw new RunnerException(re.getMessage(), errorFile,
- errorLine, re.getColumn());
-
- } catch (antlr.TokenStreamRecognitionException tsre) {
- // while this seems to store line and column internally,
- // there doesn't seem to be a method to grab it..
- // so instead it's done using a regexp
- PatternMatcher matcher = new Perl5Matcher();
- PatternCompiler compiler = new Perl5Compiler();
- // line 3:1: unexpected char: 0xA0
- String mess = "^line (\\d+):(\\d+):\\s";
-
- Pattern pattern = null;
- try {
- pattern = compiler.compile(mess);
- } catch (MalformedPatternException e) {
- Base.showWarning("Internal Problem",
- "An internal error occurred while trying\n" +
- "to compile the sketch. Please report\n" +
- "this online at " +
- "https://developer.berlios.de/bugs/?group_id=3590",
- e);
- }
-
- PatternMatcherInput input =
- new PatternMatcherInput(tsre.toString());
- if (matcher.contains(input, pattern)) {
- MatchResult result = matcher.getMatch();
-
- int errorLine = Integer.parseInt(result.group(1).toString()) - 1;
- int errorColumn = Integer.parseInt(result.group(2).toString());
- int errorFile = 0;
- for (int i = 1; i < codeCount; i++) {
- if ((code[i].flavor == PDE) &&
- (code[i].preprocOffset < errorLine)) {
- errorFile = i;
- }
- }
- errorLine -= code[errorFile].preprocOffset;
- errorLine -= preprocessor.prototypeCount;
- errorLine -= preprocessor.headerCount;
-
- throw new RunnerException(tsre.getMessage(),
- errorFile, errorLine, errorColumn);
-
- } else {
- // this is bad, defaults to the main class.. hrm.
- throw new RunnerException(tsre.toString(), 0, -1, -1);
- }
-
- } catch (RunnerException pe) {
- // RunnerExceptions are caught here and re-thrown, so that they don't
- // get lost in the more general "Exception" handler below.
- throw pe;
-
- } catch (Exception ex) {
- // TODO better method for handling this?
- System.err.println("Uncaught exception type:" + ex.getClass());
- ex.printStackTrace();
- throw new RunnerException(ex.toString());
- }
-
- // grab the imports from the code just preproc'd
-
- importedLibraries = new Vector();
- String imports[] = preprocessor.extraImports;
- try {
- LibraryManager libraryManager = new LibraryManager();
- Collection libraries = libraryManager.getAll();
- for (Iterator i = libraries.iterator(); i.hasNext(); ) {
- Library library = (Library) i.next();
- File[] headerFiles = library.getHeaderFiles();
-
- for (int j = 0; j < headerFiles.length; j++)
- for (int k = 0; k < imports.length; k++)
- if (headerFiles[j].getName().equals(imports[k]) &&
- !importedLibraries.contains(library)) {
- importedLibraries.add(library);
- //System.out.println("Adding library " + library.getName());
- }
- }
- } catch (IOException e) {
- System.err.println("Error finding libraries:");
- e.printStackTrace();
- throw new RunnerException(e.getMessage());
- }
-
- //for (int i = 0; i < imports.length; i++) {
- /*
- // remove things up to the last dot
- String entry = imports[i].substring(0, imports[i].lastIndexOf('.'));
- //System.out.println("found package " + entry);
- File libFolder = (File) Sketchbook.importToLibraryTable.get(entry);
-
- if (libFolder == null) {
- //throw new RunnerException("Could not find library for " + entry);
- continue;
- }
-
- importedLibraries.add(libFolder);
- libraryPath += File.pathSeparator + libFolder.getAbsolutePath();
- */
- /*
- String list[] = libFolder.list();
- if (list != null) {
- for (int j = 0; j < list.length; j++) {
- // this might have a dll/jnilib/so packed,
- // so add it to the library path
- if (list[j].toLowerCase().endsWith(".jar")) {
- libraryPath += File.pathSeparator +
- libFolder.getAbsolutePath() + File.separator + list[j];
- }
- }
- }
- */
- //}
-
-
- // 3. then loop over the code[] and save each .java file
-
- for (int i = 0; i < codeCount; i++) {
- if (code[i].flavor == CPP || code[i].flavor == C || code[i].flavor == HEADER) {
- // no pre-processing services necessary for java files
- // just write the the contents of 'program' to a .java file
- // into the build directory. uses byte stream and reader/writer
- // shtuff so that unicode bunk is properly handled
- String filename = code[i].name + flavorExtensionsReal[code[i].flavor];
- try {
- Base.saveFile(code[i].program, new File(buildPath, filename));
- } catch (IOException e) {
- e.printStackTrace();
- throw new RunnerException("Problem moving " + filename +
- " to the build folder");
- }
- code[i].preprocName = filename;
- }
- }
-
- // compile the program. errors will happen as a RunnerException
- // that will bubble up to whomever called build().
- //
- // note: this has been changed to catch build exceptions, adjust
- // line number for number of included prototypes, and rethrow
-
- Compiler compiler = new Compiler();
- boolean success;
- try {
- success = compiler.compile(this, buildPath, target);
- } catch (RunnerException re) {
- throw new RunnerException(re.getMessage(),
- re.file,
- re.line - preprocessor.prototypeCount - preprocessor.headerCount,
- re.column);
- } catch (Exception ex) {
- // TODO better method for handling this?
- throw new RunnerException(ex.toString());
- }
- //System.out.println("success = " + success + " ... " + primaryClassName);
- return success ? primaryClassName : null;
- }
-
- protected void size(String buildPath, String suggestedClassName)
- throws RunnerException {
- long size = 0;
- long maxsize = Preferences.getInteger("boards." + Preferences.get("board") + ".upload.maximum_size");
- Sizer sizer = new Sizer(buildPath, suggestedClassName);
- try {
- size = sizer.computeSize();
- System.out.println("Binary sketch size: " + size + " bytes (of a " +
- maxsize + " byte maximum)");
- } catch (RunnerException e) {
- System.err.println("Couldn't determine program size: " + e.getMessage());
- }
-
- if (size > maxsize)
- throw new RunnerException(
- "Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.");
- }
-
- protected String upload(String buildPath, String suggestedClassName)
- throws RunnerException {
-
- Uploader uploader;
-
- // download the program
- //
- uploader = new AvrdudeUploader();
- // macos9 now officially broken.. see PdeCompilerJavac
- //PdeCompiler compiler =
- // ((PdeBase.platform == PdeBase.MACOS9) ?
- // new PdeCompilerJavac(buildPath, className, this) :
- // new PdeCompiler(buildPath, className, this));
-
- // run the compiler, and funnel errors to the leechErr
- // which is a wrapped around
- // (this will catch and parse errors during compilation
- // the messageStream will call message() for 'compiler')
- //MessageStream messageStream = new MessageStream(downloader);
- //PrintStream leechErr = new PrintStream(messageStream);
- //boolean result = compiler.compileJava(leechErr);
- //return compiler.compileJava(leechErr);
- boolean success =
- uploader.uploadUsingPreferences(buildPath, suggestedClassName);
-
- return success ? suggestedClassName : null;
- }
-
-
- protected int countLines(String what) {
- char c[] = what.toCharArray();
- int count = 0;
- for (int i = 0; i < c.length; i++) {
- if (c[i] == '\n') count++;
- }
- return count;
- }
-
-
- /**
- * Initiate export to applet.
- *
- * +-------------------------------------------------------+
- * + +
- * + Export to: [ Applet (for the web) + ] [ OK ] +
- * + +
- * + > Advanced +
- * + +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Version: [ Java 1.1 + ] +
- * + +
- * + Recommended version of Java when exporting applets. +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Version: [ Java 1.3 + ] +
- * + +
- * + Java 1.3 is not recommended for applets, +
- * + unless you are using features that require it. +
- * + Using a version of Java other than 1.1 will require +
- * + your Windows users to install the Java Plug-In, +
- * + and your Macintosh users to be running OS X. +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Version: [ Java 1.4 + ] +
- * + +
- * + identical message as 1.3 above... +
- * + +
- * +-------------------------------------------------------+
- *
- */
- public boolean exportApplet(Target target) throws RunnerException {
- // make sure the user didn't hide the sketch folder
- ensureExistence();
-
- // fix for issue posted on the board. make sure that the code
- // is reloaded when exporting and an external editor is being used.
- if (Preferences.getBoolean("editor.external")) {
- // nuke previous files and settings
- load();
- } else {
- current.program = editor.getText();
- }
-
- zipFileContents = new Hashtable();
-
- // nuke the old applet folder because it can cause trouble
- File appletFolder = new File(folder, "applet");
- Base.removeDir(appletFolder);
- appletFolder.mkdirs();
-
- // build the sketch
- String foundName = build(target, appletFolder.getPath(), name);
- size(appletFolder.getPath(), name);
- foundName = upload(appletFolder.getPath(), name);
- // (already reported) error during export, exit this function
- if (foundName == null) return false;
-
- // if name != exportSketchName, then that's weirdness
- // BUG unfortunately, that can also be a bug in the preproc :(
- if (!name.equals(foundName)) {
- Base.showWarning("Error during export",
- "Sketch name is " + name + " but the sketch\n" +
- "name in the code was " + foundName, null);
- return false;
- }
-
-/* int wide = PApplet.DEFAULT_WIDTH;
- int high = PApplet.DEFAULT_HEIGHT;
- String renderer = "";
-
- PatternMatcher matcher = new Perl5Matcher();
- PatternCompiler compiler = new Perl5Compiler();
-
- // this matches against any uses of the size() function,
- // whether they contain numbers of variables or whatever.
- // this way, no warning is shown if size() isn't actually
- // used in the applet, which is the case especially for
- // beginners that are cutting/pasting from the reference.
- // modified for 83 to match size(XXX, ddd so that it'll
- // properly handle size(200, 200) and size(200, 200, P3D)
- String sizing =
- // match the renderer string as well
- "[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+),?\\s*([^\\)]*)\\s*\\)";
- // match just the width and height
- //"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+)(.*)\\)";
- Pattern pattern = compiler.compile(sizing);
-
- // adds a space at the beginning, in case size() is the very
- // first thing in the program (very common), since the regexp
- // needs to check for things in front of it.
- PatternMatcherInput input =
- new PatternMatcherInput(" " + scrubComments(code[0].program));
- if (matcher.contains(input, pattern)) {
- MatchResult result = matcher.getMatch();
-
- try {
- wide = Integer.parseInt(result.group(1).toString());
- high = Integer.parseInt(result.group(2).toString());
-
- renderer = result.group(3).toString(); //.trim();
-
- } catch (NumberFormatException e) {
- // found a reference to size, but it didn't
- // seem to contain numbers
- final String message =
- "The size of this applet could not automatically be\n" +
- "determined from your code. You'll have to edit the\n" +
- "HTML file to set the size of the applet.";
-
- Base.showWarning("Could not find applet size", message, null);
- }
- } // else no size() command found
-
- // originally tried to grab this with a regexp matcher,
- // but it wouldn't span over multiple lines for the match.
- // this could prolly be forced, but since that's the case
- // better just to parse by hand.
- StringBuffer dbuffer = new StringBuffer();
- String lines[] = PApplet.split(code[0].program, '\n');
- for (int i = 0; i < lines.length; i++) {
- if (lines[i].trim().startsWith("/**")) { // this is our comment
-*/ // some smartass put the whole thing on the same line
- //if (lines[j].indexOf("*/") != -1) break;
-
-// for (int j = i+1; j < lines.length; j++) {
-// if (lines[j].trim().endsWith("*/")) {
- // remove the */ from the end, and any extra *s
- // in case there's also content on this line
- // nah, don't bother.. make them use the three lines
-// break;
-// }
-
-/* int offset = 0;
- while ((offset < lines[j].length()) &&
- ((lines[j].charAt(offset) == '*') ||
- (lines[j].charAt(offset) == ' '))) {
- offset++;
- }
- // insert the return into the html to help w/ line breaks
- dbuffer.append(lines[j].substring(offset) + "\n");
- }
- }
- }
- String description = dbuffer.toString();
-
- StringBuffer sources = new StringBuffer();
- for (int i = 0; i < codeCount; i++) {
- sources.append("" +
- code[i].name + " ");
- }
-
- File htmlOutputFile = new File(appletFolder, "index.html");
- FileOutputStream fos = new FileOutputStream(htmlOutputFile);
- PrintStream ps = new PrintStream(fos);
-
- // @@sketch@@, @@width@@, @@height@@, @@archive@@, @@source@@
- // and now @@description@@
-
- InputStream is = null;
- // if there is an applet.html file in the sketch folder, use that
- File customHtml = new File(folder, "applet.html");
- if (customHtml.exists()) {
- is = new FileInputStream(customHtml);
- }
- if (is == null) {
- is = Base.getStream("applet.html");
- }
-
- // copy the loading gif to the applet
- String LOADING_IMAGE = "loading.gif";
- File loadingImage = new File(folder, LOADING_IMAGE);
- if (!loadingImage.exists()) {
- loadingImage = new File("lib", LOADING_IMAGE);
- }
- Base.copyFile(loadingImage, new File(appletFolder, LOADING_IMAGE));
-*/
- // copy the source files to the target, since we like
- // to encourage people to share their code
- for (int i = 0; i < codeCount; i++) {
- try {
- Base.copyFile(code[i].file,
- new File(appletFolder, code[i].file.getName()));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
-/* // create new .jar file
- FileOutputStream zipOutputFile =
- new FileOutputStream(new File(appletFolder, name + ".jar"));
- ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
- ZipEntry entry;
- archives.append(name + ".jar");
-
- // add the manifest file
- addManifest(zos);
-
- // add the contents of the code folder to the jar
- // unpacks all jar files, unless multi jar files selected in prefs
- if (codeFolder.exists()) {
- String includes = Compiler.contentsToClassPath(codeFolder);
- packClassPathIntoZipFile(includes, zos);
- }
-
- // add contents of 'library' folders to the jar file
- // if a file called 'export.txt' is in there, it contains
- // a list of the files that should be exported.
- // otherwise, all files are exported.
- Enumeration en = importedLibraries.elements();
- while (en.hasMoreElements()) {
- // in the list is a File object that points the
- // library sketch's "library" folder
- File libraryFolder = (File)en.nextElement();
- File exportSettings = new File(libraryFolder, "export.txt");
- String exportList[] = null;
- if (exportSettings.exists()) {
- String info[] = Base.loadStrings(exportSettings);
- for (int i = 0; i < info.length; i++) {
- if (info[i].startsWith("applet")) {
- int idx = info[i].indexOf('='); // get applet= or applet =
- String commas = info[i].substring(idx+1).trim();
- exportList = PApplet.split(commas, ", ");
- }
- }
- } else {
- exportList = libraryFolder.list();
- }
- for (int i = 0; i < exportList.length; i++) {
- if (exportList[i].equals(".") ||
- exportList[i].equals("..")) continue;
-
- exportList[i] = PApplet.trim(exportList[i]);
- if (exportList[i].equals("")) continue;
-
- File exportFile = new File(libraryFolder, exportList[i]);
- if (!exportFile.exists()) {
- System.err.println("File " + exportList[i] + " does not exist");
-
- } else if (exportFile.isDirectory()) {
- System.err.println("Ignoring sub-folder \"" + exportList[i] + "\"");
-
- } else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
- exportFile.getName().toLowerCase().endsWith(".jar")) {
- if (separateJar) {
- String exportFilename = exportFile.getName();
- Base.copyFile(exportFile, new File(appletFolder, exportFilename));
- if (renderer.equals("OPENGL") &&
- exportFilename.indexOf("natives") != -1) {
- // don't add these to the archives list
- } else {
- archives.append("," + exportFilename);
- }
- } else {
- packClassPathIntoZipFile(exportFile.getAbsolutePath(), zos);
- }
-
- } else { // just copy the file over.. prolly a .dll or something
- Base.copyFile(exportFile,
- new File(appletFolder, exportFile.getName()));
- }
- }
- }
-*/
-/* String bagelJar = "lib/core.jar";
- packClassPathIntoZipFile(bagelJar, zos);
- }
-
- // files to include from data directory
- // TODO this needs to be recursive
- if (dataFolder.exists()) {
- String dataFiles[] = dataFolder.list();
- for (int i = 0; i < dataFiles.length; i++) {
- // don't export hidden files
- // skipping dot prefix removes all: . .. .DS_Store
- if (dataFiles[i].charAt(0) == '.') continue;
-
- entry = new ZipEntry(dataFiles[i]);
- zos.putNextEntry(entry);
- zos.write(Base.grabFile(new File(dataFolder, dataFiles[i])));
- zos.closeEntry();
- }
- }
-
- // add the project's .class files to the jar
- // just grabs everything from the build directory
- // since there may be some inner classes
- // (add any .class files from the applet dir, then delete them)
- // TODO this needs to be recursive (for packages)
- String classfiles[] = appletFolder.list();
- for (int i = 0; i < classfiles.length; i++) {
- if (classfiles[i].endsWith(".class")) {
- entry = new ZipEntry(classfiles[i]);
- zos.putNextEntry(entry);
- zos.write(Base.grabFile(new File(appletFolder, classfiles[i])));
- zos.closeEntry();
- }
- }
-*/
- String classfiles[] = appletFolder.list();
- // remove the .class files from the applet folder. if they're not
- // removed, the msjvm will complain about an illegal access error,
- // since the classes are outside the jar file.
- for (int i = 0; i < classfiles.length; i++) {
- if (classfiles[i].endsWith(".class")) {
- File deadguy = new File(appletFolder, classfiles[i]);
- if (!deadguy.delete()) {
- Base.showWarning("Could not delete",
- classfiles[i] + " could not \n" +
- "be deleted from the applet folder. \n" +
- "You'll need to remove it by hand.", null);
- }
- }
- }
-
- // close up the jar file
-/* zos.flush();
- zos.close();
-*/
- if(Preferences.getBoolean("uploader.open_folder"))
- Base.openFolder(appletFolder);
- return true;
- }
-
-
- static public String scrubComments(String what) {
- char p[] = what.toCharArray();
-
- int index = 0;
- while (index < p.length) {
- // for any double slash comments, ignore until the end of the line
- if ((p[index] == '/') &&
- (index < p.length - 1) &&
- (p[index+1] == '/')) {
- p[index++] = ' ';
- p[index++] = ' ';
- while ((index < p.length) &&
- (p[index] != '\n')) {
- p[index++] = ' ';
- }
-
- // check to see if this is the start of a new multiline comment.
- // if it is, then make sure it's actually terminated somewhere.
- } else if ((p[index] == '/') &&
- (index < p.length - 1) &&
- (p[index+1] == '*')) {
- p[index++] = ' ';
- p[index++] = ' ';
- boolean endOfRainbow = false;
- while (index < p.length - 1) {
- if ((p[index] == '*') && (p[index+1] == '/')) {
- p[index++] = ' ';
- p[index++] = ' ';
- endOfRainbow = true;
- break;
-
- } else {
- index++;
- }
- }
- if (!endOfRainbow) {
- throw new RuntimeException("Missing the */ from the end of a " +
- "/* comment */");
- }
- } else { // any old character, move along
- index++;
- }
- }
- return new String(p);
- }
-
-
- /**
- * Export to application.
- *
- * +-------------------------------------------------------+
- * + +
- * + Export to: [ Application + ] [ OK ] +
- * + +
- * + > Advanced +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Version: [ Java 1.1 + ] +
- * + +
- * + Not much point to using Java 1.1 for applications. +
- * + To run applications, all users will have to +
- * + install Java, in which case they'll most likely +
- * + have version 1.3 or later. +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Version: [ Java 1.3 + ] +
- * + +
- * + Java 1.3 is the recommended setting for exporting +
- * + applications. Applications will run on any Windows +
- * + or Unix machine with Java installed. Mac OS X has +
- * + Java installed with the operation system, so there +
- * + is no additional installation will be required. +
- * + +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + +
- * + Platform: [ Mac OS X + ] <-- defaults to current platform
- * + +
- * + Exports the application as a double-clickable +
- * + .app package, compatible with Mac OS X. +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Platform: [ Windows + ] +
- * + +
- * + Exports the application as a double-clickable +
- * + .exe and a handful of supporting files. +
- * + - - - - - - - - - - - - - - - - - - - - - - - - - - - +
- * + Platform: [ jar file + ] +
- * + +
- * + A jar file can be used on any platform that has +
- * + Java installed. Simply doube-click the jar (or type +
- * + "java -jar sketch.jar" at a command prompt) to run +
- * + the application. It is the least fancy method for +
- * + exporting. +
- * + +
- * +-------------------------------------------------------+
- *
- */
- public boolean exportApplication() {
- return true;
- }
-
-
-/* public void addManifest(ZipOutputStream zos) throws IOException {
- ZipEntry entry = new ZipEntry("META-INF/MANIFEST.MF");
- zos.putNextEntry(entry);
-
- String contents =
- "Manifest-Version: 1.0\n" +
- "Created-By: Processing " + Base.VERSION_NAME + "\n" +
- "Main-Class: " + name + "\n"; // TODO not package friendly
- zos.write(contents.getBytes());
- zos.closeEntry();
-*/
- /*
- for (int i = 0; i < bagelClasses.length; i++) {
- if (!bagelClasses[i].endsWith(".class")) continue;
- entry = new ZipEntry(bagelClasses[i]);
- zos.putNextEntry(entry);
- zos.write(Base.grabFile(new File(exportDir + bagelClasses[i])));
- zos.closeEntry();
- }
- */
-/* }
-*/
-
- /**
- * Slurps up .class files from a colon (or semicolon on windows)
- * separated list of paths and adds them to a ZipOutputStream.
- */
-/* public void packClassPathIntoZipFile(String path,
- ZipOutputStream zos)
- throws IOException {
- String pieces[] = PApplet.split(path, File.pathSeparatorChar);
-
- for (int i = 0; i < pieces.length; i++) {
- if (pieces[i].length() == 0) continue;
-
- // is it a jar file or directory?
- if (pieces[i].toLowerCase().endsWith(".jar") ||
- pieces[i].toLowerCase().endsWith(".zip")) {
- try {
- ZipFile file = new ZipFile(pieces[i]);
- Enumeration entries = file.entries();
- while (entries.hasMoreElements()) {
- ZipEntry entry = (ZipEntry) entries.nextElement();
- if (entry.isDirectory()) {
- // actually 'continue's for all dir entries
-
- } else {
- String entryName = entry.getName();
- // ignore contents of the META-INF folders
- if (entryName.indexOf("META-INF") == 0) continue;
-
- // don't allow duplicate entries
- if (zipFileContents.get(entryName) != null) continue;
- zipFileContents.put(entryName, new Object());
-
- ZipEntry entree = new ZipEntry(entryName);
-
- zos.putNextEntry(entree);
- byte buffer[] = new byte[(int) entry.getSize()];
- InputStream is = file.getInputStream(entry);
-
- int offset = 0;
- int remaining = buffer.length;
- while (remaining > 0) {
- int count = is.read(buffer, offset, remaining);
- offset += count;
- remaining -= count;
- }
-
- zos.write(buffer);
- zos.flush();
- zos.closeEntry();
- }
- }
- } catch (IOException e) {
- System.err.println("Error in file " + pieces[i]);
- e.printStackTrace();
- }
- } else { // not a .jar or .zip, prolly a directory
- File dir = new File(pieces[i]);
- // but must be a dir, since it's one of several paths
- // just need to check if it exists
- if (dir.exists()) {
- packClassPathIntoZipFileRecursive(dir, null, zos);
- }
- }
- }
- }
-*/
-
- /**
- * Continue the process of magical exporting. This function
- * can be called recursively to walk through folders looking
- * for more goodies that will be added to the ZipOutputStream.
- */
-/* static public void packClassPathIntoZipFileRecursive(File dir,
- String sofar,
- ZipOutputStream zos)
- throws IOException {
- String files[] = dir.list();
- for (int i = 0; i < files.length; i++) {
- // ignore . .. and .DS_Store
- if (files[i].charAt(0) == '.') continue;
-
- File sub = new File(dir, files[i]);
- String nowfar = (sofar == null) ?
- files[i] : (sofar + "/" + files[i]);
-
- if (sub.isDirectory()) {
- packClassPathIntoZipFileRecursive(sub, nowfar, zos);
-
- } else {
- // don't add .jar and .zip files, since they only work
- // inside the root, and they're unpacked
- if (!files[i].toLowerCase().endsWith(".jar") &&
- !files[i].toLowerCase().endsWith(".zip") &&
- files[i].charAt(0) != '.') {
- ZipEntry entry = new ZipEntry(nowfar);
- zos.putNextEntry(entry);
- zos.write(Base.grabFile(sub));
- zos.closeEntry();
- }
- }
- }
- }
-*/
-
- /**
- * Make sure the sketch hasn't been moved or deleted by some
- * nefarious user. If they did, try to re-create it and save.
- * Only checks to see if the main folder is still around,
- * but not its contents.
- */
- protected void ensureExistence() {
- if (folder.exists()) return;
-
- Base.showWarning("Sketch Disappeared",
- "The sketch folder has disappeared.\n " +
- "Will attempt to re-save in the same location,\n" +
- "but anything besides the code will be lost.", null);
- try {
- folder.mkdirs();
- modified = true;
-
- for (int i = 0; i < codeCount; i++) {
- code[i].save(); // this will force a save
- }
- for (int i = 0; i < hiddenCount; i++) {
- hidden[i].save(); // this will force a save
- }
- calcModified();
-
- } catch (Exception e) {
- Base.showWarning("Could not re-save sketch",
- "Could not properly re-save the sketch. " +
- "You may be in trouble at this point,\n" +
- "and it might be time to copy and paste " +
- "your code to another text editor.", e);
- }
- }
-
-
- /**
- * Returns true if this is a read-only sketch. Used for the
- * examples directory, or when sketches are loaded from read-only
- * volumes or folders without appropriate permissions.
- */
- public boolean isReadOnly() {
- String apath = folder.getAbsolutePath();
- if (apath.startsWith(Sketchbook.examplesPath) ||
- apath.startsWith(Sketchbook.librariesPath)) {
- return true;
-
- // canWrite() doesn't work on directories
- //} else if (!folder.canWrite()) {
- } else {
- // check to see if each modified code file can be written to
- for (int i = 0; i < codeCount; i++) {
- if (code[i].modified &&
- !code[i].file.canWrite() &&
- code[i].file.exists()) {
- //System.err.println("found a read-only file " + code[i].file);
- return true;
- }
- }
- //return true;
- }
- return false;
- }
-
-
- /**
- * Returns path to the main .pde file for this sketch.
- */
- public String getMainFilePath() {
- return code[0].file.getAbsolutePath();
- }
-
-
- public void prevCode() {
- int prev = currentIndex - 1;
- if (prev < 0) prev = codeCount-1;
- setCurrent(prev);
- }
-
-
- public void nextCode() {
- setCurrent((currentIndex + 1) % codeCount);
- }
-}
diff --git a/app/SketchCode.java b/app/SketchCode.java
deleted file mode 100644
index d923ed31d..000000000
--- a/app/SketchCode.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- mode: jde; 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-05 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.io.*;
-import javax.swing.text.*;
-import javax.swing.undo.*;
-
-
-public class SketchCode {
- /** Pretty name (no extension), not the full file name */
- public String name;
-
- /** File object for where this code is located */
- public File file;
-
- /** Type of code in this tab, Sketch.PDE or Sketch.JAVA */
- public int flavor;
-
- /** Text of the program text for this tab */
- public String program;
-
- /** Document object for this tab */
- public SyntaxDocument document;
-
- /** Undo Manager for this tab, each tab keeps track of their own */
- public UndoManager undo; // = new UndoManager();
-
- // saved positions from last time this tab was used
- public int selectionStart;
- public int selectionStop;
- public int scrollPosition;
-
- public boolean modified;
- //SketchHistory history; // TODO add history information
-
- String preprocName; // name of .java file after preproc
- int preprocOffset; // where this code starts relative to the concat'd code
-
-
- public SketchCode(String name, File file, int flavor) {
- this.name = name;
- this.file = file;
- this.flavor = flavor;
-
- try {
- load();
- } catch (IOException e) {
- System.err.println("error while loading code " + name);
- }
- }
-
-
- /**
- * Load this piece of code from a file.
- */
- public void load() throws IOException {
- program = Base.loadFile(file);
- modified = 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);
- modified = false;
- }
-
-
- /**
- * Save this file to another location, used by Sketch.saveAs()
- */
- public void saveAs(File newFile) throws IOException {
- Base.saveFile(program, newFile);
- }
-}
diff --git a/app/SketchHistory.java b/app/SketchHistory.java
deleted file mode 100644
index 38f194973..000000000
--- a/app/SketchHistory.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- SketchHistory - handler for storing history information about a project
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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
-*/
-
-
-/*
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.*;
-
-
-public class SketchHistory {
- Editor editor;
-
- // why things have been saved for history
- static final int RUN = 5;
- static final int SAVE = 6;
- static final int AUTOSAVE = 7;
- static final int BEAUTIFY = 8;
-
- static final String HISTORY_SEPARATOR =
- "#################################################";
-
- JMenu menu;
-
- // true if the sketch is read-only,
- // meaning that no history will be recorded
- boolean readOnlySketch;
-
- File historyFile;
- String lastRecorded;
-
- ActionListener menuListener;
-
-
- //public SketchHistory(Editor editor) {
- //this.editor = editor;
- //}
-
- public SketchHistory(Sketch sketch) {
- menu = new JMenu("History");
-
- menuListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- retrieve(e.getActionCommand());
- }
- };
- }
-
-
-
- /// Set the path for the current sketch
-
- public void setPath(String path, boolean readOnlySketch) {
- this.readOnlySketch = true;
-
- if (readOnlySketch) return;
- historyFile = new File(path, "history.gz");
- }
-
-
- public void attachMenu(JMenu parent) {
- //if (Preferences.getBoolean("history.recording")) {
- parent.add(menu);
-
- // should leave enabled, since can still get old history
- // even if the new stuff isn't being recorded
- //menu.setEnabled(Preferences.getBoolean("history.recording"));
- //}
- }
-
-
- /// Check to see if history should be recorded.
- /// mode is RUN, SAVE, AUTOSAVE, or BEAUTIFY
- public void record(String program, int mode) {
- if (readOnlySketch) return;
-
- if (!Preferences.getBoolean("history.recording")) return;
-
- if ((lastRecorded != null) &&
- (lastRecorded.equals(program))) return;
-
- String modeStr = null;
- switch (mode) {
- case RUN: modeStr = "run"; break;
- case SAVE: modeStr = "save"; break;
- case AUTOSAVE: modeStr = "autosave"; break;
- case BEAUTIFY: modeStr = "beautify"; break;
- }
-
- try {
- boolean noPreviousHistory = false;
-
- ByteArrayOutputStream old = null;
- if (historyFile.exists()) {
- InputStream oldStream = new GZIPInputStream(new BufferedInputStream(new FileInputStream(historyFile)));
- old = new ByteArrayOutputStream();
-
- int c = oldStream.read();
- while (c != -1) {
- old.write(c);
- c = oldStream.read();
- }
- //return out.toByteArray();
- oldStream.close();
-
- } else {
- noPreviousHistory = true; // rebuild menu
- }
-
- OutputStream historyStream =
- new GZIPOutputStream(new FileOutputStream(historyFile));
-
- if (old != null) {
- historyStream.write(old.toByteArray());
- }
- PrintWriter historyWriter =
- new PrintWriter(new OutputStreamWriter(historyStream));
-
- historyWriter.println();
- historyWriter.println(HISTORY_SEPARATOR);
-
- Calendar now = Calendar.getInstance();
- // 2002 06 18 11 43 29
- // when listing, study for descrepancies.. if all are
- // 2002, then don't list the year and soforth.
- // for the other end, if all minutes are unique,
- // then don't show seconds
- int year = now.get(Calendar.YEAR);
- int month = now.get(Calendar.MONTH) + 1;
- int day = now.get(Calendar.DAY_OF_MONTH);
- int hour = now.get(Calendar.HOUR_OF_DAY);
- int minute = now.get(Calendar.MINUTE);
- int second = now.get(Calendar.SECOND);
- String parseDate = year + " " + month + " " + day + " " +
- hour + " " + minute + " " + second;
-
- String readableDate = now.getTime().toString();
-
- // increment this so sketchbook won't be mangled
- // each time this format has to change
- String historyVersion = "1";
- //Date date = new Date();
- //String datestamp = date.toString();
-
- historyWriter.println(historyVersion + " " + modeStr + " - " +
- parseDate + " - " + readableDate);
- historyWriter.println();
- historyWriter.println(program);
- historyWriter.flush(); // ??
- lastRecorded = program;
-
- //JMenuItem menuItem = new JMenuItem(modeStr + " - " + readableDate);
- JMenuItem menuItem = new JMenuItem(modeStr + " - " + readableDate);
- menuItem.addActionListener(menuListener);
- menu.insert(menuItem, 2);
-
- historyWriter.flush();
- historyWriter.close();
-
- if (noPreviousHistory) {
- // to get add the actual menu, to get the 'clear' item in there
- //rebuildMenu(historyFile.getPath());
- rebuildMenu();
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
-
- public void retrieve(String selection) {
- //System.out.println("sel '" + selection + "'");
- String readableDate =
- selection.substring(selection.indexOf("-") + 2);
-
- // make history for the current guy
- record(editor.textarea.getText(), AUTOSAVE);
- // mark editor text as having been edited
-
- try {
- BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(historyFile))));
- String line = null;
-
- int historyCount = 0;
- String historyList[] = new String[100];
-
- try {
- boolean found = false;
- while ((line = reader.readLine()) != null) {
- //System.out.println("->" + line);
- if (line.equals(HISTORY_SEPARATOR)) {
- line = reader.readLine();
- if (line.indexOf(readableDate) != -1) { // this is the one
- found = true;
- break;
- }
- }
- }
- if (found) {
- // read lines until the next separator
- line = reader.readLine(); // ignored
- //String sep = System.getProperty("line.separator");
- StringBuffer buffer = new StringBuffer();
- while ((line = reader.readLine()) != null) {
- if (line.equals(HISTORY_SEPARATOR)) break;
- //textarea.append(line + sep);
- //buffer.append(line + sep); // JTextPane wants only \n going in
- buffer.append(line + "\n");
- //System.out.println("'" + line + "'");
- }
- //textarea.editorSetText(buffer.toString());
- editor.changeText(buffer.toString(), true);
- lastRecorded = editor.textarea.getText();
- editor.setSketchModified(false);
-
- } else {
- System.err.println("couldn't find history entry for " +
- "'" + readableDate + "'");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
-
-// class HistoryMenuListener implements ActionListener {
-// public void actionPerformed(ActionEvent e) {
-// editor.selectHistory(e.getActionCommand);
-// }
-// }
-
-
- //public void rebuildHistoryMenu(String path) {
- //rebuildHistoryMenu(historyMenu, path);
- //}
-
-
- //public void rebuildHistoryMenu(Menu menu, String path) {
- public void rebuildMenu() { //String path) {
- //if (!recordingHistory) return;
- //if (!Preferences.getBoolean("history.recording")) return;
-
- menu.removeAll();
-
- //File hfile = new File(path);
- //if (!hfile.exists()) return; // no history yet
- if (!historyFile.exists()) return;
-
- JMenuItem item = new JMenuItem("Clear History");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (!historyFile.delete()) {
- //System.err.println("couldn't erase history");
- Base.showWarning("History Problem",
- "Could not erase history", null);
- }
- rebuildMenu();
- //SketchHistory.this.rebuildMenu(historyFile.getPath());
- }
- });
- menu.add(item);
- menu.addSeparator();
-
- try {
- BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(historyFile))));
- String line = null;
-
- int historyCount = 0;
- String historyList[] = new String[100];
-
- try {
- while ((line = reader.readLine()) != null) {
- //while (line = reader.readLine()) {
- //while (true) { line = reader.readLine();
- //if (line == null) continue;
- //System.out.println("line: " + line);
- if (line.equals(HISTORY_SEPARATOR)) {
- // next line is the good stuff
- line = reader.readLine();
- int version =
- Integer.parseInt(line.substring(0, line.indexOf(' ')));
- if (version == 1) {
- String whysub = line.substring(2); // after "1 "
- String why = whysub.substring(0, whysub.indexOf(" -"));
- //System.out.println("'" + why + "'");
-
- String readable = line.substring(line.lastIndexOf("-") + 2);
- if (historyList.length == historyCount) {
- String temp[] = new String[historyCount*2];
- System.arraycopy(historyList, 0, temp, 0, historyCount);
- historyList = temp;
- }
- historyList[historyCount++] = why + " - " + readable;
-
- } // otherwise don't know what to do
- }
- }
- //System.out.println(line);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // add the items to the menu in reverse order
-
- //ActionListener historyMenuListener =
- // new ActionListener() {
- // public void actionPerformed(ActionEvent e) {
- // editor.retrieveHistory(e.getActionCommand());
- //}
- //};
-
- for (int i = historyCount-1; i >= 0; --i) {
- JMenuItem mi = new JMenuItem(historyList[i]);
- mi.addActionListener(menuListener);
- menu.add(mi);
- }
-
- reader.close();
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-}
-
-
-*/
diff --git a/app/Sketchbook.java b/app/Sketchbook.java
deleted file mode 100644
index 4c48d3ac0..000000000
--- a/app/Sketchbook.java
+++ /dev/null
@@ -1,683 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-05 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.net.*;
-import java.text.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-import javax.swing.text.*;
-import javax.swing.undo.*;
-
-import com.apple.mrj.*;
-
-
-/**
- * Handles sketchbook mechanics for the sketch menu and file I/O.
- */
-public class Sketchbook {
- Editor editor;
-
- JMenu openMenu;
- JMenu popupMenu;
- //JMenu examples;
- JMenu importMenu;
-
- // set to true after the first time it's built.
- // so that the errors while building don't show up again.
- boolean builtOnce;
-
- //File sketchbookFolder;
- //String sketchbookPath; // canonical path
-
- // last file/directory used for file opening
- //String handleOpenDirectory;
- // opted against this.. in imovie, apple always goes
- // to the "Movies" folder, even if that wasn't the last used
-
- // these are static because they're used by Sketch
- static File examplesFolder;
- static String examplesPath; // canonical path (for comparison)
-
- static File librariesFolder;
- static String librariesPath;
-
- // maps imported packages to their library folder
- static Hashtable importToLibraryTable = new Hashtable();
-
- // classpath for all known libraries for p5
- // (both those in the p5/libs folder and those with lib subfolders
- // found in the sketchbook)
- static String librariesClassPath;
-
-
- public Sketchbook(Editor editor) {
- this.editor = editor;
-
- // this shouldn't change throughout.. it may as well be static
- // but only one instance of sketchbook will be built so who cares
- examplesFolder = new File(System.getProperty("user.dir"), "examples");
- examplesPath = examplesFolder.getAbsolutePath();
-
- librariesFolder = new File(System.getProperty("user.dir"),
- "hardware" + File.separator + "libraries");
- librariesPath = librariesFolder.getAbsolutePath();
-
- String sketchbookPath = Preferences.get("sketchbook.path");
-
- // if a value is at least set, first check to see if the
- // folder exists. if it doesn't, warn the user that the
- // sketchbook folder is being reset.
- if (sketchbookPath != null) {
- File skechbookFolder = new File(sketchbookPath);
- if (!skechbookFolder.exists()) {
- Base.showWarning("Sketchbook folder disappeared",
- "The sketchbook folder no longer exists,\n" +
- "so a new sketchbook will be created in the\n" +
- "default location.", null);
- sketchbookPath = null;
- }
- }
-
- if (sketchbookPath == null) {
- // by default, set default sketchbook path to the user's
- // home folder with 'sketchbook' as a subdirectory of that
-
- /*
- File home = new File(System.getProperty("user.home"));
-
- if (Base.platform == Base.MACOSX) {
- // on macosx put the sketchbook in the "Documents" folder
- home = new File(home, "Documents");
-
- } else if (Base.platform == Base.WINDOWS) {
- // on windows put the sketchbook in the "My Documents" folder
- home = new File(home, "My Documents");
- }
- */
-
- // use a subfolder called 'sketchbook'
- //File home = Preferences.getProcessingHome();
- //String folderName = Preferences.get("sketchbook.name.default");
- //File sketchbookFolder = new File(home, folderName);
-
- //System.out.println("resetting sketchbook path");
- File sketchbookFolder = Base.getDefaultSketchbookFolder();
- //System.out.println("default is " + sketchbookFolder);
- Preferences.set("sketchbook.path",
- sketchbookFolder.getAbsolutePath());
-
- if (!sketchbookFolder.exists()) sketchbookFolder.mkdirs();
- }
- openMenu = new JMenu("Sketchbook");
- popupMenu = new JMenu("Sketchbook");
- importMenu = new JMenu("Import Library");
- }
-
-
- static public String getSketchbookPath() {
- return Preferences.get("sketchbook.path");
- }
-
-
- /**
- * Handle creating a sketch folder, return its base .pde file
- * or null if the operation was cancelled.
- */
- public String handleNew(boolean noPrompt,
- boolean shift,
- boolean library) throws IOException {
- File newbieDir = null;
- String newbieName = null;
-
- boolean prompt = Preferences.getBoolean("sketchbook.prompt");
- if (shift) prompt = !prompt; // reverse behavior if shift is down
-
- // no sketch has been started, don't prompt for the name if it's
- // starting up, just make the farker. otherwise if the person hits
- // 'cancel' i'd have to add a thing to make p5 quit, which is silly.
- // instead give them an empty sketch, and they can look at examples.
- // i hate it when imovie makes you start with that goofy dialog box.
- // unless, ermm, they user tested it and people preferred that as
- // a way to get started. shite. now i hate myself.
- //
- if (noPrompt) prompt = false;
-
- if (prompt) {
- // prompt for the filename and location for the new sketch
- FileDialog fd = new FileDialog(editor,
- "Create sketch folder named:",
- FileDialog.SAVE);
- fd.setDirectory(getSketchbookPath());
- fd.show();
-
- String newbieParentDir = fd.getDirectory();
- newbieName = fd.getFile();
- if (newbieName == null) return null;
-
- newbieName = sanitizeName(newbieName);
- newbieDir = new File(newbieParentDir, newbieName);
-
- } else {
- // use a generic name like sketch_031008a, the date plus a char
- String newbieParentDir = getSketchbookPath();
-
- 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());
- }
-
- // make the directory for the new sketch
- newbieDir.mkdirs();
-
- // if it's a library, make a library subfolder to tag it as such
- if (library) {
- new File(newbieDir, "library").mkdirs();
- }
-
- // make an empty pde file
- File newbieFile = new File(newbieDir, newbieName + ".pde");
- new FileOutputStream(newbieFile); // create the file
-
- // TODO this wouldn't be needed if i could figure out how to
- // associate document icons via a dot-extension/mime-type scenario
- // help me steve jobs, you're my only hope.
-
- // jdk13 on osx, or jdk11
- // though apparently still available for 1.4
- if (Base.isMacOS()) {
- MRJFileUtils.setFileTypeAndCreator(newbieFile,
- MRJOSType.kTypeTEXT,
- new MRJOSType("Pde1"));
- // thank you apple, for changing this @#$)(*
- //com.apple.eio.setFileTypeAndCreator(String filename, int, int)
- }
-
- // make a note of a newly added sketch in the sketchbook menu
- rebuildMenusAsync();
-
- // now open it up
- //handleOpen(newbieName, newbieFile, newbieDir);
- //return newSketch;
- return newbieFile.getAbsolutePath();
- }
-
-
- /**
- * Convert to sanitized name and alert the user
- * if changes were made.
- */
- static public String sanitizeName(String origName) {
- String newName = sanitizedName(origName);
-
- if (!newName.equals(origName)) {
- Base.showMessage("Naming issue",
- "The sketch name had to be modified.\n" +
- "You can only use basic letters and numbers\n" +
- "to name a sketch (ascii only and no spaces,\n" +
- "it can't start with a number, and should be\n" +
- "less than 64 characters long)");
- }
- return newName;
- }
-
-
- /**
- * Return true if the name is valid for a Processing sketch.
- */
- static public boolean isSanitary(String name) {
- return sanitizedName(name).equals(name);
- }
-
-
- /**
- * Produce a sanitized name that fits our standards for likely to work.
- *
- * Java classes have a wider range of names that are technically allowed
- * (supposedly any Unicode name) than what we support. The reason for
- * going more narrow is to avoid situations with text encodings and
- * converting during the process of moving files between operating
- * systems, i.e. uploading from a Windows machine to a Linux server,
- * or reading a FAT32 partition in OS X and using a thumb drive.
- *
- * This helper function replaces everything but A-Z, a-z, and 0-9 with
- * underscores. Also disallows starting the sketch name with a digit.
- */
- static public String sanitizedName(String origName) {
- char c[] = origName.toCharArray();
- StringBuffer buffer = new StringBuffer();
-
- // can't lead with a digit, so start with an underscore
- if ((c[0] >= '0') && (c[0] <= '9')) {
- buffer.append('_');
- }
- for (int i = 0; i < c.length; i++) {
- if (((c[i] >= '0') && (c[i] <= '9')) ||
- ((c[i] >= 'a') && (c[i] <= 'z')) ||
- ((c[i] >= 'A') && (c[i] <= 'Z'))) {
- buffer.append(c[i]);
-
- } else {
- buffer.append('_');
- }
- }
- // let's not be ridiculous about the length of filenames.
- // in fact, Mac OS 9 can handle 255 chars, though it can't really
- // deal with filenames longer than 31 chars in the Finder.
- // but limiting to that for sketches would mean setting the
- // upper-bound on the character limit here to 25 characters
- // (to handle the base name + ".class")
- if (buffer.length() > 63) {
- buffer.setLength(63);
- }
- return buffer.toString();
- }
-
-
- public String handleOpen() {
- // swing's file choosers are ass ugly, so we use the
- // native (awt peered) dialogs where possible
- FileDialog fd = new FileDialog(editor, //new Frame(),
- "Open a Processing sketch...",
- FileDialog.LOAD);
- //fd.setDirectory(Preferences.get("sketchbook.path"));
- //fd.setDirectory(getSketchbookPath());
-
- // only show .pde files as eligible bachelors
- // TODO this doesn't seem to ever be used. AWESOME.
- fd.setFilenameFilter(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- //System.out.println("check filter on " + dir + " " + name);
- return name.toLowerCase().endsWith(".pde");
- }
- });
-
- // gimme some money
- fd.show();
-
- // what in the hell yu want, boy?
- String directory = fd.getDirectory();
- String filename = fd.getFile();
-
- // user cancelled selection
- if (filename == null) return null;
-
- // this may come in handy sometime
- //handleOpenDirectory = directory;
-
- File selection = new File(directory, filename);
- return selection.getAbsolutePath();
- }
-
-
- /**
- * Asynchronous version of menu rebuild to be used on 'new' and 'save',
- * to prevent the interface from locking up until the menus are done.
- */
- public void rebuildMenusAsync() {
- // disabling the async option for actual release, this hasn't been tested
- /*
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- rebuildMenus();
- }
- });
- */
- rebuildMenus();
- }
-
-
- /**
- * Rebuild the menu full of sketches based on the
- * contents of the sketchbook.
- *
- * Creates a separate JMenu object for the popup,
- * because it seems that after calling "getPopupMenu"
- * the menu will disappear from its original location.
- */
- public void rebuildMenus() {
- //EditorConsole.systemOut.println("rebuilding menus");
- try {
- // rebuild file/open and the toolbar popup menus
- buildMenu(openMenu);
- builtOnce = true; // disable error messages while loading
- buildMenu(popupMenu);
-
- // rebuild the "import library" menu
- librariesClassPath = "";
- importMenu.removeAll();
- /*
- if (addLibraries(importMenu, new File(getSketchbookPath()))) {
- importMenu.addSeparator();
- }
- */
- if (addLibraries(importMenu, examplesFolder)) {
- importMenu.addSeparator();
- }
- addLibraries(importMenu, librariesFolder);
- //System.out.println("libraries cp is now " + librariesClassPath);
-
- } catch (IOException e) {
- Base.showWarning("Problem while building sketchbook menu",
- "There was a problem with building the\n" +
- "sketchbook menu. Things might get a little\n" +
- "kooky around here.", e);
- }
- //EditorConsole.systemOut.println("done rebuilding menus");
- }
-
-
- public void buildMenu(JMenu menu) {
- JMenuItem item;
-
- // rebuild the popup menu
- menu.removeAll();
-
- //item = new JMenuItem("Open...");
- item = Editor.newJMenuItem("Open...", 'O', false);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- editor.handleOpen(null);
- }
- });
- menu.add(item);
- menu.addSeparator();
-
- try {
- boolean sketches =
- addSketches(menu, new File(getSketchbookPath()));
- if (sketches) menu.addSeparator();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- ActionListener listener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- editor.handleOpen(e.getActionCommand());
- }
- };
-
- try {
- LibraryManager libManager = new LibraryManager();
- JMenu examplesMenu = new JMenu("Examples");
- addSketches(examplesMenu, examplesFolder);
- libManager.populateExamplesMenu(examplesMenu, listener);
- menu.add(examplesMenu);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- /*
- // don't do this until it's finished
- // libraries don't show up as proper sketches anyway
- try {
- if (Preferences.getBoolean("export.library")) {
- JMenu librariesMenu = new JMenu("Libraries");
- addSketches(librariesMenu, librariesFolder);
- menu.add(librariesMenu);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- */
- }
-
-
- public JMenu getOpenMenu() {
- if (openMenu == null) rebuildMenus();
- return openMenu;
- }
-
-
- public JPopupMenu getPopupMenu() {
- if (popupMenu == null) rebuildMenus();
- return popupMenu.getPopupMenu();
- }
-
-
- public JMenu getImportMenu() {
- return importMenu;
- }
-
-
- protected boolean addSketches(JMenu menu, File folder) throws IOException {
- // skip .DS_Store files, etc
- if (!folder.isDirectory()) return false;
-
- String list[] = folder.list();
- // if a bad folder or something like that, this might come back null
- if (list == null) return false;
-
- // alphabetize list, since it's not always alpha order
- // replaced hella slow bubble sort with this feller for 0093
- Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
-
- ActionListener listener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- editor.handleOpen(e.getActionCommand());
- }
- };
-
- boolean ifound = false;
-
- for (int i = 0; i < list.length; i++) {
- if ((list[i].charAt(0) == '.') ||
- list[i].equals("CVS")) continue;
-
- File subfolder = new File(folder, list[i]);
- if (!subfolder.isDirectory()) continue;
-
- File entry = new File(subfolder, list[i] + ".pde");
- // if a .pde file of the same prefix as the folder exists..
- if (entry.exists()) {
- //String sanityCheck = sanitizedName(list[i]);
- //if (!sanityCheck.equals(list[i])) {
- if (!Sketchbook.isSanitary(list[i])) {
- if (!builtOnce) {
- String complaining =
- "The sketch \"" + list[i] + "\" cannot be used.\n" +
- "Sketch names must contain only basic letters and numbers\n" +
- "(ASCII-only with no spaces, " +
- "and it cannot start with a number).\n" +
- "To get rid of this message, remove the sketch from\n" +
- entry.getAbsolutePath();
- Base.showMessage("Ignoring sketch with bad name", complaining);
- }
- continue;
- }
-
- JMenuItem item = new JMenuItem(list[i]);
- item.addActionListener(listener);
- item.setActionCommand(entry.getAbsolutePath());
- menu.add(item);
- ifound = true;
-
- } else {
- // not a sketch folder, but maybe a subfolder containing sketches
- JMenu submenu = new JMenu(list[i]);
- // needs to be separate var
- // otherwise would set ifound to false
- boolean found = addSketches(submenu, subfolder); //, false);
- if (found) {
- menu.add(submenu);
- ifound = true;
- }
- }
- }
- return ifound; // actually ignored, but..
- }
-
-
- protected boolean addLibraries(JMenu menu, File folder) throws IOException {
- // skip .DS_Store files, etc
- if (!folder.isDirectory()) return false;
-
- String list[] = folder.list();
- // if a bad folder or something like that, this might come back null
- if (list == null) return false;
-
- // alphabetize list, since it's not always alpha order
- // replaced hella slow bubble sort with this feller for 0093
- Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
-
- ActionListener listener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- editor.sketch.importLibrary(e.getActionCommand());
- }
- };
-
- boolean ifound = false;
-
- for (int i = 0; i < list.length; i++) {
- if ((list[i].charAt(0) == '.') ||
- list[i].equals("CVS")) continue;
-
- File subfolder = new File(folder, list[i]);
- if (!subfolder.isDirectory()) continue;
-
- //File exported = new File(subfolder, "library");
- //File entry = new File(exported, list[i] + ".o");
- FileFilter onlyHFiles = new FileFilter() {
- public boolean accept(File file) {
- return (file.getName()).endsWith(".h");
- }
- };
-
- // if the folder has header files
- if (subfolder.listFiles(onlyHFiles).length > 0) {
- // if a .jar file of the same prefix as the folder exists
- // inside the 'library' subfolder of the sketch
- //if (entry.exists()) {
- /*
- String sanityCheck = sanitizedName(list[i]);
- if (!sanityCheck.equals(list[i])) {
- String mess =
- "The library \"" + list[i] + "\" cannot be used.\n" +
- "Library names must contain only basic letters and numbers.\n" +
- "(ascii only and no spaces, and it cannot start with a number)";
- Base.showMessage("Ignoring bad sketch name", mess);
- continue;
- }
- */
-/*
- // get the path for all .jar files in this code folder
- String libraryClassPath =
- Compiler.contentsToClassPath(exported);
- // grab all jars and classes from this folder,
- // and append them to the library classpath
- librariesClassPath +=
- File.pathSeparatorChar + libraryClassPath;
- // need to associate each import with a library folder
- String packages[] =
- Compiler.packageListFromClassPath(libraryClassPath);
- for (int k = 0; k < packages.length; k++) {
- //System.out.println(packages[k] + " -> " + exported);
- //String already = (String) importToLibraryTable.get(packages[k]);
- importToLibraryTable.put(packages[k], exported);
- }
-*/
- JMenuItem item = new JMenuItem(list[i]);
- item.addActionListener(listener);
- item.setActionCommand(subfolder.getAbsolutePath());
- menu.add(item);
- ifound = true;
-
- } else { // not a library, but is still a folder, so recurse
- JMenu submenu = new JMenu(list[i]);
- // needs to be separate var, otherwise would set ifound to false
- boolean found = addLibraries(submenu, subfolder);
- if (found) {
- menu.add(submenu);
- ifound = true;
- }
- }
- }
- return ifound;
- /*return false;*/ }
-
-
- /**
- * Clear out projects that are empty.
- */
- public void clean() {
- //if (!Preferences.getBoolean("sketchbook.auto_clean")) return;
-
- File sketchbookFolder = new File(getSketchbookPath());
- if (!sketchbookFolder.exists()) return;
-
- //String entries[] = new File(userPath).list();
- String entries[] = sketchbookFolder.list();
- if (entries != null) {
- for (int j = 0; j < entries.length; j++) {
- //System.out.println(entries[j] + " " + entries.length);
- if (entries[j].charAt(0) == '.') continue;
-
- //File prey = new File(userPath, entries[j]);
- File prey = new File(sketchbookFolder, entries[j]);
- File pde = new File(prey, entries[j] + ".pde");
-
- // make sure this is actually a sketch folder with a .pde,
- // not a .DS_Store file or another random user folder
-
- if (pde.exists() &&
- (Base.calcFolderSize(prey) == 0)) {
- //System.out.println("i want to remove " + prey);
-
- if (Preferences.getBoolean("sketchbook.auto_clean")) {
- Base.removeDir(prey);
-
- } else { // otherwise prompt the user
- String prompt =
- "Remove empty sketch titled \"" + entries[j] + "\"?";
-
- Object[] options = { "Yes", "No" };
- int result =
- JOptionPane.showOptionDialog(editor,
- prompt,
- "Housekeeping",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE,
- null,
- options,
- options[0]);
- if (result == JOptionPane.YES_OPTION) {
- Base.removeDir(prey);
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/SwingWorker.java b/app/SwingWorker.java
deleted file mode 100644
index feffc9fb4..000000000
--- a/app/SwingWorker.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package processing.app;
-
-import javax.swing.SwingUtilities;
-
-/**
- * This is the 3rd version of SwingWorker (also known as
- * SwingWorker 3), an abstract class that you subclass to
- * perform GUI-related work in a dedicated thread. For
- * instructions on and examples of using this class, see:
- *
- * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
- *
- * Note that the API changed slightly in the 3rd version:
- * You must now invoke start() on the SwingWorker after
- * creating it.
- */
-public abstract class SwingWorker {
- private Object value; // see getValue(), setValue()
-
- /**
- * Class to maintain reference to current worker thread
- * under separate synchronization control.
- */
- private static class ThreadVar {
- private Thread thread;
- ThreadVar(Thread t) { thread = t; }
- synchronized Thread get() { return thread; }
- synchronized void clear() { thread = null; }
- }
-
- private ThreadVar threadVar;
-
- /**
- * Get the value produced by the worker thread, or null if it
- * hasn't been constructed yet.
- */
- protected synchronized Object getValue() {
- return value;
- }
-
- /**
- * Set the value produced by worker thread
- */
- private synchronized void setValue(Object x) {
- value = x;
- }
-
- /**
- * Compute the value to be returned by the get method.
- */
- public abstract Object construct();
-
- /**
- * Called on the event dispatching thread (not on the worker thread)
- * after the construct method has returned.
- */
- public void finished() {
- }
-
- /**
- * A new method that interrupts the worker thread. Call this method
- * to force the worker to stop what it's doing.
- */
- public void interrupt() {
- Thread t = threadVar.get();
- if (t != null) {
- t.interrupt();
- }
- threadVar.clear();
- }
-
- /**
- * Return the value created by the construct method.
- * Returns null if either the constructing thread or the current
- * thread was interrupted before a value was produced.
- *
- * @return the value created by the construct method
- */
- public Object get() {
- while (true) {
- Thread t = threadVar.get();
- if (t == null) {
- return getValue();
- }
- try {
- t.join();
- }
- catch (InterruptedException e) {
- Thread.currentThread().interrupt(); // propagate
- return null;
- }
- }
- }
-
-
- /**
- * Start a thread that will call the construct method
- * and then exit.
- */
- public SwingWorker() {
- final Runnable doFinished = new Runnable() {
- public void run() { finished(); }
- };
-
- Runnable doConstruct = new Runnable() {
- public void run() {
- try {
- setValue(construct());
- }
- finally {
- threadVar.clear();
- }
-
- SwingUtilities.invokeLater(doFinished);
- }
- };
-
- Thread t = new Thread(doConstruct);
- threadVar = new ThreadVar(t);
- }
-
- /**
- * Start the worker thread.
- */
- public void start() {
- Thread t = threadVar.get();
- if (t != null) {
- t.start();
- }
- }
-}
diff --git a/build/shared/lib/RXTXcomm.jar b/app/lib/RXTXcomm.jar
similarity index 100%
rename from build/shared/lib/RXTXcomm.jar
rename to app/lib/RXTXcomm.jar
diff --git a/app/lib/antlr.jar b/app/lib/antlr.jar
new file mode 100644
index 000000000..42f25e540
Binary files /dev/null and b/app/lib/antlr.jar differ
diff --git a/app/lib/apple.jar b/app/lib/apple.jar
new file mode 100755
index 000000000..160d62b66
Binary files /dev/null and b/app/lib/apple.jar differ
diff --git a/app/lib/ecj.jar b/app/lib/ecj.jar
new file mode 100644
index 000000000..878a32cfc
Binary files /dev/null and b/app/lib/ecj.jar differ
diff --git a/app/lib/jna.jar b/app/lib/jna.jar
new file mode 100644
index 000000000..5c669aff6
Binary files /dev/null and b/app/lib/jna.jar differ
diff --git a/build/shared/lib/oro.jar b/app/lib/oro.jar
similarity index 100%
rename from build/shared/lib/oro.jar
rename to app/lib/oro.jar
diff --git a/app/preproc/CVS/Entries b/app/preproc/CVS/Entries
deleted file mode 100644
index 9273971f1..000000000
--- a/app/preproc/CVS/Entries
+++ /dev/null
@@ -1,15 +0,0 @@
-/CSymbolTable.java/1.1.1.1/Thu Sep 22 15:32:54 2005//
-/CToken.java/1.1.1.1/Thu Sep 22 15:32:54 2005//
-/ExtendedCommonASTWithHiddenTokens.java/1.1.1.1/Thu Sep 22 15:32:55 2005//
-/LineObject.java/1.1.1.1/Thu Sep 22 15:32:55 2005//
-/Makefile/1.1.1.1/Thu Sep 22 15:32:55 2005//
-/PreprocessorInfoChannel.java/1.1.1.1/Thu Sep 22 15:32:55 2005//
-/StdCParser.g/1.1.1.1/Thu Sep 22 15:32:56 2005//
-/TNode.java/1.1.1.1/Thu Sep 22 15:32:56 2005//
-/TNodeFactory.java/1.1.1.1/Thu Sep 22 15:32:56 2005//
-/WEmitter.g/1.4/Thu Sep 22 15:32:56 2005//
-/WParser.g/1.4/Thu Sep 22 15:32:57 2005//
-/WTreeParser.g/1.2/Thu Sep 22 15:32:57 2005//
-/whitespace_test.pde/1.1.1.1/Thu Sep 22 15:32:56 2005//
-/PdePreprocessor.java/1.13/Sat Sep 24 11:26:19 2005//
-D
diff --git a/app/preproc/CVS/Repository b/app/preproc/CVS/Repository
deleted file mode 100644
index 8edc19831..000000000
--- a/app/preproc/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-wiring/app/preproc
diff --git a/app/preproc/CVS/Root b/app/preproc/CVS/Root
deleted file mode 100644
index d59a7bfa3..000000000
--- a/app/preproc/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:ext:dmellis@wcvs.uniandes.edu.co:/home/cvs/cvsrep
diff --git a/app/preproc/test/data/foo1.cpp b/app/preproc/test/data/foo1.cpp
deleted file mode 100644
index 7113b33fc..000000000
--- a/app/preproc/test/data/foo1.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-int encoder = 4;
-unsigned long speed = 0;
-
-void setup()
-{
- pinMode(encoder, INPUT);
-}
-
-void loop()
-{
- speed = getspeed();
- delay(1000);
-}
-
-unsigned long getspeed()
-{
- unsigned long duration = 0;
- duration = pulseIn(encoder, HIGH);
- return(duration);
-}
-
diff --git a/app/preproc/test/data/foo1.cpp.out b/app/preproc/test/data/foo1.cpp.out
deleted file mode 100644
index 4542ae3ac..000000000
--- a/app/preproc/test/data/foo1.cpp.out
+++ /dev/null
@@ -1,3 +0,0 @@
-void setup();
-void loop();
-unsigned long getspeed();
diff --git a/app/preproc/test/data/foo2.cpp b/app/preproc/test/data/foo2.cpp
deleted file mode 100644
index 36db12ce9..000000000
--- a/app/preproc/test/data/foo2.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-void playMessage(prog_uchar* message){
-
-maxStringSize = sizeof(message); // find message size
-}
-
-void loop() {
- playMessage(signMessage);
-}
diff --git a/app/preproc/test/data/foo2.cpp.out b/app/preproc/test/data/foo2.cpp.out
deleted file mode 100644
index 688d1807e..000000000
--- a/app/preproc/test/data/foo2.cpp.out
+++ /dev/null
@@ -1,2 +0,0 @@
-void playMessage(prog_uchar* message);
-void loop();
diff --git a/app/preproc/test/data/foo3.cpp b/app/preproc/test/data/foo3.cpp
deleted file mode 100644
index 9b92470d7..000000000
--- a/app/preproc/test/data/foo3.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-void setup() // run once, when the sketch starts
-{
- ;
-}
-
-void loop() // run over and over again
-{
- ;
-}
-
-/*
-void loop(){
- if (1){
- ;
- }
-else if(0){
- ;
-}
-} */
diff --git a/app/preproc/test/data/foo3.cpp.out b/app/preproc/test/data/foo3.cpp.out
deleted file mode 100644
index 82cdaeca9..000000000
--- a/app/preproc/test/data/foo3.cpp.out
+++ /dev/null
@@ -1,2 +0,0 @@
-void setup();
-void loop();
diff --git a/app/preproc/test/data/foo4.cpp b/app/preproc/test/data/foo4.cpp
deleted file mode 100644
index 9bc971566..000000000
--- a/app/preproc/test/data/foo4.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// Continually measures temperatures at three points using the Dallas DS18B20 on three
-// separate Arduino pins.
-//
-// Uses the parasitic power mode
-//
-// Displays to a serial LCD operating at 9600 baud.
-//
-// Arduino Board DS18B20
-//
-// +5 VDC
-// |
-// 4.7K
-// 8 ---------------- |----- 2 (DQ) Note that terms 1 and 3 are grounded.
-//
-// 7 ---- same as above
-// 6 ---- same as above
-//
-// Tx ---------------------------- To Serial LCD (LCD #117)
-//
-// Peter H Anderson, Baltimore, MD, May 5, '07
-
-
-void setup()
-{
- int n, dev_channel[3] = {8, 7, 6}, _1W_Pin;
-
- for (n=0; n<1; n++)
- {
- _1W_Pin = dev_channel[n];
- digitalWrite(_1W_Pin, LOW);
- pinMode(_1W_Pin, INPUT); // sets the digital pin as input (logic 1)
- }
- Serial.begin(9600);
- delay(100);
- Serial.print("?B40"); // set backlight intensity
- delay(100);
-}
-
-void loop()
-{
- int n, dev_channel[3] = {8, 7, 6}, _1W_Pin;
- int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
-
- for (n=0; n<3; n++)
- {
- _1W_Pin = dev_channel[n];
- OneWireReset(_1W_Pin);
- OneWireOutByte(_1W_Pin, 0xcc, 0);
- OneWireOutByte(_1W_Pin, 0x44, 1); // perform temperature conversion, strong pullup for one sec
-
- OneWireReset(_1W_Pin);
- OneWireOutByte(_1W_Pin, 0xcc, 0);
- OneWireOutByte(_1W_Pin, 0xbe, 0);
-
- LowByte = OneWireInByte(_1W_Pin);
- HighByte = OneWireInByte(_1W_Pin);
- TReading = (HighByte << 8) + LowByte;
- SignBit = TReading & 0x8000; // test most sig bit
- if (SignBit) // negative
- {
- TReading = (TReading ^ 0xffff) + 1; // 2's comp
- }
- Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
-
- Whole = Tc_100 / 100; // separate off the whole and fractional portions
- Fract = Tc_100 % 100;
-
- if (n==0) // if its the first time, clear the LCD
- {
- Serial.print("?f");
- delay(100);
- }
-
- if (SignBit) // If its negative
- {
- Serial.print("-");
- }
- Serial.print(Whole);
- Serial.print(".");
- if (Fract < 10)
- {
- Serial.print("0");
- }
- Serial.print(Fract);
- Serial.print("?n");
- }
- delay(5000); // 5 second delay. Adjust as necessary
-}
-
-void OneWireReset(int _1W_Pin) // reset. Should improve to act as a presence pulse
-{
- digitalWrite(_1W_Pin, LOW);
- pinMode(_1W_Pin, OUTPUT); // bring low for 500 us
- delayMicroseconds(500);
- pinMode(_1W_Pin, INPUT);
- delayMicroseconds(500);
-}
-
-void OneWireOutByte(int _1W_Pin, byte d, byte strong) // output byte d (least sig bit first).
-{
- byte n;
-
- for(n=8; n!=0; n--)
- {
- if ((d & 0x01) == 1) // test least sig bit
- {
- digitalWrite(_1W_Pin, LOW);
- pinMode(_1W_Pin, OUTPUT);
- delayMicroseconds(5);
- pinMode(_1W_Pin, INPUT);
- delayMicroseconds(60);
- }
- else
- {
- digitalWrite(_1W_Pin, LOW);
- pinMode(_1W_Pin, OUTPUT);
- delayMicroseconds(60);
- pinMode(_1W_Pin, INPUT);
- }
-
- d=d>>1; // now the next bit is in the least sig bit position.
- }
- if(strong)
- {
- digitalWrite(_1W_Pin, HIGH); // One sec of strong +5 VDC
- pinMode(_1W_Pin, OUTPUT);
- delay(1000);
- pinMode(_1W_Pin, INPUT);
- digitalWrite(_1W_Pin, LOW);
- }
-}
diff --git a/app/preproc/test/data/foo4.cpp.out b/app/preproc/test/data/foo4.cpp.out
deleted file mode 100644
index 58c736416..000000000
--- a/app/preproc/test/data/foo4.cpp.out
+++ /dev/null
@@ -1,4 +0,0 @@
-void setup();
-void loop();
-void OneWireReset(int _1W_Pin);
-void OneWireOutByte(int _1W_Pin, byte d, byte strong);
diff --git a/app/preproc/test/data/foo5.cpp b/app/preproc/test/data/foo5.cpp
deleted file mode 100644
index 5b8ee2db4..000000000
--- a/app/preproc/test/data/foo5.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-void setup()
-{
-}
-
-void loop()
-{
- char cmd[16];
- int pin;
- pin = atoi(&cmd[1]);
-}
-
-/*
-// convert string to numeric value
-int atoi(char *array) {
-}
-*/
diff --git a/app/preproc/test/data/foo5.cpp.out b/app/preproc/test/data/foo5.cpp.out
deleted file mode 100644
index 82cdaeca9..000000000
--- a/app/preproc/test/data/foo5.cpp.out
+++ /dev/null
@@ -1,2 +0,0 @@
-void setup();
-void loop();
diff --git a/app/preproc/test/data/foo6.cpp b/app/preproc/test/data/foo6.cpp
deleted file mode 100644
index f294435af..000000000
--- a/app/preproc/test/data/foo6.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-void setup()
-{
-}
-
-void loop()
-{
-}
-
-void foo(int x, int y, char *z)
-{
-}
diff --git a/app/preproc/test/data/foo6.cpp.out b/app/preproc/test/data/foo6.cpp.out
deleted file mode 100644
index d35513110..000000000
--- a/app/preproc/test/data/foo6.cpp.out
+++ /dev/null
@@ -1,3 +0,0 @@
-void setup();
-void loop();
-void foo(int x, int y, char *z);
diff --git a/app/preproc/test/data/foo7.cpp b/app/preproc/test/data/foo7.cpp
deleted file mode 100644
index 93724a54a..000000000
--- a/app/preproc/test/data/foo7.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "hello" /* for blah */
-
-int x[] = { 1, 2, 3 };
-int y[2] = { 1, 2 };
-
-class Foo {
-public:
- Foo();
- Foo(int x);
- int bar() { return x; }
-private:
- int x;
-};
-
-Foo::Foo(int x) : x(x) {}
-
-Foo::Foo() {
- x = 0;
-}
-
-Foo foo(3);
-Foo bar = Foo(2);
-
-void setup() {
-}
-
-void
-loop (
-
-)
-
-
-
-{
-}
diff --git a/app/preproc/test/data/foo7.cpp.out b/app/preproc/test/data/foo7.cpp.out
deleted file mode 100644
index edb355ae0..000000000
--- a/app/preproc/test/data/foo7.cpp.out
+++ /dev/null
@@ -1,5 +0,0 @@
-void setup();
-void
-loop (
-
-);
diff --git a/app/preproc/test/data/t1.cpp b/app/preproc/test/data/t1.cpp
deleted file mode 100644
index b11d4bfe5..000000000
--- a/app/preproc/test/data/t1.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-abc/* def */ghi
-jkl// mno
-pqr"stu"vwx
-#yz
-123
\ No newline at end of file
diff --git a/app/preproc/test/data/t1.cpp.out b/app/preproc/test/data/t1.cpp.out
deleted file mode 100644
index 723a710da..000000000
--- a/app/preproc/test/data/t1.cpp.out
+++ /dev/null
@@ -1,5 +0,0 @@
-abc ghi
-jkl
-pqr vwx
-
-123
\ No newline at end of file
diff --git a/app/preproc/test/data/t10.cpp b/app/preproc/test/data/t10.cpp
deleted file mode 100644
index 735cb56fd..000000000
--- a/app/preproc/test/data/t10.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"d\nef\\\"ghi"jkl//"
\ No newline at end of file
diff --git a/app/preproc/test/data/t10.cpp.out b/app/preproc/test/data/t10.cpp.out
deleted file mode 100644
index abc43e324..000000000
--- a/app/preproc/test/data/t10.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t11.cpp b/app/preproc/test/data/t11.cpp
deleted file mode 100644
index 5e25564df..000000000
--- a/app/preproc/test/data/t11.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"d\\nef\\\"ghi"jkl//"
\ No newline at end of file
diff --git a/app/preproc/test/data/t11.cpp.out b/app/preproc/test/data/t11.cpp.out
deleted file mode 100644
index abc43e324..000000000
--- a/app/preproc/test/data/t11.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t12.cpp b/app/preproc/test/data/t12.cpp
deleted file mode 100644
index 1abde0a61..000000000
--- a/app/preproc/test/data/t12.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"dnef\\\\\"ghi"jkl//"
\ No newline at end of file
diff --git a/app/preproc/test/data/t12.cpp.out b/app/preproc/test/data/t12.cpp.out
deleted file mode 100644
index abc43e324..000000000
--- a/app/preproc/test/data/t12.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t13.cpp b/app/preproc/test/data/t13.cpp
deleted file mode 100644
index d0e184f75..000000000
--- a/app/preproc/test/data/t13.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc'"'def'"'ghi
\ No newline at end of file
diff --git a/app/preproc/test/data/t13.cpp.out b/app/preproc/test/data/t13.cpp.out
deleted file mode 100644
index a371d86fa..000000000
--- a/app/preproc/test/data/t13.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc def ghi
\ No newline at end of file
diff --git a/app/preproc/test/data/t14.cpp b/app/preproc/test/data/t14.cpp
deleted file mode 100644
index 5b5a740ab..000000000
--- a/app/preproc/test/data/t14.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-# abc /* def
-ghi */ jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t14.cpp.out b/app/preproc/test/data/t14.cpp.out
deleted file mode 100644
index 872e9cc0b..000000000
--- a/app/preproc/test/data/t14.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
- jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t15.cpp b/app/preproc/test/data/t15.cpp
deleted file mode 100644
index a8b57e51d..000000000
--- a/app/preproc/test/data/t15.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc /* def * ghi */ jkl
diff --git a/app/preproc/test/data/t15.cpp.out b/app/preproc/test/data/t15.cpp.out
deleted file mode 100644
index 87bb2bed0..000000000
--- a/app/preproc/test/data/t15.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
diff --git a/app/preproc/test/data/t16.cpp b/app/preproc/test/data/t16.cpp
deleted file mode 100644
index e565fc803..000000000
--- a/app/preproc/test/data/t16.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc /* def * ghi **/ jkl
diff --git a/app/preproc/test/data/t16.cpp.out b/app/preproc/test/data/t16.cpp.out
deleted file mode 100644
index 87bb2bed0..000000000
--- a/app/preproc/test/data/t16.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
diff --git a/app/preproc/test/data/t17.cpp b/app/preproc/test/data/t17.cpp
deleted file mode 100644
index bf639dc31..000000000
--- a/app/preproc/test/data/t17.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc /* def ** ghi **/ jkl
diff --git a/app/preproc/test/data/t17.cpp.out b/app/preproc/test/data/t17.cpp.out
deleted file mode 100644
index 87bb2bed0..000000000
--- a/app/preproc/test/data/t17.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
diff --git a/app/preproc/test/data/t18.cpp b/app/preproc/test/data/t18.cpp
deleted file mode 100644
index ba05f1618..000000000
--- a/app/preproc/test/data/t18.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-abc /* def ** ghi ***
-jkl *
-* // mno **/ pqr
diff --git a/app/preproc/test/data/t18.cpp.out b/app/preproc/test/data/t18.cpp.out
deleted file mode 100644
index 5c75bd891..000000000
--- a/app/preproc/test/data/t18.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc pqr
diff --git a/app/preproc/test/data/t2.cpp b/app/preproc/test/data/t2.cpp
deleted file mode 100644
index 6083c0fc1..000000000
--- a/app/preproc/test/data/t2.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-abc // def /*
-ghi
-jlk // mno */
\ No newline at end of file
diff --git a/app/preproc/test/data/t2.cpp.out b/app/preproc/test/data/t2.cpp.out
deleted file mode 100644
index 1c6c05995..000000000
--- a/app/preproc/test/data/t2.cpp.out
+++ /dev/null
@@ -1,3 +0,0 @@
-abc
-ghi
-jlk
\ No newline at end of file
diff --git a/app/preproc/test/data/t3.cpp b/app/preproc/test/data/t3.cpp
deleted file mode 100644
index 0fca745bb..000000000
--- a/app/preproc/test/data/t3.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-// /* // */ "
-asdf
-// /* // */ "
\ No newline at end of file
diff --git a/app/preproc/test/data/t3.cpp.out b/app/preproc/test/data/t3.cpp.out
deleted file mode 100644
index 4caa2172b..000000000
--- a/app/preproc/test/data/t3.cpp.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-asdf
-
\ No newline at end of file
diff --git a/app/preproc/test/data/t4.cpp b/app/preproc/test/data/t4.cpp
deleted file mode 100644
index 59db82ded..000000000
--- a/app/preproc/test/data/t4.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
-abc
-/*
-def
-*/
-ghi
-*/
\ No newline at end of file
diff --git a/app/preproc/test/data/t4.cpp.out b/app/preproc/test/data/t4.cpp.out
deleted file mode 100644
index 16ef36566..000000000
--- a/app/preproc/test/data/t4.cpp.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-ghi
-*/
\ No newline at end of file
diff --git a/app/preproc/test/data/t5.cpp b/app/preproc/test/data/t5.cpp
deleted file mode 100644
index 85fd0ec2c..000000000
--- a/app/preproc/test/data/t5.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"def//ghi"jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t5.cpp.out b/app/preproc/test/data/t5.cpp.out
deleted file mode 100644
index 1c1e993b0..000000000
--- a/app/preproc/test/data/t5.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t6.cpp b/app/preproc/test/data/t6.cpp
deleted file mode 100644
index e65dafb96..000000000
--- a/app/preproc/test/data/t6.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-abc // def " ghi
-jkl
-mno // pqr " stu
\ No newline at end of file
diff --git a/app/preproc/test/data/t6.cpp.out b/app/preproc/test/data/t6.cpp.out
deleted file mode 100644
index 29f1b4c26..000000000
--- a/app/preproc/test/data/t6.cpp.out
+++ /dev/null
@@ -1,3 +0,0 @@
-abc
-jkl
-mno
\ No newline at end of file
diff --git a/app/preproc/test/data/t7.cpp b/app/preproc/test/data/t7.cpp
deleted file mode 100644
index bf0a386a6..000000000
--- a/app/preproc/test/data/t7.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"def\\"ghi"jkl//"
\ No newline at end of file
diff --git a/app/preproc/test/data/t7.cpp.out b/app/preproc/test/data/t7.cpp.out
deleted file mode 100644
index 1bcf7d0d5..000000000
--- a/app/preproc/test/data/t7.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc ghi
\ No newline at end of file
diff --git a/app/preproc/test/data/t8.cpp b/app/preproc/test/data/t8.cpp
deleted file mode 100644
index 34c7a17c2..000000000
--- a/app/preproc/test/data/t8.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"def\"ghi"jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t8.cpp.out b/app/preproc/test/data/t8.cpp.out
deleted file mode 100644
index 1c1e993b0..000000000
--- a/app/preproc/test/data/t8.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
\ No newline at end of file
diff --git a/app/preproc/test/data/t9.cpp b/app/preproc/test/data/t9.cpp
deleted file mode 100644
index 3b63f08ce..000000000
--- a/app/preproc/test/data/t9.cpp
+++ /dev/null
@@ -1 +0,0 @@
-abc"def\\\"ghi"jkl//"
\ No newline at end of file
diff --git a/app/preproc/test/data/t9.cpp.out b/app/preproc/test/data/t9.cpp.out
deleted file mode 100644
index abc43e324..000000000
--- a/app/preproc/test/data/t9.cpp.out
+++ /dev/null
@@ -1 +0,0 @@
-abc jkl
\ No newline at end of file
diff --git a/app/preproc/test/test.sh b/app/preproc/test/test.sh
deleted file mode 100755
index d50ecad0b..000000000
--- a/app/preproc/test/test.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-javac -classpath ../../../build/shared/lib/oro.jar test_PdePreprocessor.java
-for i in data/t*.cpp; do echo $i; java -classpath ../../../build/shared/lib/oro.jar:. test_PdePreprocessor strip $i | diff - $i.out; done
-for i in data/foo*.cpp; do echo $i; java -classpath ../../../build/shared/lib/oro.jar:. test_PdePreprocessor prototypes $i | diff - $i.out; done
diff --git a/app/preproc/test/test_PdePreprocessor.java b/app/preproc/test/test_PdePreprocessor.java
deleted file mode 100644
index 38bd9145d..000000000
--- a/app/preproc/test/test_PdePreprocessor.java
+++ /dev/null
@@ -1,44 +0,0 @@
-import java.io.Reader;
-import java.io.File;
-import java.io.FileReader;
-
-import java.util.List;
-import java.util.ArrayList;
-
-import com.oroinc.text.regex.*;
-
-public class test_PdePreprocessor {
- /************************************************************************
- Paste from PdePreprocessor.java: strip(), collapseBraces(), prototypes()
- ************************************************************************/
-
- public static void main(String[] args) {
- if (args.length < 2) {
- System.err.println("Usage: PreProc [strip|prototypes] ");
- return;
- }
-
- try {
- test_PdePreprocessor preproc = new test_PdePreprocessor();
- Reader reader = new FileReader(new File(args[1]));
- StringBuffer buffer = new StringBuffer();
- char[] buf = new char[1024];
- int n;
-
- while ((n = reader.read(buf, 0, 1024)) != -1) {
- buffer.append(buf, 0, n);
- }
-
- if (args[0].equals("strip")) {
- System.out.print(preproc.strip(buffer.toString()));
- } else {
- List prototypes = preproc.prototypes(buffer.toString());
- for (int i = 0; i < prototypes.size(); i++) {
- System.out.println((String) prototypes.get(i));
- }
- }
- } catch (Exception e) {
- System.err.println(e);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/antlr/ExtendedCommonASTWithHiddenTokens.java b/app/src/antlr/ExtendedCommonASTWithHiddenTokens.java
new file mode 100644
index 000000000..d997f0be8
--- /dev/null
+++ b/app/src/antlr/ExtendedCommonASTWithHiddenTokens.java
@@ -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);
+ }
+ }
+ }
+
+}
diff --git a/app/src/antlr/TokenStreamCopyingHiddenTokenFilter.java b/app/src/antlr/TokenStreamCopyingHiddenTokenFilter.java
new file mode 100644
index 000000000..cd3306aed
--- /dev/null
+++ b/app/src/antlr/TokenStreamCopyingHiddenTokenFilter.java
@@ -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;
+ }
+}
diff --git a/app/src/antlr/java/java.g b/app/src/antlr/java/java.g
new file mode 100644
index 000000000..ee948ccd0
--- /dev/null
+++ b/app/src/antlr/java/java.g
@@ -0,0 +1,1277 @@
+header {
+package antlr.java;
+}
+
+/** Java 1.3 Recognizer
+ *
+ * Run 'java Main [-showtree] directory-full-of-java-files'
+ *
+ * [The -showtree option pops up a Swing frame that shows
+ * the AST constructed from the parser.]
+ *
+ * Run 'java Main '
+ *
+ * Contributing authors:
+ * John Mitchell johnm@non.net
+ * Terence Parr parrt@magelang.com
+ * John Lilley jlilley@empathy.com
+ * Scott Stanchfield thetick@magelang.com
+ * Markus Mohnen mohnen@informatik.rwth-aachen.de
+ * Peter Williams pete.williams@sun.com
+ * Allan Jacobs Allan.Jacobs@eng.sun.com
+ * Steve Messick messick@redhills.com
+ * John Pybus john@pybus.org
+ *
+ * Version 1.00 December 9, 1997 -- initial release
+ * Version 1.01 December 10, 1997
+ * fixed bug in octal def (0..7 not 0..8)
+ * Version 1.10 August 1998 (parrt)
+ * added tree construction
+ * fixed definition of WS,comments for mac,pc,unix newlines
+ * added unary plus
+ * Version 1.11 (Nov 20, 1998)
+ * Added "shutup" option to turn off last ambig warning.
+ * Fixed inner class def to allow named class defs as statements
+ * synchronized requires compound not simple statement
+ * add [] after builtInType DOT class in primaryExpression
+ * "const" is reserved but not valid..removed from modifiers
+ * Version 1.12 (Feb 2, 1999)
+ * Changed LITERAL_xxx to xxx in tree grammar.
+ * Updated java.g to use tokens {...} now for 2.6.0 (new feature).
+ *
+ * Version 1.13 (Apr 23, 1999)
+ * Didn't have (stat)? for else clause in tree parser.
+ * Didn't gen ASTs for interface extends. Updated tree parser too.
+ * Updated to 2.6.0.
+ * Version 1.14 (Jun 20, 1999)
+ * Allowed final/abstract on local classes.
+ * Removed local interfaces from methods
+ * Put instanceof precedence where it belongs...in relationalExpr
+ * It also had expr not type as arg; fixed it.
+ * Missing ! on SEMI in classBlock
+ * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
+ * fixed: didn't like Object[].class in parser or tree parser
+ * Version 1.15 (Jun 26, 1999)
+ * Screwed up rule with instanceof in it. :( Fixed.
+ * Tree parser didn't like (expr).something; fixed.
+ * Allowed multiple inheritance in tree grammar. oops.
+ * Version 1.16 (August 22, 1999)
+ * Extending an interface built a wacky tree: had extra EXTENDS.
+ * Tree grammar didn't allow multiple superinterfaces.
+ * Tree grammar didn't allow empty var initializer: {}
+ * Version 1.17 (October 12, 1999)
+ * ESC lexer rule allowed 399 max not 377 max.
+ * java.tree.g didn't handle the expression of synchronized
+ * statements.
+ * Version 1.18 (August 12, 2001)
+ * Terence updated to Java 2 Version 1.3 by
+ * observing/combining work of Allan Jacobs and Steve
+ * Messick. Handles 1.3 src. Summary:
+ * o primary didn't include boolean.class kind of thing
+ * o constructor calls parsed explicitly now:
+ * see explicitConstructorInvocation
+ * o add strictfp modifier
+ * o missing objBlock after new expression in tree grammar
+ * o merged local class definition alternatives, moved after declaration
+ * o fixed problem with ClassName.super.field
+ * o reordered some alternatives to make things more efficient
+ * o long and double constants were not differentiated from int/float
+ * o whitespace rule was inefficient: matched only one char
+ * o add an examples directory with some nasty 1.3 cases
+ * o made Main.java use buffered IO and a Reader for Unicode support
+ * o supports UNICODE?
+ * Using Unicode charVocabulay makes code file big, but only
+ * in the bitsets at the end. I need to make ANTLR generate
+ * unicode bitsets more efficiently.
+ * Version 1.19 (April 25, 2002)
+ * Terence added in nice fixes by John Pybus concerning floating
+ * constants and problems with super() calls. John did a nice
+ * reorg of the primary/postfix expression stuff to read better
+ * and makes f.g.super() parse properly (it was METHOD_CALL not
+ * a SUPER_CTOR_CALL). Also:
+ *
+ * o "finally" clause was a root...made it a child of "try"
+ * o Added stuff for asserts too for Java 1.4, but *commented out*
+ * as it is not backward compatible.
+ *
+ * Version 1.20 (October 27, 2002)
+ *
+ * Terence ended up reorging John Pybus' stuff to
+ * remove some nondeterminisms and some syntactic predicates.
+ * Note that the grammar is stricter now; e.g., this(...) must
+ * be the first statement.
+ *
+ * Trinary ?: operator wasn't working as array name:
+ * (isBig ? bigDigits : digits)[i];
+ *
+ * Checked parser/tree parser on source for
+ * Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4,
+ * and the 110k-line jGuru server source.
+ *
+ * This grammar is in the PUBLIC DOMAIN
+ *
+ */
+class JavaRecognizer extends Parser;
+options {
+ k = 2; // two token lookahead
+ exportVocab=Java; // Call its vocabulary "Java"
+ codeGenMakeSwitchThreshold = 2; // Some optimizations
+ codeGenBitsetTestThreshold = 3;
+ defaultErrorHandler = false; // Don't generate parser error handlers
+ buildAST = true;
+}
+
+tokens {
+ BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF;
+ INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF;
+ PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
+ PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP;
+ POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT;
+ IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION;
+ FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";
+ STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL;
+}
+
+// Compilation Unit: In Java, this is a single file. This is the start
+// rule for this parser
+compilationUnit
+ : // A compilation unit starts with an optional package definition
+ ( packageDefinition
+ | /* nothing */
+ )
+
+ // Next we have a series of zero or more import statements
+ ( importDefinition )*
+
+ // Wrapping things up with any number of class or interface
+ // definitions
+ ( typeDefinition )*
+
+ EOF!
+ ;
+
+
+// Package statement: "package" followed by an identifier.
+packageDefinition
+ options {defaultErrorHandler = true;} // let ANTLR handle errors
+ : p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI!
+ ;
+
+
+// Import statement: import followed by a package or class name
+importDefinition
+ options {defaultErrorHandler = true;}
+ : i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI!
+ ;
+
+// A type definition in a file is either a class or interface definition.
+typeDefinition
+ options {defaultErrorHandler = true;}
+ : m:modifiers!
+ ( classDefinition[#m]
+ | interfaceDefinition[#m]
+ )
+ | SEMI!
+ ;
+
+/** A declaration is the creation of a reference or primitive-type variable
+ * Create a separate Type/Var tree for each var in the var list.
+ */
+declaration!
+ : m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
+ {#declaration = #v;}
+ ;
+
+// A type specification is a type name with possible brackets afterwards
+// (which would make it an array type).
+typeSpec[boolean addImagNode]
+ : classTypeSpec[addImagNode]
+ | builtInTypeSpec[addImagNode]
+ ;
+
+// A class type specification is a class type with possible brackets afterwards
+// (which would make it an array type).
+classTypeSpec[boolean addImagNode]
+ : identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ {
+ if ( addImagNode ) {
+ #classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
+ }
+ }
+ ;
+
+// A builtin type specification is a builtin type with possible brackets
+// afterwards (which would make it an array type).
+builtInTypeSpec[boolean addImagNode]
+ : builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ {
+ if ( addImagNode ) {
+ #builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
+ }
+ }
+ ;
+
+// A type name. which is either a (possibly qualified) class name or
+// a primitive (builtin) type
+type
+ : identifier
+ | builtInType
+ ;
+
+// The primitive types.
+builtInType
+ : "void"
+ | "boolean"
+ | "byte"
+ | "char"
+ | "short"
+ | "int"
+ | "float"
+ | "long"
+ | "double"
+ ;
+
+// A (possibly-qualified) java identifier. We start with the first IDENT
+// and expand its name by adding dots and following IDENTS
+identifier
+ : IDENT ( DOT^ IDENT )*
+ ;
+
+identifierStar
+ : IDENT
+ ( DOT^ IDENT )*
+ ( DOT^ STAR )?
+ ;
+
+// A list of zero or more modifiers. We could have used (modifier)* in
+// place of a call to modifiers, but I thought it was a good idea to keep
+// this rule separate so they can easily be collected in a Vector if
+// someone so desires
+modifiers
+ : ( modifier )*
+ {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
+ ;
+
+// modifiers for Java classes, interfaces, class/instance vars and methods
+modifier
+ : "private"
+ | "public"
+ | "protected"
+ | "static"
+ | "transient"
+ | "final"
+ | "abstract"
+ | "native"
+ | "threadsafe"
+ | "synchronized"
+// | "const" // reserved word, but not valid
+ | "volatile"
+ | "strictfp"
+ ;
+
+// Definition of a Java class
+classDefinition![AST modifiers]
+ : "class" 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,IDENT,sc,ic,cb);}
+ ;
+
+superClassClause!
+ : ( "extends" id:identifier )?
+ {#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);}
+ ;
+
+// Definition of a Java Interface
+interfaceDefinition![AST modifiers]
+ : "interface" IDENT
+ // it might extend some other interfaces
+ ie:interfaceExtends
+ // now parse the body of the interface (looks like a class...)
+ cb:classBlock
+ {#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
+ modifiers,IDENT,ie,cb);}
+ ;
+
+
+// This is the body of a class. You can have fields and extra semicolons,
+// That's about it (until you see what a field is...)
+classBlock
+ : LCURLY!
+ ( field | SEMI! )*
+ RCURLY!
+ {#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
+ ;
+
+// An interface can extend several other interfaces...
+interfaceExtends
+ : (
+ e:"extends"!
+ identifier ( COMMA! identifier )*
+ )?
+ {#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
+ #interfaceExtends);}
+ ;
+
+// A class can implement several interfaces...
+implementsClause
+ : (
+ i:"implements"! identifier ( COMMA! identifier )*
+ )?
+ {#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
+ #implementsClause);}
+ ;
+
+// Now the various things that can be defined inside a class or interface...
+// Note that not all of these are really valid in an interface (constructors,
+// for example), and if this grammar were used for a compiler there would
+// need to be some semantic checks to make sure we're doing the right thing...
+field!
+ : // method, constructor, or variable declaration
+ mods:modifiers
+ ( h:ctorHead s:constructorBody // constructor
+ {#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);}
+
+ | cd:classDefinition[#mods] // inner class
+ {#field = #cd;}
+
+ | id:interfaceDefinition[#mods] // inner interface
+ {#field = #id;}
+
+ | t:typeSpec[false] // method or variable declaration(s)
+ ( IDENT // the name of the method
+
+ // parse the formal parameter declarations.
+ LPAREN! param:parameterDeclarationList RPAREN!
+
+ rt:declaratorBrackets[#t]
+
+ // get the list of exceptions that this method is
+ // declared to throw
+ (tc:throwsClause)?
+
+ ( s2:compoundStatement | SEMI )
+ {#field = #(#[METHOD_DEF,"METHOD_DEF"],
+ mods,
+ #(#[TYPE,"TYPE"],rt),
+ IDENT,
+ param,
+ tc,
+ s2);}
+ | v:variableDefinitions[#mods,#t] SEMI
+// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);}
+ {#field = #v;}
+ )
+ )
+
+ // "static { ... }" class initializer
+ | "static" s3:compoundStatement
+ {#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);}
+
+ // "{ ... }" instance initializer
+ | s4:compoundStatement
+ {#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);}
+ ;
+
+constructorBody
+ : lc:LCURLY^ {#lc.setType(SLIST);}
+ ( options { greedy=true; } : explicitConstructorInvocation)?
+ (statement)*
+ RCURLY!
+ ;
+
+/** Catch obvious constructor calls, but not the expr.super(...) calls */
+explicitConstructorInvocation
+ : "this"! lp1:LPAREN^ argList RPAREN! SEMI!
+ {#lp1.setType(CTOR_CALL);}
+ | "super"! lp2:LPAREN^ argList RPAREN! SEMI!
+ {#lp2.setType(SUPER_CTOR_CALL);}
+ ;
+
+variableDefinitions[AST mods, AST t]
+ : variableDeclarator[getASTFactory().dupTree(mods),
+ getASTFactory().dupTree(t)]
+ ( COMMA!
+ variableDeclarator[getASTFactory().dupTree(mods),
+ getASTFactory().dupTree(t)]
+ )*
+ ;
+
+/** Declaration of a variable. This can be a class/instance variable,
+ * or a local variable in a method
+ * It can also include possible initialization.
+ */
+variableDeclarator![AST mods, AST t]
+ : id:IDENT d:declaratorBrackets[t] v:varInitializer
+ {#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);}
+ ;
+
+declaratorBrackets[AST typ]
+ : {#declaratorBrackets=typ;}
+ (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ ;
+
+varInitializer
+ : ( ASSIGN^ initializer )?
+ ;
+
+// This is an initializer used to set up an array.
+arrayInitializer
+ : lc:LCURLY^ {#lc.setType(ARRAY_INIT);}
+ ( initializer
+ (
+ // CONFLICT: does a COMMA after an initializer start a new
+ // initializer or start the option ',' at end?
+ // ANTLR generates proper code by matching
+ // the comma as soon as possible.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ COMMA! initializer
+ )*
+ (COMMA!)?
+ )?
+ RCURLY!
+ ;
+
+
+// The two "things" that can initialize an array element are an expression
+// and another (nested) array initializer.
+initializer
+ : expression
+ | arrayInitializer
+ ;
+
+// This is the header of a method. It includes the name and parameters
+// for the method.
+// This also watches for a list of exception classes in a "throws" clause.
+ctorHead
+ : IDENT // the name of the method
+
+ // parse the formal parameter declarations.
+ LPAREN! parameterDeclarationList RPAREN!
+
+ // get the list of exceptions that this method is declared to throw
+ (throwsClause)?
+ ;
+
+// This is a list of exception classes that the method is declared to throw
+throwsClause
+ : "throws"^ identifier ( COMMA! identifier )*
+ ;
+
+
+// A list of formal parameters
+parameterDeclarationList
+ : ( parameterDeclaration ( COMMA! parameterDeclaration )* )?
+ {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
+ #parameterDeclarationList);}
+ ;
+
+// A formal parameter.
+parameterDeclaration!
+ : pm:parameterModifier t:typeSpec[false] id:IDENT
+ pd:declaratorBrackets[#t]
+ {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
+ pm, #([TYPE,"TYPE"],pd), id);}
+ ;
+
+parameterModifier
+ : (f:"final")?
+ {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);}
+ ;
+
+// Compound statement. This is used in many contexts:
+// Inside a class definition prefixed with "static":
+// it is a class initializer
+// Inside a class definition without "static":
+// it is an instance initializer
+// As the body of a method
+// As a completely indepdent braced block of code inside a method
+// it starts a new scope for variable definitions
+
+compoundStatement
+ : lc:LCURLY^ {#lc.setType(SLIST);}
+ // include the (possibly-empty) list of statements
+ (statement)*
+ RCURLY!
+ ;
+
+
+statement
+ // A list of statements in curly braces -- start a new scope!
+ : compoundStatement
+
+ // declarations are ambiguous with "ID DOT" relative to expression
+ // statements. Must backtrack to be sure. Could use a semantic
+ // predicate to test symbol table to see what the type was coming
+ // up, but that's pretty hard without a symbol table ;)
+ | (declaration)=> declaration SEMI!
+
+ // An expression statement. This could be a method call,
+ // assignment statement, or any other expression evaluated for
+ // side-effects.
+ | expression SEMI!
+
+ // class definition
+ | m:modifiers! classDefinition[#m]
+
+ // Attach a label to the front of a statement
+ | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
+
+ // If-else statement
+ | "if"^ LPAREN! expression RPAREN! statement
+ (
+ // CONFLICT: the old "dangling-else" problem...
+ // ANTLR generates proper code matching
+ // as soon as possible. Hush warning.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ "else"! statement
+ )?
+
+ // For statement
+ | "for"^
+ LPAREN!
+ forInit SEMI! // initializer
+ forCond SEMI! // condition test
+ forIter // updater
+ RPAREN!
+ statement // statement to loop over
+
+ // While statement
+ | "while"^ LPAREN! expression RPAREN! statement
+
+ // do-while statement
+ | "do"^ statement "while"! LPAREN! expression RPAREN! SEMI!
+
+ // get out of a loop (or switch)
+ | "break"^ (IDENT)? SEMI!
+
+ // do next iteration of a loop
+ | "continue"^ (IDENT)? SEMI!
+
+ // Return an expression
+ | "return"^ (expression)? SEMI!
+
+ // switch/case statement
+ | "switch"^ LPAREN! expression RPAREN! LCURLY!
+ ( casesGroup )*
+ RCURLY!
+
+ // exception try-catch block
+ | tryBlock
+
+ // throw an exception
+ | "throw"^ expression SEMI!
+
+ // synchronize a statement
+ | "synchronized"^ LPAREN! expression RPAREN! compoundStatement
+
+ // asserts (uncomment if you want 1.4 compatibility)
+ | "assert"^ expression ( COLON! expression )? SEMI!
+
+ // empty statement
+ | s:SEMI {#s.setType(EMPTY_STAT);}
+ ;
+
+casesGroup
+ : ( // CONFLICT: to which case group do the statements bind?
+ // ANTLR generates proper code: it groups the
+ // many "case"/"default" labels together then
+ // follows them with the statements
+ options {
+ greedy = true;
+ }
+ :
+ aCase
+ )+
+ caseSList
+ {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
+ ;
+
+aCase
+ : ("case"^ expression | "default") COLON!
+ ;
+
+caseSList
+ : (statement)*
+ {#caseSList = #(#[SLIST,"SLIST"],#caseSList);}
+ ;
+
+// The initializer for a for loop
+forInit
+ // if it looks like a declaration, it is
+ : ( (declaration)=> declaration
+ // otherwise it could be an expression list...
+ | expressionList
+ )?
+ {#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
+ ;
+
+forCond
+ : (expression)?
+ {#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
+ ;
+
+forIter
+ : (expressionList)?
+ {#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
+ ;
+
+// an exception handler try/catch block
+tryBlock
+ : "try"^ compoundStatement
+ (handler)*
+ ( finallyClause )?
+ ;
+
+finallyClause
+ : "finally"^ compoundStatement
+ ;
+
+// an exception handler
+handler
+ : "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement
+ ;
+
+
+// expressions
+// Note that most of these expressions follow the pattern
+// thisLevelExpression :
+// nextHigherPrecedenceExpression
+// (OPERATOR nextHigherPrecedenceExpression)*
+// which is a standard recursive definition for a parsing an expression.
+// The operators in java have the following precedences:
+// lowest (13) = *= /= %= += -= <<= >>= >>>= &= ^= |=
+// (12) ?:
+// (11) ||
+// (10) &&
+// ( 9) |
+// ( 8) ^
+// ( 7) &
+// ( 6) == !=
+// ( 5) < <= > >=
+// ( 4) << >>
+// ( 3) +(binary) -(binary)
+// ( 2) * / %
+// ( 1) ++ -- +(unary) -(unary) ~ ! (type)
+// [] () (method call) . (dot -- identifier qualification)
+// new () (explicit parenthesis)
+//
+// the last two are not usually on a precedence chart; I put them in
+// to point out that new has a higher precedence than '.', so you
+// can validy use
+// new Frame().show()
+//
+// Note that the above precedence levels map to the rules below...
+// Once you have a precedence chart, writing the appropriate rules as below
+// is usually very straightfoward
+
+
+
+// the mother of all expressions
+expression
+ : assignmentExpression
+ {#expression = #(#[EXPR,"EXPR"],#expression);}
+ ;
+
+
+// This is a list of expressions.
+expressionList
+ : expression (COMMA! expression)*
+ {#expressionList = #(#[ELIST,"ELIST"], expressionList);}
+ ;
+
+
+// assignment expression (level 13)
+assignmentExpression
+ : conditionalExpression
+ ( ( ASSIGN^
+ | PLUS_ASSIGN^
+ | MINUS_ASSIGN^
+ | STAR_ASSIGN^
+ | DIV_ASSIGN^
+ | MOD_ASSIGN^
+ | SR_ASSIGN^
+ | BSR_ASSIGN^
+ | SL_ASSIGN^
+ | BAND_ASSIGN^
+ | BXOR_ASSIGN^
+ | BOR_ASSIGN^
+ )
+ assignmentExpression
+ )?
+ ;
+
+
+// conditional test (level 12)
+conditionalExpression
+ : logicalOrExpression
+ ( QUESTION^ assignmentExpression COLON! conditionalExpression )?
+ ;
+
+
+// logical or (||) (level 11)
+logicalOrExpression
+ : logicalAndExpression (LOR^ logicalAndExpression)*
+ ;
+
+
+// logical and (&&) (level 10)
+logicalAndExpression
+ : inclusiveOrExpression (LAND^ inclusiveOrExpression)*
+ ;
+
+
+// bitwise or non-short-circuiting or (|) (level 9)
+inclusiveOrExpression
+ : exclusiveOrExpression (BOR^ exclusiveOrExpression)*
+ ;
+
+
+// exclusive or (^) (level 8)
+exclusiveOrExpression
+ : andExpression (BXOR^ andExpression)*
+ ;
+
+
+// bitwise or non-short-circuiting and (&) (level 7)
+andExpression
+ : equalityExpression (BAND^ equalityExpression)*
+ ;
+
+
+// equality/inequality (==/!=) (level 6)
+equalityExpression
+ : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
+ ;
+
+
+// boolean relational expressions (level 5)
+relationalExpression
+ : shiftExpression
+ ( ( ( LT^
+ | GT^
+ | LE^
+ | GE^
+ )
+ shiftExpression
+ )*
+ | "instanceof"^ typeSpec[true]
+ )
+ ;
+
+
+// bit shift expressions (level 4)
+shiftExpression
+ : additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
+ ;
+
+
+// binary addition/subtraction (level 3)
+additiveExpression
+ : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
+ ;
+
+
+// multiplication/division/modulo (level 2)
+multiplicativeExpression
+ : unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
+ ;
+
+unaryExpression
+ : INC^ unaryExpression
+ | DEC^ unaryExpression
+ | MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
+ | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
+ | unaryExpressionNotPlusMinus
+ ;
+
+unaryExpressionNotPlusMinus
+ : BNOT^ unaryExpression
+ | LNOT^ unaryExpression
+
+ | ( // subrule allows option to shut off warnings
+ options {
+ // "(int" ambig with postfixExpr due to lack of sequence
+ // info in linear approximate LL(k). It's ok. Shut up.
+ generateAmbigWarnings=false;
+ }
+ : // If typecast is built in type, must be numeric operand
+ // Also, no reason to backtrack if type keyword like int, float...
+ lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN!
+ unaryExpression
+
+ // Have to backtrack to see if operator follows. If no operator
+ // follows, it's a typecast. No semantic checking needed to parse.
+ // if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)"
+ | (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
+ lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN!
+ unaryExpressionNotPlusMinus
+
+ | postfixExpression
+ )
+ ;
+
+// qualified names, array expressions, method invocation, post inc/dec
+postfixExpression
+ :
+ /*
+ "this"! lp1:LPAREN^ argList RPAREN!
+ {#lp1.setType(CTOR_CALL);}
+
+ | "super"! lp2:LPAREN^ argList RPAREN!
+ {#lp2.setType(SUPER_CTOR_CALL);}
+ |
+ */
+ primaryExpression
+
+ (
+ /*
+ options {
+ // the use of postfixExpression in SUPER_CTOR_CALL adds DOT
+ // to the lookahead set, and gives loads of false non-det
+ // warnings.
+ // shut them off.
+ generateAmbigWarnings=false;
+ }
+ : */
+ DOT^ IDENT
+ ( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
+ argList
+ RPAREN!
+ )?
+ | DOT^ "this"
+
+ | DOT^ "super"
+ ( // (new Outer()).super() (create enclosing instance)
+ lp3:LPAREN^ argList RPAREN!
+ {#lp3.setType(SUPER_CTOR_CALL);}
+ | DOT^ IDENT
+ ( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
+ argList
+ RPAREN!
+ )?
+ )
+ | DOT^ newExpression
+ | lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK!
+ )*
+
+ ( // possibly add on a post-increment or post-decrement.
+ // allows INC/DEC on too much, but semantics can check
+ in:INC^ {#in.setType(POST_INC);}
+ | de:DEC^ {#de.setType(POST_DEC);}
+ )?
+ ;
+
+// the basic element of an expression
+primaryExpression
+ : identPrimary ( options {greedy=true;} : DOT^ "class" )?
+ | constant
+ | "true"
+ | "false"
+ | "null"
+ | newExpression
+ | "this"
+ | "super"
+ | LPAREN! assignmentExpression RPAREN!
+ // look for int.class and int[].class
+ | builtInType
+ ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
+ DOT^ "class"
+ ;
+
+/** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class,
+ * and a.b.c.class refs. Also this(...) and super(...). Match
+ * this or super.
+ */
+identPrimary
+ : IDENT
+ (
+ options {
+ // .ident could match here or in postfixExpression.
+ // We do want to match here. Turn off warning.
+ greedy=true;
+ }
+ : DOT^ IDENT
+ )*
+ (
+ options {
+ // ARRAY_DECLARATOR here conflicts with INDEX_OP in
+ // postfixExpression on LBRACK RBRACK.
+ // We want to match [] here, so greedy. This overcomes
+ // limitation of linear approximate lookahead.
+ greedy=true;
+ }
+ : ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! )
+ | ( options {greedy=true;} :
+ lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK!
+ )+
+ )?
+ ;
+
+/** object instantiation.
+ * Trees are built as illustrated by the following input/tree pairs:
+ *
+ * new T()
+ *
+ * new
+ * |
+ * T -- ELIST
+ * |
+ * arg1 -- arg2 -- .. -- argn
+ *
+ * new int[]
+ *
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR
+ *
+ * new int[] {1,2}
+ *
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR -- ARRAY_INIT
+ * |
+ * EXPR -- EXPR
+ * | |
+ * 1 2
+ *
+ * new int[3]
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR
+ * |
+ * EXPR
+ * |
+ * 3
+ *
+ * new int[1][2]
+ *
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR
+ * |
+ * ARRAY_DECLARATOR -- EXPR
+ * | |
+ * EXPR 1
+ * |
+ * 2
+ *
+ */
+newExpression
+ : "new"^ type
+ ( LPAREN! argList RPAREN! (classBlock)?
+
+ //java 1.1
+ // Note: This will allow bad constructs like
+ // new int[4][][3] {exp,exp}.
+ // There needs to be a semantic check here...
+ // to make sure:
+ // a) [ expr ] and [ ] are not mixed
+ // b) [ expr ] and an init are not used together
+
+ | newArrayDeclarator (arrayInitializer)?
+ )
+ ;
+
+argList
+ : ( expressionList
+ | /*nothing*/
+ {#argList = #[ELIST,"ELIST"];}
+ )
+ ;
+
+newArrayDeclarator
+ : (
+ // CONFLICT:
+ // newExpression is a primaryExpression which can be
+ // followed by an array index reference. This is ok,
+ // as the generated code will stay in this loop as
+ // long as it sees an LBRACK (proper behavior)
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
+ (expression)?
+ RBRACK!
+ )+
+ ;
+
+constant
+ : NUM_INT
+ | CHAR_LITERAL
+ | STRING_LITERAL
+ | NUM_FLOAT
+ | NUM_LONG
+ | NUM_DOUBLE
+ ;
+
+
+//----------------------------------------------------------------------------
+// The Java scanner
+//----------------------------------------------------------------------------
+class JavaLexer extends Lexer;
+
+options {
+ exportVocab=Java; // call the vocabulary "Java"
+ testLiterals=false; // don't automatically test for literals
+ k=4; // four characters of lookahead
+ charVocabulary='\u0003'..'\uFFFF';
+ // without inlining some bitset tests, couldn't do unicode;
+ // I need to make ANTLR generate smaller bitsets; see
+ // bottom of JavaLexer.java
+ codeGenBitsetTestThreshold=20;
+}
+
+
+
+// OPERATORS
+QUESTION : '?' ;
+LPAREN : '(' ;
+RPAREN : ')' ;
+LBRACK : '[' ;
+RBRACK : ']' ;
+LCURLY : '{' ;
+RCURLY : '}' ;
+COLON : ':' ;
+COMMA : ',' ;
+//DOT : '.' ;
+ASSIGN : '=' ;
+EQUAL : "==" ;
+LNOT : '!' ;
+BNOT : '~' ;
+NOT_EQUAL : "!=" ;
+DIV : '/' ;
+DIV_ASSIGN : "/=" ;
+PLUS : '+' ;
+PLUS_ASSIGN : "+=" ;
+INC : "++" ;
+MINUS : '-' ;
+MINUS_ASSIGN : "-=" ;
+DEC : "--" ;
+STAR : '*' ;
+STAR_ASSIGN : "*=" ;
+MOD : '%' ;
+MOD_ASSIGN : "%=" ;
+SR : ">>" ;
+SR_ASSIGN : ">>=" ;
+BSR : ">>>" ;
+BSR_ASSIGN : ">>>=" ;
+GE : ">=" ;
+GT : ">" ;
+SL : "<<" ;
+SL_ASSIGN : "<<=" ;
+LE : "<=" ;
+LT : '<' ;
+BXOR : '^' ;
+BXOR_ASSIGN : "^=" ;
+BOR : '|' ;
+BOR_ASSIGN : "|=" ;
+LOR : "||" ;
+BAND : '&' ;
+BAND_ASSIGN : "&=" ;
+LAND : "&&" ;
+SEMI : ';' ;
+
+
+// Whitespace -- ignored
+WS : ( ' '
+ | '\t'
+ | '\f'
+ // handle newlines
+ | ( options {generateAmbigWarnings=false;}
+ : "\r\n" // Evil DOS
+ | '\r' // Macintosh
+ | '\n' // Unix (the right way)
+ )
+ { newline(); }
+ )+
+ { _ttype = Token.SKIP; }
+ ;
+
+// Single-line comments
+SL_COMMENT
+ : "//"
+ (~('\n'|'\r'))* ('\n'|'\r'('\n')?)
+ {$setType(Token.SKIP); 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')
+ )*
+ "*/"
+ {$setType(Token.SKIP);}
+ ;
+
+
+// character literals
+CHAR_LITERAL
+ : '\'' ( ESC | ~'\'' ) '\''
+ ;
+
+// string literals
+STRING_LITERAL
+ : '"' (ESC|~('"'|'\\'))* '"'
+ ;
+
+
+// escape sequence -- note that this is protected; it can only be called
+// from another lexer rule -- it will not ever directly return a token to
+// the parser
+// There are various ambiguities hushed in this rule. The optional
+// '0'...'9' digit matches should be matched here rather than letting
+// them go back to STRING_LITERAL to be matched. ANTLR does the
+// right thing by matching immediately; hence, it's ok to shut off
+// the FOLLOW ambig warnings.
+protected
+ESC
+ : '\\'
+ ( 'n'
+ | 'r'
+ | 't'
+ | 'b'
+ | 'f'
+ | '"'
+ | '\''
+ | '\\'
+ | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+ | '0'..'3'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )?
+ | '4'..'7'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )
+ ;
+
+
+// hexadecimal digit (again, note it's protected!)
+protected
+HEX_DIGIT
+ : ('0'..'9'|'A'..'F'|'a'..'f')
+ ;
+
+
+// a dummy rule to force vocabulary to be all characters (except special
+// ones that ANTLR uses internally (0 to 2)
+protected
+VOCAB
+ : '\3'..'\377'
+ ;
+
+
+// an identifier. Note that testLiterals is set to true! This means
+// that after we match the rule, we look in the literals table to see
+// if it's a literal or really an identifer
+IDENT
+ options {testLiterals=true;}
+ : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
+ ;
+
+
+// a numeric literal
+NUM_INT
+ {boolean isDecimal=false; Token t=null;}
+ : '.' {_ttype = DOT;}
+ ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
+ {
+ if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
+ _ttype = NUM_FLOAT;
+ }
+ else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ }
+ )?
+
+ | ( '0' {isDecimal = true;} // special case for just '0'
+ ( ('x'|'X')
+ ( // hex
+ // the 'e'|'E' and float suffix stuff look
+ // like hex digits, hence the (...)+ doesn't
+ // know when to stop: ambig. ANTLR resolves
+ // it correctly by matching immediately. It
+ // is therefor ok to hush warning.
+ options {
+ warnWhenFollowAmbig=false;
+ }
+ : HEX_DIGIT
+ )+
+ | ('0'..'7')+ // octal
+ )?
+ | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
+ )
+ ( ('l'|'L') { _ttype = NUM_LONG; }
+
+ // only check to see if it's a float if looks like decimal so far
+ | {isDecimal}?
+ ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
+ | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
+ | f4:FLOAT_SUFFIX {t=f4;}
+ )
+ {
+ if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
+ _ttype = NUM_FLOAT;
+ }
+ else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ }
+ )?
+ ;
+
+
+// a couple protected methods to assist in matching floating point numbers
+protected
+EXPONENT
+ : ('e'|'E') ('+'|'-')? ('0'..'9')+
+ ;
+
+
+protected
+FLOAT_SUFFIX
+ : 'f'|'F'|'d'|'D'
+ ;
+
diff --git a/app/src/antlr/java/java.g.java15 b/app/src/antlr/java/java.g.java15
new file mode 100644
index 000000000..b119cd35f
--- /dev/null
+++ b/app/src/antlr/java/java.g.java15
@@ -0,0 +1,2002 @@
+header
+{
+package de.hunsicker.jalopy.language.antlr;
+
+import de.hunsicker.jalopy.language.antlr.JavaNode;
+import de.hunsicker.jalopy.language.JavaNodeHelper;
+}
+
+/** Java 1.5 Recognizer
+ *
+ * Run 'java Main [-showtree] directory-full-of-java-files'
+ *
+ * [The -showtree option pops up a Swing frame that shows
+ * the JavaNode constructed from the parser.]
+ *
+ * Run 'java Main '
+ *
+ * Contributing authors:
+ * John Mitchell johnm@non.net
+ * Terence Parr parrt@magelang.com
+ * John Lilley jlilley@empathy.com
+ * Scott Stanchfield thetick@magelang.com
+ * Markus Mohnen mohnen@informatik.rwth-aachen.de
+ * Peter Williams pete.williams@sun.com
+ * Allan Jacobs Allan.Jacobs@eng.sun.com
+ * Steve Messick messick@redhills.com
+ * John Pybus john@pybus.org
+ *
+ * Version 1.00 December 9, 1997 -- initial release
+ * Version 1.01 December 10, 1997
+ * fixed bug in octal def (0..7 not 0..8)
+ * Version 1.10 August 1998 (parrt)
+ * added tree construction
+ * fixed definition of WS,comments for mac,pc,unix newlines
+ * added unary plus
+ * Version 1.11 (Nov 20, 1998)
+ * Added "shutup" option to turn off last ambig warning.
+ * Fixed inner class def to allow named class defs as statements
+ * synchronized requires compound not simple statement
+ * add [] after builtInType DOT class in primaryExpression
+ * "const" is reserved but not valid..removed from modifiers
+ * Version 1.12 (Feb 2, 1999)
+ * Changed LITERAL_xxx to xxx in tree grammar.
+ * Updated java.g to use tokens {...} now for 2.6.0 (new feature).
+ *
+ * Version 1.13 (Apr 23, 1999)
+ * Didn't have (stat)? for else clause in tree parser.
+ * Didn't gen ASTs for interface extends. Updated tree parser too.
+ * Updated to 2.6.0.
+ * Version 1.14 (Jun 20, 1999)
+ * Allowed final/abstract on local classes.
+ * Removed local interfaces from methods
+ * Put instanceof precedence where it belongs...in relationalExpr
+ * It also had expr not type as arg; fixed it.
+ * Missing ! on SEMI in classBlock
+ * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
+ * fixed: didn't like Object[].class in parser or tree parser
+ * Version 1.15 (Jun 26, 1999)
+ * Screwed up rule with instanceof in it. :( Fixed.
+ * Tree parser didn't like (expr).something; fixed.
+ * Allowed multiple inheritance in tree grammar. oops.
+ * Version 1.16 (August 22, 1999)
+ * Extending an interface built a wacky tree: had extra EXTENDS.
+ * Tree grammar didn't allow multiple superinterfaces.
+ * Tree grammar didn't allow empty var initializer: {}
+ * Version 1.17 (October 12, 1999)
+ * ESC lexer rule allowed 399 max not 377 max.
+ * java.tree.g didn't handle the expression of synchronized
+ * statements.
+ * Version 1.18 (August 12, 2001)
+ * Terence updated to Java 2 Version 1.3 by
+ * observing/combining work of Allan Jacobs and Steve
+ * Messick. Handles 1.3 src. Summary:
+ * o primary didn't include boolean.class kind of thing
+ * o constructor calls parsed explicitly now:
+ * see explicitConstructorInvocation
+ * o add strictfp modifier
+ * o missing objBlock after new expression in tree grammar
+ * o merged local class definition alternatives, moved after declaration
+ * o fixed problem with ClassName.super.field
+ * o reordered some alternatives to make things more efficient
+ * o long and double constants were not differentiated from int/float
+ * o whitespace rule was inefficient: matched only one char
+ * o add an examples directory with some nasty 1.3 cases
+ * o made Main.java use buffered IO and a Reader for Unicode support
+ * o supports UNICODE?
+ * Using Unicode charVocabulay makes code file big, but only
+ * in the bitsets at the end. I need to make ANTLR generate
+ * unicode bitsets more efficiently.
+ * Version 1.19 (April 25, 2002)
+ * Terence added in nice fixes by John Pybus concerning floating
+ * constants and problems with super() calls. John did a nice
+ * reorg of the primary/postfix expression stuff to read better
+ * and makes f.g.super() parse properly (it was METHOD_CALL not
+ * a SUPER_CTOR_CALL). Also:
+ *
+ * o "finally" clause was a root...made it a child of "try"
+ * o Added stuff for asserts too for Java 1.4, but *commented out*
+ * as it is not backward compatible.
+ *
+ * Version 1.20 (October 27, 2002)
+ *
+ * Terence ended up reorging John Pybus' stuff to
+ * remove some nondeterminisms and some syntactic predicates.
+ * Note that the grammar is stricter now; e.g., this(...) must
+ * be the first statement.
+ *
+ * Trinary ?: operator wasn't working as array name:
+ * (isBig ? bigDigits : digits)[i];
+ *
+ * Checked parser/tree parser on source for
+ * Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4,
+ * and the 110k-line jGuru server source.
+ *
+ * Version 1.21 (October 17, 2003)
+ * Fixed lots of problems including:
+ * Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g
+ * He found a problem/fix with floating point that start with 0
+ * Ray also fixed problem that (int.class) was not recognized.
+ * Thorsten van Ellen noticed that \n are allowed incorrectly in strings.
+ * TJP fixed CHAR_LITERAL analogously.
+ *
+ * Version 1.21.2 (March, 2003)
+ * Changes by Matt Quail to support generics (as per JDK1.5/JSR14)
+ * Notes:
+ * o We only allow the "extends" keyword and not the "implements"
+ * keyword, since thats what JSR14 seems to imply.
+ * o Thanks to Monty Zukowski for his help on the antlr-interest
+ * mail list.
+ * o Thanks to Alan Eliasen for testing the grammar over his
+ * Fink source base
+ *
+ * Version 1.22 (July, 2004)
+ * Changes by Michael Studman to support Java 1.5 language extensions
+ * Notes:
+ * o Added support for annotations types
+ * o Finished off Matt Quail's generics enhancements to support bound type arguments
+ * o Added support for new for statement syntax
+ * o Added support for static import syntax
+ * o Added support for enum types
+ * o Tested against JDK 1.5 source base and source base of jdigraph project
+ * o Thanks to Matt Quail for doing the hard part by doing most of the generics work
+ *
+ * Version 1.22.1 (July 28, 2004)
+ * Bug/omission fixes for Java 1.5 language support
+ * o Fixed tree structure bug with classOrInterface - thanks to Pieter Vangorpto for
+ * spotting this
+ * o Fixed bug where incorrect handling of SR and BSR tokens would cause type
+ * parameters to be recognised as type arguments.
+ * o Enabled type parameters on constructors, annotations on enum constants
+ * and package definitions
+ * o Fixed problems when parsing if ((char.class.equals(c))) {} - solution by Matt Quail at Cenqua
+ *
+ * Version 1.22.2 (July 28, 2004)
+ * Slight refactoring of Java 1.5 language support
+ * o Refactored for/"foreach" productions so that original literal "for" literal
+ * is still used but the for sub-clauses vary by token type
+ * o Fixed bug where type parameter was not included in generic constructor's branch of AST
+ *
+ * Version 1.22.3 (August 26, 2004)
+ * Bug fixes as identified by Michael Stahl; clean up of tabs/spaces
+ * and other refactorings
+ * o Fixed typeParameters omission in identPrimary and newStatement
+ * o Replaced GT reconcilliation code with simple semantic predicate
+ * o Adapted enum/assert keyword checking support from Michael Stahl's java15 grammar
+ * o Refactored typeDefinition production and field productions to reduce duplication
+ *
+ * Version 1.22.4 (October 21, 2004)
+ * Small bux fixes
+ * o Added typeArguments to explicitConstructorInvocation, e.g. new MyParameterised()
+ * o Added typeArguments to postfixExpression productions for anonymous inner class super
+ * constructor invocation, e.g. new Outer().super()
+ * o Fixed bug in array declarations identified by Geoff Roy
+ *
+ * This grammar is in the PUBLIC DOMAIN
+ */
+
+class InternalJavaParser extends Parser;
+options {
+ k = 2; // two token lookahead
+ exportVocab=Java; // Call its vocabulary "Java"
+ codeGenMakeSwitchThreshold = 2; // Some optimizations
+ codeGenBitsetTestThreshold = 3;
+ defaultErrorHandler = false; // Don't generate parser error handlers
+ buildAST = true;
+// classHeaderSuffix = "Parser";
+ importVocab = Common;
+ ASTLabelType = JavaNode;
+// useTokenPrefix = true;
+ // This class is abstract
+ classHeaderPrefix = "public abstract";
+
+}
+tokens {
+ BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF;
+ INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF;
+ PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
+ PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP;
+ POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT;
+ IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION;
+ FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";
+ STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL; VARIABLE_PARAMETER_DEF;
+ STATIC_IMPORT; ENUM_DEF; ENUM_CONSTANT_DEF; FOR_EACH_CLAUSE; ANNOTATION_DEF; ANNOTATIONS;
+ ANNOTATION; ANNOTATION_MEMBER_VALUE_PAIR; ANNOTATION_FIELD_DEF; ANNOTATION_ARRAY_INIT;
+ TYPE_ARGUMENTS; TYPE_ARGUMENT; TYPE_PARAMETERS; TYPE_PARAMETER; WILDCARD_TYPE;
+ TYPE_UPPER_BOUNDS; TYPE_LOWER_BOUNDS;
+
+ ROOT;CASESLIST;SEPARATOR_COMMENT;BOF;SYNBLOCK;SPECIAL_COMMENT;
+
+}
+
+{
+ /**
+ * Counts the number of LT seen in the typeArguments production.
+ * It is used in semantic predicates to ensure we have seen
+ * enough closing '>' characters; which actually may have been
+ * either GT, SR or BSR tokens.
+ */
+ private int ltCounter = 0;
+
+ protected abstract void attachStuff(JavaNode[] nodes) throws TokenStreamIOException;
+
+}
+
+// Compilation Unit: In Java, this is a single file. This is the start
+// rule for this parser compilationUnit
+parse
+ {
+ JavaNode root = (JavaNode) getASTFactory().create();
+ root.setType(JavaTokenTypes.ROOT);
+ root.setText(getFilename());
+ currentAST.root = root;
+ }
+
+ : // A compilation unit starts with an optional package definition
+ ( (annotations "package")=> packageDefinition
+ | /* nothing */
+ )
+
+ // Next we have a series of zero or more import statements
+ ( importDefinition )*
+
+ // Wrapping things up with any number of class or interface
+ // definitions
+ ( typeDefinition )*
+
+ EOF
+ ;
+
+
+// Package statement: optional annotations followed by "package" then the package identifier.
+packageDefinition
+ options {defaultErrorHandler = true;} // let ANTLR handle errors
+ : annotations p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI
+ ;
+
+
+// Import statement: import followed by a package or class name
+importDefinition
+ options {defaultErrorHandler = true;}
+ { boolean isStatic = false; }
+ : i:"import"^ {#i.setType(IMPORT);} ( "static"! {#i.setType(STATIC_IMPORT);} )? identifierStar SEMI
+ ;
+
+// A type definition is either a class, interface, enum or annotation with possible additional semis.
+typeDefinition
+ options {defaultErrorHandler = true;}
+ : m:modifiers!
+ typeDefinitionInternal[#m]
+ | SEMI
+ ;
+
+// Protected type definitions production for reuse in other productions
+protected typeDefinitionInternal[JavaNode mods]
+ : classDefinition[#mods] // inner class
+ | interfaceDefinition[#mods] // inner interface
+ | enumDefinition[#mods] // inner enum
+ | annotationDefinition[#mods] // inner annotation
+ ;
+
+// A declaration is the creation of a reference or primitive-type variable
+// Create a separate Type/Var tree for each var in the var list.
+declaration!
+ : m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
+ {#declaration = #v;}
+ ;
+
+// A type specification is a type name with possible brackets afterwards
+// (which would make it an array type).
+typeSpec[boolean addImagNode]
+ : classTypeSpec[addImagNode]
+ | builtInTypeSpec[addImagNode]
+ ;
+
+// A class type specification is a class type with either:
+// - possible brackets afterwards
+// (which would make it an array type).
+// - generic type arguments after
+classTypeSpec[boolean addImagNode]
+ : classOrInterfaceType[false]
+ (options{greedy=true;}: // match as many as possible
+ lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
+ )*
+ {
+ if ( addImagNode ) {
+ #classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
+ }
+ }
+ ;
+
+// A non-built in type name, with possible type parameters
+classOrInterfaceType[boolean addImagNode]
+ : IDENT^ (typeArguments)?
+ (options{greedy=true;}: // match as many as possible
+ DOT^
+ IDENT (typeArguments)?
+ )*
+ {
+ if ( addImagNode ) {
+ #classOrInterfaceType = #(#[TYPE,"TYPE"], #classOrInterfaceType);
+ }
+ }
+ ;
+
+// A specialised form of typeSpec where built in types must be arrays
+typeArgumentSpec
+ : classTypeSpec[true]
+ | builtInTypeArraySpec[true]
+ ;
+
+// A generic type argument is a class type, a possibly bounded wildcard type or a built-in type array
+typeArgument
+ : ( typeArgumentSpec
+ | wildcardType
+ )
+ {#typeArgument = #(#[TYPE_ARGUMENT,"TYPE_ARGUMENT"], #typeArgument);}
+ ;
+
+// Wildcard type indicating all types (with possible constraint)
+wildcardType
+ : q:QUESTION^ {#q.setType(WILDCARD_TYPE);}
+ (("extends" | "super")=> typeArgumentBounds)?
+ ;
+
+// Type arguments to a class or interface type
+typeArguments
+{int currentLtLevel = 0;}
+ :
+ {currentLtLevel = ltCounter;}
+ LT! {ltCounter++;}
+ typeArgument
+ (options{greedy=true;}: // match as many as possible
+ {inputState.guessing !=0 || ltCounter == currentLtLevel + 1}?
+ COMMA typeArgument
+ )*
+
+ ( // turn warning off since Antlr generates the right code,
+ // plus we have our semantic predicate below
+ options{generateAmbigWarnings=false;}:
+ typeArgumentsOrParametersEnd
+ )?
+
+ // make sure we have gobbled up enough '>' characters
+ // if we are at the "top level" of nested typeArgument productions
+ {(currentLtLevel != 0) || ltCounter == currentLtLevel}?
+
+ {#typeArguments = #(#[TYPE_ARGUMENTS, "TYPE_ARGUMENTS"], #typeArguments);}
+ ;
+
+// this gobbles up *some* amount of '>' characters, and counts how many
+// it gobbled.
+protected typeArgumentsOrParametersEnd
+ : GT! {ltCounter-=1;}
+ | SR! {ltCounter-=2;}
+ | BSR! {ltCounter-=3;}
+ ;
+
+// Restriction on wildcard types based on super class or derrived class
+typeArgumentBounds
+ {boolean isUpperBounds = false;}
+ :
+ ( "extends"! {isUpperBounds=true;} | "super"! ) classOrInterfaceType[false]
+ {
+ if (isUpperBounds)
+ {
+ #typeArgumentBounds = #(#[TYPE_UPPER_BOUNDS,"TYPE_UPPER_BOUNDS"], #typeArgumentBounds);
+ }
+ else
+ {
+ #typeArgumentBounds = #(#[TYPE_LOWER_BOUNDS,"TYPE_LOWER_BOUNDS"], #typeArgumentBounds);
+ }
+ }
+ ;
+
+// A builtin type array specification is a builtin type with brackets afterwards
+builtInTypeArraySpec[boolean addImagNode]
+ : builtInType
+ (options{greedy=true;}: // match as many as possible
+ lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
+ )+
+
+ {
+ if ( addImagNode ) {
+ #builtInTypeArraySpec = #(#[TYPE,"TYPE"], #builtInTypeArraySpec);
+ }
+ }
+ ;
+
+// A builtin type specification is a builtin type with possible brackets
+// afterwards (which would make it an array type).
+builtInTypeSpec[boolean addImagNode]
+ : builtInType
+ (options{greedy=true;}: // match as many as possible
+ lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
+ )*
+ {
+ if ( addImagNode ) {
+ #builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
+ }
+ }
+ ;
+
+// A type name. which is either a (possibly qualified and parameterized)
+// class name or a primitive (builtin) type
+type
+ : classOrInterfaceType[false]
+ | builtInType
+ ;
+
+// The primitive types.
+builtInType
+ : "void"
+ | "boolean"
+ | "byte"
+ | "char"
+ | "short"
+ | "int"
+ | "float"
+ | "long"
+ | "double"
+ ;
+
+// A (possibly-qualified) java identifier. We start with the first IDENT
+// and expand its name by adding dots and following IDENTS
+identifier
+ : IDENT ( DOT^ IDENT )*
+ ;
+
+identifierStar
+ : IDENT
+ ( DOT^ IDENT )*
+ ( DOT^ STAR )?
+ ;
+
+// A list of zero or more modifiers. We could have used (modifier)* in
+// place of a call to modifiers, but I thought it was a good idea to keep
+// this rule separate so they can easily be collected in a Vector if
+// someone so desires
+modifiers
+ :
+ (
+ //hush warnings since the semantic check for "@interface" solves the non-determinism
+ options{generateAmbigWarnings=false;}:
+
+ modifier
+ |
+ //Semantic check that we aren't matching @interface as this is not an annotation
+ //A nicer way to do this would be nice
+ {LA(1)==AT && !LT(2).getText().equals("interface")}? annotation
+ )*
+
+ {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
+ ;
+
+// modifiers for Java classes, interfaces, class/instance vars and methods
+modifier
+ : "private"
+ | "public"
+ | "protected"
+ | "static"
+ | "transient"
+ | "final"
+ | "abstract"
+ | "native"
+ | "threadsafe"
+ | "synchronized"
+ | "volatile"
+ | "strictfp"
+ ;
+
+annotation!
+ : a:AT i:identifier ( lp:LPAREN ( args:annotationArguments )? rp:RPAREN )?
+ {#annotation = #(#[ANNOTATION,"ANNOTATION"],a, i, lp, args, rp);}
+ ;
+
+annotations
+ : (annotation)*
+ {#annotations = #([ANNOTATIONS, "ANNOTATIONS"], #annotations);}
+ ;
+
+annotationArguments
+ : annotationMemberValueInitializer | anntotationMemberValuePairs
+ ;
+
+anntotationMemberValuePairs
+ : annotationMemberValuePair ( COMMA annotationMemberValuePair )*
+ ;
+
+annotationMemberValuePair!
+ : i:IDENT ASSIGN! v:annotationMemberValueInitializer
+ {#annotationMemberValuePair = #(#[ANNOTATION_MEMBER_VALUE_PAIR,"ANNOTATION_MEMBER_VALUE_PAIR"], i, v);}
+ ;
+
+annotationMemberValueInitializer
+ :
+ conditionalExpression | annotation | annotationMemberArrayInitializer
+ ;
+
+// This is an initializer used to set up an annotation member array.
+annotationMemberArrayInitializer
+ : lc:LCURLY^ {#lc.setType(ANNOTATION_ARRAY_INIT);}
+ ( annotationMemberArrayValueInitializer
+ (
+ // CONFLICT: does a COMMA after an initializer start a new
+ // initializer or start the option ',' at end?
+ // ANTLR generates proper code by matching
+ // the comma as soon as possible.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ COMMA annotationMemberArrayValueInitializer
+ )*
+ (COMMA)?
+ )?
+ RCURLY
+ ;
+
+// The two things that can initialize an annotation array element are a conditional expression
+// and an annotation (nested annotation array initialisers are not valid)
+annotationMemberArrayValueInitializer
+ : conditionalExpression
+ | annotation
+ ;
+
+superClassClause!
+ : ( "extends" c:classOrInterfaceType[false] )?
+ {#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],c);}
+ ;
+
+// Definition of a Java class
+classDefinition![JavaNode modifiers]
+ : c:"class" IDENT
+ // it _might_ have type paramaters
+ (tp:typeParameters)?
+ // 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,IDENT,tp,sc,ic,cb);
+ attachStuff(new JavaNode[] {#classDefinition, modifiers, #c});
+ }
+ ;
+
+// Definition of a Java Interface
+interfaceDefinition![JavaNode modifiers]
+ : i:"interface" IDENT
+ // it _might_ have type paramaters
+ (tp:typeParameters)?
+ // it might extend some other interfaces
+ ie:interfaceExtends
+ // now parse the body of the interface (looks like a class...)
+ ib:interfaceBlock
+ {#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
+ modifiers,IDENT,tp,ie,ib);
+ attachStuff(new JavaNode[] {#interfaceDefinition, modifiers, #i});
+ }
+ ;
+
+enumDefinition![JavaNode modifiers]
+ : e:"enum" IDENT
+ // it might implement some interfaces...
+ ic:implementsClause
+ // now parse the body of the enum
+ eb:enumBlock
+ {#enumDefinition = #(#[ENUM_DEF,"ENUM_DEF"],
+ modifiers,IDENT,ic,eb);
+ attachStuff(new JavaNode[] {#enumDefinition, modifiers, #e});
+ }
+ ;
+
+annotationDefinition![JavaNode modifiers]
+ : a:AT "interface" IDENT
+ // now parse the body of the annotation
+ ab:annotationBlock
+ {#annotationDefinition = #(#[ANNOTATION_DEF,"ANNOTATION_DEF"],
+ modifiers,IDENT,ab);
+ attachStuff(new JavaNode[] {#annotationDefinition, modifiers, #a});
+ }
+ ;
+
+typeParameters
+{int currentLtLevel = 0;}
+ :
+ {currentLtLevel = ltCounter;}
+ LT {ltCounter++;}
+ typeParameter (COMMA typeParameter)*
+ (typeArgumentsOrParametersEnd)?
+
+ // make sure we have gobbled up enough '>' characters
+ // if we are at the "top level" of nested typeArgument productions
+ {(currentLtLevel != 0) || ltCounter == currentLtLevel}?
+
+ {#typeParameters = #(#[TYPE_PARAMETERS, "TYPE_PARAMETERS"], #typeParameters);}
+ ;
+
+typeParameter
+ :
+ // I'm pretty sure Antlr generates the right thing here:
+ (id:IDENT) ( options{generateAmbigWarnings=false;}: typeParameterBounds )?
+ {#typeParameter = #(#[TYPE_PARAMETER,"TYPE_PARAMETER"], #typeParameter);}
+ ;
+
+typeParameterBounds
+ :
+ "extends"! classOrInterfaceType[false]
+ (BAND classOrInterfaceType[false])*
+ {#typeParameterBounds = #(#[TYPE_UPPER_BOUNDS,"TYPE_UPPER_BOUNDS"], #typeParameterBounds);}
+ ;
+
+// This is the body of a class. You can have classFields and extra semicolons.
+classBlock
+ : lc:LCURLY^
+ ( classField | SEMI )*
+ RCURLY
+ { #lc.setType(OBJBLOCK);}
+ //{#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
+ ;
+
+// This is the body of an interface. You can have interfaceField and extra semicolons.
+interfaceBlock
+ : lc:LCURLY^
+ ( interfaceField | SEMI )*
+ RCURLY
+ { #lc.setType(OBJBLOCK);}
+ //{#interfaceBlock = #([OBJBLOCK, "OBJBLOCK"], #interfaceBlock);}
+ ;
+
+// This is the body of an annotation. You can have annotation fields and extra semicolons,
+// That's about it (until you see what an annoation field is...)
+annotationBlock
+ : lc:LCURLY^
+ ( annotationField | SEMI )*
+ RCURLY
+ { #lc.setType(OBJBLOCK);}
+// {#annotationBlock = #([OBJBLOCK, "OBJBLOCK"], #annotationBlock);}
+ ;
+
+// This is the body of an enum. You can have zero or more enum constants
+// followed by any number of fields like a regular class
+enumBlock
+ : lc:LCURLY^
+ ( enumConstant ( options{greedy=true;}: COMMA! enumConstant )* ( COMMA! )? )?
+ ( SEMI! ( classField | SEMI! )* )?
+ RCURLY
+ { #lc.setType(OBJBLOCK);}
+// {#enumBlock = #([OBJBLOCK, "OBJBLOCK"], #enumBlock);}
+ ;
+
+// An annotation field
+annotationField!
+ : mods:modifiers
+ ( td:typeDefinitionInternal[#mods]
+ {#annotationField = #td;}
+ | t:typeSpec[false] // annotation field
+ ( i:IDENT // the name of the field
+
+ LPAREN RPAREN
+
+ rt:declaratorBrackets[#t]
+
+ ( "default" amvi:annotationMemberValueInitializer ) ?
+// { if (#d!=null) #d = #(d,#(amvi)); }
+
+ SEMI
+
+ {#annotationField =
+ #(#[ANNOTATION_FIELD_DEF,"ANNOTATION_FIELD_DEF"],
+ mods,
+ #(#[TYPE,"TYPE"],rt),
+ i,LPAREN,RPAREN,amvi,SEMI
+ );
+ attachStuff(new JavaNode[] {#annotationField, #mods, #t});
+ }
+ | v:variableDefinitions[#mods,#t] // typeVariableDefinitions
+ {
+ #annotationField = #v;
+ }
+ )
+ )
+ ;
+
+//An enum constant may have optional parameters and may have a
+//a class body
+enumConstant!
+ : an:annotations
+ i:IDENT
+ ( lp:LPAREN
+ a:argList
+ rp:RPAREN
+ )?
+ ( b:enumConstantBlock )?
+ {#enumConstant = #([ENUM_CONSTANT_DEF, "ENUM_CONSTANT_DEF"], an, i, lp,a,rp, b);}
+ ;
+
+//The class-like body of an enum constant
+enumConstantBlock
+ : LCURLY
+ ( enumConstantField | SEMI )*
+ RCURLY
+ {#enumConstantBlock = #([OBJBLOCK, "OBJBLOCK"], #enumConstantBlock);}
+ ;
+
+//An enum constant field is just like a class field but without
+//the posibility of a constructor definition or a static initializer
+enumConstantField!
+ : mods:modifiers
+ ( td:typeDefinitionInternal[#mods]
+ {#enumConstantField = #td;}
+
+ | // A generic method has the typeParameters before the return type.
+ // This is not allowed for variable definitions, but this production
+ // allows it, a semantic check could be used if you wanted.
+ (tp:typeParameters)? t:typeSpec[false] // method or variable declaration(s)
+ ( IDENT // the name of the method
+
+ // parse the formal parameter declarations.
+ LPAREN param:parameterDeclarationList RPAREN
+
+ rt:declaratorBrackets[#t]
+
+ // get the list of exceptions that this method is
+ // declared to throw
+ (tc:throwsClause)?
+
+ ( s2:compoundStatement | semim:SEMI )
+ {#enumConstantField = #(#[METHOD_DEF,"METHOD_DEF"],
+ mods,
+ tp,
+ #(#[TYPE,"TYPE"],rt),
+ IDENT,
+ param,
+ tc,
+ s2,
+ semim);
+ attachStuff(new JavaNode[] {#enumConstantField, #mods, #t});
+ }
+ | v:variableDefinitions[#mods,#t] // typeVariableDefinitions
+ {#enumConstantField = #v;
+ }
+ )
+ )
+
+ // "{ ... }" instance initializer
+ | s4:compoundStatement
+ {#enumConstantField = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);
+ attachStuff(new JavaNode[] {#enumConstantField, #s4});
+ }
+ ;
+
+// An interface can extend several other interfaces...
+interfaceExtends
+ : (
+ e:"extends"!
+ classOrInterfaceType[false] ( COMMA! classOrInterfaceType[false] )*
+ )?
+ {#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
+ #interfaceExtends);}
+ ;
+
+// A class can implement several interfaces...
+implementsClause
+ : (
+ i:"implements"! classOrInterfaceType[false] ( COMMA! classOrInterfaceType[false] )*
+ )?
+ {#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
+ #implementsClause);}
+ ;
+
+// Now the various things that can be defined inside a class
+classField!
+ : // method, constructor, or variable declaration
+ mods:modifiers
+ ( td:typeDefinitionInternal[#mods]
+ {#classField = #td;}
+
+ | (tp:typeParameters)?
+ (
+ h:ctorHead s:constructorBody // constructor
+ {#classField = #(#[CTOR_DEF,"CTOR_DEF"], mods, tp, h, s);
+ attachStuff(new JavaNode[] {#classField, #mods, #h});
+ }
+
+ | // A generic method/ctor has the typeParameters before the return type.
+ // This is not allowed for variable definitions, but this production
+ // allows it, a semantic check could be used if you wanted.
+ t:typeSpec[false] // method or variable declaration(s)
+ ( IDENT // the name of the method
+
+ // parse the formal parameter declarations.
+ LPAREN param:parameterDeclarationList RPAREN
+
+ rt:declaratorBrackets[#t]
+
+ // get the list of exceptions that this method is
+ // declared to throw
+ (tc:throwsClause)?
+
+ ( s2:compoundStatement | semim:SEMI )
+ {#classField = #(#[METHOD_DEF,"METHOD_DEF"],
+ mods,
+ tp,
+ #(#[TYPE,"TYPE"],rt),
+ IDENT,
+ LPAREN,
+ param,
+ RPAREN,
+ tc,
+ s2,
+ semim);
+ attachStuff(new JavaNode[] {#classField, #mods, #t});
+ }
+ | v:variableDefinitions[#mods,#t] semi:SEMI!// typeVariableDefinitions
+ {
+ #classField = #v;
+
+ #classField.addChild(#semi);
+
+ AST next = #classField.getNextSibling();
+ // HACK for multiple variable declaration in one statement
+ // e.g float x, y, z;
+ // the semicolon will only be added to the first statement so
+ // we have to add it manually to all others
+ if (next != null)
+ {
+ AST ssemi = JavaNodeHelper.getFirstChild(#classField, JavaTokenTypes.SEMI);
+
+ for (AST var = next; var != null; var = var.getNextSibling())
+ {
+ var.addChild(astFactory.create(ssemi));
+ }
+ }
+
+
+ }
+ )
+ )
+ )
+
+ // "static { ... }" class initializer
+ | "static" s3:compoundStatement
+ {#classField = #(#[STATIC_INIT,"STATIC_INIT"], s3);
+ attachStuff(new JavaNode[] {#classField, #s3});
+ }
+
+ // "{ ... }" instance initializer
+ | s4:compoundStatement
+ {#classField = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);
+ attachStuff(new JavaNode[] {#classField, #s4});
+ }
+ ;
+
+// Now the various things that can be defined inside a interface
+interfaceField!
+ : // method, constructor, or variable declaration
+ mods:modifiers
+ ( td:typeDefinitionInternal[#mods]
+ {#interfaceField = #td;}
+
+ | (tp:typeParameters)?
+ // A generic method has the typeParameters before the return type.
+ // This is not allowed for variable definitions, but this production
+ // allows it, a semantic check could be used if you want a more strict
+ // grammar.
+ t:typeSpec[false] // method or variable declaration(s)
+ ( IDENT // the name of the method
+
+ // parse the formal parameter declarations.
+ LPAREN param:parameterDeclarationList RPAREN
+
+ rt:declaratorBrackets[#t]
+
+ // get the list of exceptions that this method is
+ // declared to throw
+ (tc:throwsClause)?
+
+ SEMI
+
+ {#interfaceField = #(#[METHOD_DEF,"METHOD_DEF"],
+ mods,
+ tp,
+ #(#[TYPE,"TYPE"],rt),
+ IDENT,
+ LPAREN,
+ param,
+ RPAREN,
+ tc,
+ SEMI);
+ attachStuff(new JavaNode[] {#interfaceField, #mods, #t});
+ }
+ | v:variableDefinitions[#mods,#t] semi:SEMI!
+ {
+ #interfaceField = #v;
+
+ #interfaceField.addChild(#semi);
+
+ AST next = #interfaceField.getNextSibling();
+ // HACK for multiple variable declaration in one statement
+ // e.g float x, y, z;
+ // the semicolon will only be added to the first statement so
+ // we have to add it manually to all others
+ if (next != null)
+ {
+ AST ssemi = JavaNodeHelper.getFirstChild(#interfaceField, JavaTokenTypes.SEMI);
+
+ for (AST var = next; var != null; var = var.getNextSibling())
+ {
+ var.addChild(astFactory.create(ssemi));
+ }
+ }
+
+
+ }
+ )
+ )
+ ;
+
+constructorBody
+ : lc:LCURLY^ {#lc.setType(SLIST);}
+ ( options { greedy=true; } : explicitConstructorInvocation)?
+ (statement)*
+ RCURLY
+ ;
+
+/** Catch obvious constructor calls, but not the expr.super(...) calls */
+explicitConstructorInvocation
+ : (typeArguments)?
+ ( "this" lp1:LPAREN^ argList RPAREN SEMI
+ {#lp1.setType(CTOR_CALL);}
+ | "super" lp2:LPAREN^ argList RPAREN SEMI
+ {#lp2.setType(SUPER_CTOR_CALL);}
+ )
+ ;
+
+/** Catch variable definitions but add the semicolon ???*/
+typeVariableDefinitions[JavaNode mods, JavaNode t]
+ : v:variableDefinitions[mods,t]
+ (semi:SEMI
+ {
+ #v.addChild(#semi);
+ }
+ )
+ ;
+
+variableDefinitions[JavaNode mods, JavaNode t]
+ : variableDeclarator[(JavaNode)getASTFactory().dupTree(mods),
+ (JavaNode)getASTFactory().dupTree(t)]
+ ( COMMA!
+ variableDeclarator[(JavaNode)getASTFactory().dupTree(mods),
+ (JavaNode)getASTFactory().dupTree(t)]
+ )*
+
+ ;
+
+/** Declaration of a variable. This can be a class/instance variable,
+ * or a local variable in a method
+ * It can also include possible initialization.
+ */
+variableDeclarator![JavaNode mods, JavaNode t]
+ : id:IDENT d:declaratorBrackets[t] v:varInitializer
+ {#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);
+ attachStuff(new JavaNode[] {#variableDeclarator,mods, t});
+ }
+ ;
+
+declaratorBrackets[JavaNode typ]
+ : {#declaratorBrackets=typ;}
+ (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ ;
+
+varInitializer
+ : ( ASSIGN^ initializer )?
+ ;
+
+// This is an initializer used to set up an array.
+arrayInitializer
+ : lc:LCURLY^ {#lc.setType(ARRAY_INIT);}
+ ( initializer
+ (
+ // CONFLICT: does a COMMA after an initializer start a new
+ // initializer or start the option ',' at end?
+ // ANTLR generates proper code by matching
+ // the comma as soon as possible.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ COMMA initializer
+ )*
+ (COMMA)?
+ )?
+ RCURLY
+ ;
+
+
+// The two "things" that can initialize an array element are an expression
+// and another (nested) array initializer.
+initializer
+ : expression
+ | arrayInitializer
+ ;
+
+// This is the header of a method. It includes the name and parameters
+// for the method.
+// This also watches for a list of exception classes in a "throws" clause.
+ctorHead
+ : IDENT // the name of the method
+
+ // parse the formal parameter declarations.
+ LPAREN parameterDeclarationList RPAREN
+
+ // get the list of exceptions that this method is declared to throw
+ (throwsClause)?
+ ;
+
+// This is a list of exception classes that the method is declared to throw
+throwsClause
+ : "throws"^ identifier ( COMMA identifier )*
+ ;
+
+// A list of formal parameters
+// Zero or more parameters
+// If a parameter is variable length (e.g. String... myArg) it is the right-most parameter
+parameterDeclarationList
+ // The semantic check in ( .... )* block is flagged as superfluous, and seems superfluous but
+ // is the only way I could make this work. If my understanding is correct this is a known bug
+ : ( ( parameterDeclaration )=> parameterDeclaration
+ ( options {warnWhenFollowAmbig=false;} : ( COMMA parameterDeclaration ) => COMMA parameterDeclaration )*
+ ( COMMA variableLengthParameterDeclaration )?
+ |
+ variableLengthParameterDeclaration
+ )?
+ {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
+ #parameterDeclarationList);}
+ ;
+
+// A formal parameter.
+parameterDeclaration!
+ : pm:parameterModifier t:typeSpec[false] id:IDENT
+ pd:declaratorBrackets[#t]
+ {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
+ pm, #([TYPE,"TYPE"],pd), id);}
+ ;
+
+variableLengthParameterDeclaration!
+ : pm:parameterModifier t:typeSpec[false] TRIPLE_DOT id:IDENT
+ pd:declaratorBrackets[#t]
+ {#variableLengthParameterDeclaration = #(#[VARIABLE_PARAMETER_DEF,"VARIABLE_PARAMETER_DEF"],
+ pm, #([TYPE,"TYPE"],pd), id);}
+ ;
+
+parameterModifier
+ //final can appear amongst annotations in any order - greedily consume any preceding
+ //annotations to shut nond-eterminism warnings off
+ : (options{greedy=true;} : annotation)* (f:"final")? (annotation)*
+ {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], #parameterModifier);}
+ ;
+
+// Compound statement. This is used in many contexts:
+// Inside a class definition prefixed with "static":
+// it is a class initializer
+// Inside a class definition without "static":
+// it is an instance initializer
+// As the body of a method
+// As a completely indepdent braced block of code inside a method
+// it starts a new scope for variable definitions
+
+compoundStatement
+ : lc:LCURLY^ {#lc.setType(SLIST);}
+ // include the (possibly-empty) list of statements
+ (statement)*
+ RCURLY
+ ;
+
+
+statement
+ // A list of statements in curly braces -- start a new scope!
+ : compoundStatement
+
+ // declarations are ambiguous with "ID DOT" relative to expression
+ // statements. Must backtrack to be sure. Could use a semantic
+ // predicate to test symbol table to see what the type was coming
+ // up, but that's pretty hard without a symbol table ;)
+ // (declaration)=> declaration SEMI
+ | (declaration)=> decl:declaration semi1:SEMI!
+ {
+ // add semicolon to the AST
+ #decl.addChild(#semi1);
+
+ AST next = currentAST.root.getNextSibling();
+
+ // HACK for multiple variable declaration in one statement
+ // e.g float x, y, z;
+ // the semicolon will only be added to the first statement so
+ // we have to add it manually to all others
+ if (next != null)
+ {
+ AST semi = JavaNodeHelper.getFirstChild(currentAST.root, JavaTokenTypes.SEMI);
+
+ for (AST var = next; var != null; var = var.getNextSibling())
+ {
+ var.addChild(astFactory.create(semi));
+ }
+ }
+ }
+
+ // An expression statement. This could be a method call,
+ // assignment statement, or any other expression evaluated for
+ // side-effects.
+ | e:expression semi2:SEMI!
+ {#e.addChild(#semi2);
+ }
+
+ //TODO: what abour interfaces, enums and annotations
+ // class definition
+ | m:modifiers! classDefinition[#m]
+
+ // Attach a label to the front of a statement
+ | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
+
+ // If-else statement
+ | "if"^ LPAREN expression RPAREN statement
+ (
+ // CONFLICT: the old "dangling-else" problem...
+ // ANTLR generates proper code matching
+ // as soon as possible. Hush warning.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ "else" statement
+ )?
+
+ // For statement
+ | forStatement
+
+ // While statement
+ | "while"^ LPAREN expression RPAREN statement
+
+ // do-while statement
+ | "do"^ statement "while" LPAREN expression RPAREN SEMI
+
+ // get out of a loop (or switch)
+ | "break"^ (IDENT)? SEMI
+
+ // do next iteration of a loop
+ | "continue"^ (IDENT)? SEMI
+
+ // Return an expression
+ | "return"^ (expression)? SEMI
+
+ // switch/case statement
+ | "switch"^ LPAREN expression RPAREN LCURLY
+ ( casesGroup )*
+ RCURLY
+
+ // exception try-catch block
+ | tryBlock
+
+ // throw an exception
+ | "throw"^ expression SEMI
+
+ // synchronize a statement
+ | synBlock:"synchronized"^ LPAREN expression RPAREN compoundStatement
+ { #synBlock.setType(SYNBLOCK);}
+
+ // asserts (uncomment if you want 1.4 compatibility)
+ | "assert"^ expression ( COLON! expression )? SEMI
+
+ // empty statement possibly ?????
+ | s:SEMI {#s.setType(EMPTY_STAT);}
+ ;
+
+forStatement
+ : f:"for"^
+ LPAREN
+ ( (forInit SEMI)=>traditionalForClause
+ | forEachClause
+ )
+ RPAREN
+ statement // statement to loop over
+ ;
+
+traditionalForClause
+ :
+ forInit SEMI // initializer
+ forCond SEMI // condition test
+ forIter // updater
+ ;
+
+forEachClause
+ :
+ p:parameterDeclaration COLON! expression
+ {#forEachClause = #(#[FOR_EACH_CLAUSE,"FOR_EACH_CLAUSE"], #forEachClause);}
+ ;
+
+casesGroup
+ : ( // CONFLICT: to which case group do the statements bind?
+ // ANTLR generates proper code: it groups the
+ // many "case"/"default" labels together then
+ // follows them with the statements
+ options {
+ greedy = true;
+ }
+ :
+ aCase
+ )+
+ caseSList
+ {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
+ ;
+
+aCase
+ : ("case"^ expression | "default") COLON
+ ;
+
+caseSList
+ : (statement)*
+ {#caseSList = #(#[CASESLIST,"CASESLIST"],#caseSList);}
+ ;
+
+// The initializer for a for loop
+forInit
+ // if it looks like a declaration, it is
+ : ((declaration)=> declaration
+ // otherwise it could be an expression list...
+ | expressionList
+ )?
+ {#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
+ ;
+
+forCond
+ : (expression)?
+ {#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
+ ;
+
+forIter
+ : (expressionList)?
+ {#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
+ ;
+
+// an exception handler try/catch block
+tryBlock
+ : "try"^ compoundStatement
+ (handler)*
+ ( finallyClause )?
+ ;
+
+finallyClause
+ : "finally"^ compoundStatement
+ ;
+
+// an exception handler
+handler
+ : "catch"^ LPAREN parameterDeclaration RPAREN compoundStatement
+ ;
+
+
+// expressions
+// Note that most of these expressions follow the pattern
+// thisLevelExpression :
+// nextHigherPrecedenceExpression
+// (OPERATOR nextHigherPrecedenceExpression)*
+// which is a standard recursive definition for a parsing an expression.
+// The operators in java have the following precedences:
+// lowest (13) = *= /= %= += -= <<= >>= >>>= &= ^= |=
+// (12) ?:
+// (11) ||
+// (10) &&
+// ( 9) |
+// ( 8) ^
+// ( 7) &
+// ( 6) == !=
+// ( 5) < <= > >=
+// ( 4) << >>
+// ( 3) +(binary) -(binary)
+// ( 2) * / %
+// ( 1) ++ -- +(unary) -(unary) ~ ! (type)
+// [] () (method call) . (dot -- identifier qualification)
+// new () (explicit parenthesis)
+//
+// the last two are not usually on a precedence chart; I put them in
+// to point out that new has a higher precedence than '.', so you
+// can validy use
+// new Frame().show()
+//
+// Note that the above precedence levels map to the rules below...
+// Once you have a precedence chart, writing the appropriate rules as below
+// is usually very straightfoward
+
+
+
+// the mother of all expressions
+expression
+ : assignmentExpression
+ {#expression = #(#[EXPR,"EXPR"],#expression);}
+ ;
+
+
+// This is a list of expressions.
+expressionList
+ : expression (COMMA expression)*
+ {#expressionList = #(#[ELIST,"ELIST"], expressionList);}
+ ;
+
+
+// assignment expression (level 13)
+assignmentExpression
+ : conditionalExpression
+ ( ( ASSIGN^
+ | PLUS_ASSIGN^
+ | MINUS_ASSIGN^
+ | STAR_ASSIGN^
+ | DIV_ASSIGN^
+ | MOD_ASSIGN^
+ | SR_ASSIGN^
+ | BSR_ASSIGN^
+ | SL_ASSIGN^
+ | BAND_ASSIGN^
+ | BXOR_ASSIGN^
+ | BOR_ASSIGN^
+ )
+ assignmentExpression
+ )?
+ ;
+
+
+// conditional test (level 12)
+conditionalExpression
+ : logicalOrExpression
+ ( QUESTION^ assignmentExpression COLON conditionalExpression )?
+ ;
+
+
+// logical or (||) (level 11)
+logicalOrExpression
+ : logicalAndExpression (LOR^ logicalAndExpression)*
+ ;
+
+
+// logical and (&&) (level 10)
+logicalAndExpression
+ : inclusiveOrExpression (LAND^ inclusiveOrExpression)*
+ ;
+
+
+// bitwise or non-short-circuiting or (|) (level 9)
+inclusiveOrExpression
+ : exclusiveOrExpression (BOR^ exclusiveOrExpression)*
+ ;
+
+
+// exclusive or (^) (level 8)
+exclusiveOrExpression
+ : andExpression (BXOR^ andExpression)*
+ ;
+
+
+// bitwise or non-short-circuiting and (&) (level 7)
+andExpression
+ : equalityExpression (BAND^ equalityExpression)*
+ ;
+
+
+// equality/inequality (==/!=) (level 6)
+equalityExpression
+ : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
+ ;
+
+
+// boolean relational expressions (level 5)
+relationalExpression
+ : shiftExpression
+ ( ( ( LT^
+ | GT^
+ | LE^
+ | GE^
+ )
+ shiftExpression
+ )*
+ | "instanceof"^ typeSpec[true]
+ )
+ ;
+
+
+// bit shift expressions (level 4)
+shiftExpression
+ : additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
+ ;
+
+
+// binary addition/subtraction (level 3)
+additiveExpression
+ : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
+ ;
+
+
+// multiplication/division/modulo (level 2)
+multiplicativeExpression
+ : unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
+ ;
+
+unaryExpression
+ : INC^ unaryExpression
+ | DEC^ unaryExpression
+ | MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
+ | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
+ | unaryExpressionNotPlusMinus
+ ;
+
+unaryExpressionNotPlusMinus
+ : BNOT^ unaryExpression
+ | LNOT^ unaryExpression
+ | ( // subrule allows option to shut off warnings
+ options {
+ // "(int" ambig with postfixExpr due to lack of sequence
+ // info in linear approximate LL(k). It's ok. Shut up.
+ generateAmbigWarnings=false;
+ }
+ : // If typecast is built in type, must be numeric operand
+ // Have to backtrack to see if operator follows
+ (LPAREN builtInTypeSpec[true] RPAREN unaryExpression)=>
+ lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN!
+ unaryExpression
+
+ // Have to backtrack to see if operator follows. If no operator
+ // follows, it's a typecast. No semantic checking needed to parse.
+ // if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)"
+ | (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
+ lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN!
+ unaryExpressionNotPlusMinus
+
+ | postfixExpression
+ )
+ ;
+
+// qualified names, array expressions, method invocation, post inc/dec
+postfixExpression
+ :
+ primaryExpression
+
+ (
+ /*
+ options {
+ // the use of postfixExpression in SUPER_CTOR_CALL adds DOT
+ // to the lookahead set, and gives loads of false non-det
+ // warnings.
+ // shut them off.
+ generateAmbigWarnings=false;
+ }
+ : */
+ //type arguments are only appropriate for a parameterized method/ctor invocations
+ //semantic check may be needed here to ensure that this is the case
+ DOT^ (typeArguments)?
+ ( IDENT
+ ( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
+ argList
+ RPAREN
+ )?
+ | "super"
+ ( // (new Outer()).super() (create enclosing instance)
+ lp3:LPAREN^ argList RPAREN
+ {#lp3.setType(SUPER_CTOR_CALL);}
+ | DOT^ (typeArguments)? IDENT
+ ( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
+ argList
+ RPAREN
+ )?
+ )
+ )
+ | DOT^ "this"
+ | DOT^ newExpression
+ | lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK
+ )*
+
+ ( // possibly add on a post-increment or post-decrement.
+ // allows INC/DEC on too much, but semantics can check
+ in:INC^ {#in.setType(POST_INC);}
+ | de:DEC^ {#de.setType(POST_DEC);}
+ )?
+ ;
+
+// the basic element of an expression
+primaryExpression
+ : identPrimary ( options {greedy=true;} : DOT^ "class" )?
+ | constant
+ | "true"
+ | "false"
+ | "null"
+ | newExpression
+ | "this"
+ | "super"
+ | LPAREN assignmentExpression RPAREN
+ // look for int.class and int[].class
+ | builtInType
+ ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
+ DOT^ "class"
+ ;
+
+/** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class,
+ * and a.b.c.class refs. Also this(...) and super(...). Match
+ * this or super.
+ */
+identPrimary
+ : (ta1:typeArguments!)?
+ IDENT
+ // Syntax for method invocation with type arguments is
+ // foo("blah")
+ (
+ options {
+ // .ident could match here or in postfixExpression.
+ // We do want to match here. Turn off warning.
+ greedy=true;
+ // This turns the ambiguity warning of the second alternative
+ // off. See below. (The "false" predicate makes it non-issue)
+ warnWhenFollowAmbig=false;
+ }
+ // we have a new nondeterminism because of
+ // typeArguments... only a syntactic predicate will help...
+ // The problem is that this loop here conflicts with
+ // DOT typeArguments "super" in postfixExpression (k=2)
+ // A proper solution would require a lot of refactoring...
+// Original way.
+// : (DOT (typeArguments)? IDENT) =>
+// DOT^ (ta2:typeArguments!)? IDENT
+ : (DOT^ (typeArguments)? IDENT)
+ | {false}? // FIXME: this is very ugly but it seems to work...
+ // this will also produce an ANTLR warning!
+ // Unfortunately a syntactic predicate can only select one of
+ // multiple alternatives on the same level, not break out of
+ // an enclosing loop, which is why this ugly hack (a fake
+ // empty alternative with always-false semantic predicate)
+ // is necessary.
+ )*
+ (
+ options {
+ // ARRAY_DECLARATOR here conflicts with INDEX_OP in
+ // postfixExpression on LBRACK RBRACK.
+ // We want to match [] here, so greedy. This overcomes
+ // limitation of linear approximate lookahead.
+ greedy=true;
+ }
+ : ( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
+ // if the input is valid, only the last IDENT may
+ // have preceding typeArguments... rather hacky, this is...
+// Not required because see above
+// {if (#ta2 != null) astFactory.addASTChild(currentAST, #ta2);}
+// {if (#ta2 == null) astFactory.addASTChild(currentAST, #ta1);}
+ argList RPAREN
+ )
+ | ( options {greedy=true;} :
+ lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK!
+ )+
+ )?
+ ;
+
+/** object instantiation.
+ * Trees are built as illustrated by the following input/tree pairs:
+ *
+ * new T()
+ *
+ * new
+ * |
+ * T -- ELIST
+ * |
+ * arg1 -- arg2 -- .. -- argn
+ *
+ * new int[]
+ *
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR
+ *
+ * new int[] {1,2}
+ *
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR -- ARRAY_INIT
+ * |
+ * EXPR -- EXPR
+ * | |
+ * 1 2
+ *
+ * new int[3]
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR
+ * |
+ * EXPR
+ * |
+ * 3
+ *
+ * new int[1][2]
+ *
+ * new
+ * |
+ * int -- ARRAY_DECLARATOR
+ * |
+ * ARRAY_DECLARATOR -- EXPR
+ * | |
+ * EXPR 1
+ * |
+ * 2
+ *
+ */
+newExpression
+ : "new"^ (typeArguments)? type
+ ( LPAREN argList RPAREN (classBlock)?
+
+ //java 1.1
+ // Note: This will allow bad constructs like
+ // new int[4][][3] {exp,exp}.
+ // There needs to be a semantic check here...
+ // to make sure:
+ // a) [ expr ] and [ ] are not mixed
+ // b) [ expr ] and an init are not used together
+
+ | newArrayDeclarator (arrayInitializer)?
+ )
+ ;
+
+argList
+ : ( expressionList
+ | /*nothing*/
+ {#argList = #[ELIST,"ELIST"];}
+ )
+ ;
+
+newArrayDeclarator
+ : (
+ // CONFLICT:
+ // newExpression is a primaryExpression which can be
+ // followed by an array index reference. This is ok,
+ // as the generated code will stay in this loop as
+ // long as it sees an LBRACK (proper behavior)
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
+ (expression)?
+ RBRACK!
+ )+
+ ;
+
+constant
+ : NUM_INT
+ | CHAR_LITERAL
+ | STRING_LITERAL
+ | NUM_FLOAT
+ | NUM_LONG
+ | NUM_DOUBLE
+ ;
+
+
+//----------------------------------------------------------------------------
+// The Java scanner
+//----------------------------------------------------------------------------
+class InternalJavaLexer extends Lexer;
+
+options {
+ exportVocab=Java; // call the vocabulary "Java"
+ testLiterals=false; // don't automatically test for literals
+ k=4; // four characters of lookahead
+ charVocabulary='\u0003'..'\uFFFF';
+ // without inlining some bitset tests, couldn't do unicode;
+ // I need to make ANTLR generate smaller bitsets; see
+ // bottom of JavaLexer.java
+ codeGenBitsetTestThreshold=20;
+ // This class is abstract
+ classHeaderPrefix = "public abstract";
+}
+
+{
+ /** flag for enabling the "assert" keyword */
+ private boolean assertEnabled = true;
+ /** flag for enabling the "enum" keyword */
+ private boolean enumEnabled = true;
+
+ /** Enable the "assert" keyword */
+ public void enableAssert(boolean shouldEnable) { assertEnabled = shouldEnable; }
+ /** Query the "assert" keyword state */
+ public boolean isAssertEnabled() { return assertEnabled; }
+ /** Enable the "enum" keyword */
+ public void enableEnum(boolean shouldEnable) { enumEnabled = shouldEnable; }
+ /** Query the "enum" keyword state */
+ public boolean isEnumEnabled() { return enumEnabled; }
+
+ protected abstract Token makeJavaDoc(Token node, String text) throws TokenStreamIOException;
+
+}
+
+// OPERATORS
+QUESTION : '?' ;
+LPAREN : '(' ;
+RPAREN : ')' ;
+LBRACK : '[' ;
+RBRACK : ']' ;
+LCURLY : '{' ;
+RCURLY : '}' ;
+COLON : ':' ;
+COMMA : ',' ;
+//DOT : '.' ;
+ASSIGN : '=' ;
+EQUAL : "==" ;
+LNOT : '!' ;
+BNOT : '~' ;
+NOT_EQUAL : "!=" ;
+DIV : '/' ;
+DIV_ASSIGN : "/=" ;
+PLUS : '+' ;
+PLUS_ASSIGN : "+=" ;
+INC : "++" ;
+MINUS : '-' ;
+MINUS_ASSIGN : "-=" ;
+DEC : "--" ;
+STAR : '*' ;
+STAR_ASSIGN : "*=" ;
+MOD : '%' ;
+MOD_ASSIGN : "%=" ;
+SR : ">>" ;
+SR_ASSIGN : ">>=" ;
+BSR : ">>>" ;
+BSR_ASSIGN : ">>>=" ;
+GE : ">=" ;
+GT : ">" ;
+SL : "<<" ;
+SL_ASSIGN : "<<=" ;
+LE : "<=" ;
+LT : '<' ;
+BXOR : '^' ;
+BXOR_ASSIGN : "^=" ;
+BOR : '|' ;
+BOR_ASSIGN : "|=" ;
+LOR : "||" ;
+BAND : '&' ;
+BAND_ASSIGN : "&=" ;
+LAND : "&&" ;
+SEMI : ';' ;
+
+
+// Whitespace -- ignored
+WS : ( ' '
+ | '\t'
+ | '\f'
+ // handle newlines
+ | ( options {generateAmbigWarnings=false;}
+ : "\r\n" // Evil DOS
+ | '\r' // Macintosh
+ | '\n' // Unix (the right way)
+ )
+ { newline(); }
+ )+
+ { // _ttype = Token.SKIP;
+ }
+ ;
+
+protected SEPARATOR_COMMENT
+: "//~" (~('\n'|'\r') {if (LA(1) == EOF_CHAR) break;} )*
+ ( '\n'! | '\r'!('\n'!)? )?
+ {newline();}
+;
+
+// Single-line comments
+protected SL_COMMENT
+: "//" (~('\n'|'\r') {if (LA(1) == EOF_CHAR) break;} )*
+ ( '\n'! | '\r'!('\n'!)? )?
+ {newline();
+
+ }
+;
+COMMENT
+:
+ (
+ options {
+ // ANTLR does it right by consuming input as soon as possible
+ generateAmbigWarnings=false;
+ // TODO spec:SPECIAL_COMMENT {$setToken(spec);} |
+ }:
+
+ sep:SEPARATOR_COMMENT {$setToken(sep); } |
+ sl:SL_COMMENT {$setToken(sl); }
+ )
+;
+
+// 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')
+ )*
+ "*/"
+ {
+ // $setType(Token.SKIP);
+ Token n = makeJavaDoc(makeToken(_ttype), $getText);
+ $setToken(n);
+ $setType(n.getType());
+ }
+ ;
+
+
+// character literals
+CHAR_LITERAL
+ : '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\''
+ ;
+
+// string literals
+STRING_LITERAL
+ : '"' (ESC|~('"'|'\\'|'\n'|'\r'))* '"'
+ ;
+
+
+// escape sequence -- note that this is protected; it can only be called
+// from another lexer rule -- it will not ever directly return a token to
+// the parser
+// There are various ambiguities hushed in this rule. The optional
+// '0'...'9' digit matches should be matched here rather than letting
+// them go back to STRING_LITERAL to be matched. ANTLR does the
+// right thing by matching immediately; hence, it's ok to shut off
+// the FOLLOW ambig warnings.
+protected
+ESC
+ : '\\'
+ ( 'n'
+ | 'r'
+ | 't'
+ | 'b'
+ | 'f'
+ | '"'
+ | '\''
+ | '\\'
+ | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+ | '0'..'3'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )?
+ | '4'..'7'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )
+ ;
+
+
+// hexadecimal digit (again, note it's protected!)
+protected
+HEX_DIGIT
+ : ('0'..'9'|'A'..'F'|'a'..'f')
+ ;
+
+
+// a dummy rule to force vocabulary to be all characters (except special
+// ones that ANTLR uses internally (0 to 2)
+protected
+VOCAB
+ : '\3'..'\377'
+ ;
+
+
+// an identifier. Note that testLiterals is set to true! This means
+// that after we match the rule, we look in the literals table to see
+// if it's a literal or really an identifer
+IDENT
+ options {testLiterals=true;}
+ : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
+ {
+ // check if "assert" keyword is enabled
+ if (assertEnabled && "assert".equals($getText)) {
+ $setType(LITERAL_assert); // set token type for the rule in the parser
+ }
+ // check if "enum" keyword is enabled
+ if (enumEnabled && "enum".equals($getText)) {
+ $setType(LITERAL_enum); // set token type for the rule in the parser
+ }
+ }
+ ;
+
+
+// a numeric literal
+NUM_INT
+ {boolean isDecimal=false; Token t=null;}
+ : '.' {_ttype = DOT;}
+ (
+ (('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
+ {
+ if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
+ _ttype = NUM_FLOAT;
+ }
+ else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ })
+ |
+ // JDK 1.5 token for variable length arguments
+ (".." {_ttype = TRIPLE_DOT;})
+ )?
+
+ | ( '0' {isDecimal = true;} // special case for just '0'
+ ( ('x'|'X')
+ ( // hex
+ // the 'e'|'E' and float suffix stuff look
+ // like hex digits, hence the (...)+ doesn't
+ // know when to stop: ambig. ANTLR resolves
+ // it correctly by matching immediately. It
+ // is therefor ok to hush warning.
+ options {
+ warnWhenFollowAmbig=false;
+ }
+ : HEX_DIGIT
+ )+
+
+ | //float or double with leading zero
+ (('0'..'9')+ ('.'|EXPONENT|FLOAT_SUFFIX)) => ('0'..'9')+
+
+ | ('0'..'7')+ // octal
+ )?
+ | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
+ )
+ ( ('l'|'L') { _ttype = NUM_LONG; }
+
+ // only check to see if it's a float if looks like decimal so far
+ | {isDecimal}?
+ ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
+ | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
+ | f4:FLOAT_SUFFIX {t=f4;}
+ )
+ {
+ if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
+ _ttype = NUM_FLOAT;
+ }
+ else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ }
+ )?
+ ;
+
+// JDK 1.5 token for annotations and their declarations
+AT
+ : '@'
+ ;
+
+// a couple protected methods to assist in matching floating point numbers
+protected
+EXPONENT
+ : ('e'|'E') ('+'|'-')? ('0'..'9')+
+ ;
+
+
+protected
+FLOAT_SUFFIX
+ : 'f'|'F'|'d'|'D'
+ ;
+
diff --git a/app/src/antlr/java/java.tree.g b/app/src/antlr/java/java.tree.g
new file mode 100644
index 000000000..e995ef49d
--- /dev/null
+++ b/app/src/antlr/java/java.tree.g
@@ -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)? )
+ ;
diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java
new file mode 100644
index 000000000..94f6a3239
--- /dev/null
+++ b/app/src/processing/app/Base.java
@@ -0,0 +1,2091 @@
+/* -*- 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 java.io.*;
+import java.util.*;
+
+import javax.swing.*;
+
+import processing.app.debug.Compiler;
+import processing.core.*;
+
+
+/**
+ * The base class for the main processing application.
+ * Primary role of this class is for platform identification and
+ * general interaction with the system (launching URLs, loading
+ * files and images, etc) that comes from that.
+ */
+public class Base {
+ static final int REVISION = 17;
+ static String VERSION_NAME = "0017";
+
+ static HashMap platformNames = new HashMap();
+ static {
+ platformNames.put(PConstants.WINDOWS, "windows");
+ platformNames.put(PConstants.MACOSX, "macosx");
+ platformNames.put(PConstants.LINUX, "linux");
+ }
+
+ static HashMap platformIndices = new HashMap();
+ static {
+ platformIndices.put("windows", PConstants.WINDOWS);
+ platformIndices.put("macosx", PConstants.MACOSX);
+ platformIndices.put("linux", PConstants.LINUX);
+ }
+ static Platform platform;
+
+ static private boolean commandLine;
+
+ // A single instance of the preferences window
+ Preferences preferencesFrame;
+
+ // set to true after the first time the menu is built.
+ // so that the errors while building don't show up again.
+ boolean builtOnce;
+
+ static File buildFolder;
+
+ // these are static because they're used by Sketch
+ static private File examplesFolder;
+ static private File librariesFolder;
+ static private File toolsFolder;
+ static private File hardwareFolder;
+
+ static HashSet libraries;
+
+ // maps imported packages to their library folder
+ static HashMap importToLibraryTable;
+
+ // classpath for all known libraries for p5
+ // (both those in the p5/libs folder and those with lib subfolders
+ // found in the sketchbook)
+ static public String librariesClassPath;
+
+ // Location for untitled items
+ static File untitledFolder;
+
+ // p5 icon for the window
+ static Image icon;
+
+// int editorCount;
+// Editor[] editors;
+ java.util.List editors =
+ Collections.synchronizedList(new ArrayList());
+// ArrayList editors = Collections.synchronizedList(new ArrayList());
+ Editor activeEditor;
+
+// int nextEditorX;
+// int nextEditorY;
+
+
+ static public void main(String args[]) {
+ try {
+ File versionFile = getContentFile("lib/version.txt");
+ if (versionFile.exists()) {
+ VERSION_NAME = PApplet.loadStrings(versionFile)[0];
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+// if (System.getProperty("mrj.version") != null) {
+// //String jv = System.getProperty("java.version");
+// String ov = System.getProperty("os.version");
+// if (ov.startsWith("10.5")) {
+// System.setProperty("apple.laf.useScreenMenuBar", "true");
+// }
+// }
+
+ /*
+ commandLine = false;
+ if (args.length >= 2) {
+ if (args[0].startsWith("--")) {
+ commandLine = true;
+ }
+ }
+
+ if (PApplet.javaVersion < 1.5f) {
+ //System.err.println("no way man");
+ Base.showError("Need to install Java 1.5",
+ "This version of Processing requires \n" +
+ "Java 1.5 or later to run properly.\n" +
+ "Please visit java.com to upgrade.", null);
+ }
+ */
+
+ initPlatform();
+
+// // Set the look and feel before opening the window
+// try {
+// platform.setLookAndFeel();
+// } catch (Exception e) {
+// System.err.println("Non-fatal error while setting the Look & Feel.");
+// System.err.println("The error message follows, however Processing should run fine.");
+// System.err.println(e.getMessage());
+// //e.printStackTrace();
+// }
+
+ // Use native popups so they don't look so crappy on osx
+ JPopupMenu.setDefaultLightWeightPopupEnabled(false);
+
+ // Don't put anything above this line that might make GUI,
+ // because the platform has to be inited properly first.
+
+ // Make sure a full JDK is installed
+ //initRequirements();
+
+ // run static initialization that grabs all the prefs
+ Preferences.init(null);
+
+ // setup the theme coloring fun
+ Theme.init();
+
+ if (Base.isMacOS()) {
+ String properMenuBar = "apple.laf.useScreenMenuBar";
+ String menubar = Preferences.get(properMenuBar);
+ if (menubar != null) {
+ // Get the current menu bar setting and use it
+ System.setProperty(properMenuBar, menubar);
+
+ } else {
+ // 10.4 is not affected, 10.5 (and prolly 10.6) are
+ if (System.getProperty("os.version").startsWith("10.4")) {
+ // Don't bother checking next time
+ Preferences.set(properMenuBar, "true");
+ // Also set the menubar now
+ System.setProperty(properMenuBar, "true");
+
+ } else {
+ // Running 10.5 or 10.6 or whatever, give 'em the business
+ String warning =
+ "" +
+ " " +
+ "The standard menu bar has been disabled." +
+ "
Due to an Apple bug, the Arduino menu bar " +
+ "is unusable on Mac OS X 10.5. " +
+ "As a workaround, the menu bar will be placed inside " +
+ "the editor window. This setting can be changed in the " +
+ "Preferences window. If this bug makes you sad, " +
+ "please contact Apple via bugreporter.apple.com.
" +
+ " ";
+ Object[] options = { "OK", "More Info" };
+ int result = JOptionPane.showOptionDialog(new Frame(),
+ warning,
+ "Menu Bar Problem",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE,
+ null,
+ options,
+ options[0]);
+ if (result == -1) {
+ // They hit ESC or closed the window, so just hide it for now
+ // But don't bother setting the preference in the file
+ } else {
+ // Shut off in the preferences for next time
+ Preferences.set(properMenuBar, "false");
+ if (result == 1) { // More Info
+ Base.openURL("http://dev.processing.org/bugs/show_bug.cgi?id=786");
+ }
+ }
+ // Whether or not canceled, set to false (right now) if we're on 10.5
+ System.setProperty(properMenuBar, "false");
+ }
+ }
+ }
+
+ // Set the look and feel before opening the window
+ // For 0158, moving it lower so that the apple.laf.useScreenMenuBar stuff works
+ try {
+ platform.setLookAndFeel();
+ } catch (Exception e) {
+ System.err.println("Non-fatal error while setting the Look & Feel.");
+ System.err.println("The error message follows, however Arduino should run fine.");
+ System.err.println(e.getMessage());
+ //e.printStackTrace();
+ }
+
+ // Create a location for untitled sketches
+ untitledFolder = createTempFolder("untitled");
+ untitledFolder.deleteOnExit();
+
+ new Base(args);
+ }
+
+
+ static protected void setCommandLine() {
+ commandLine = true;
+ }
+
+
+ static protected boolean isCommandLine() {
+ return commandLine;
+ }
+
+
+ static protected void initPlatform() {
+ try {
+ Class platformClass = Class.forName("processing.app.Platform");
+ if (Base.isMacOS()) {
+ platformClass = Class.forName("processing.app.macosx.Platform");
+ } else if (Base.isWindows()) {
+ platformClass = Class.forName("processing.app.windows.Platform");
+ } else if (Base.isLinux()) {
+ platformClass = Class.forName("processing.app.linux.Platform");
+ }
+ platform = (Platform) platformClass.newInstance();
+ } catch (Exception e) {
+ Base.showError("Problem Setting the Platform",
+ "An unknown error occurred while trying to load\n" +
+ "platform-specific code for your machine.", e);
+ }
+ }
+
+
+ static protected void initRequirements() {
+ try {
+ Class.forName("com.sun.jdi.VirtualMachine");
+ } catch (ClassNotFoundException cnfe) {
+ Base.showPlatforms();
+ Base.showError("Please install JDK 1.5 or later",
+ "Arduino requires a full JDK (not just a JRE)\n" +
+ "to run. Please install JDK 1.5 or later.\n" +
+ "More information can be found in the reference.", cnfe);
+ }
+ }
+
+
+ public Base(String[] args) {
+ platform.init(this);
+
+ // Get paths for the libraries and examples in the Processing folder
+ //String workingDirectory = System.getProperty("user.dir");
+ examplesFolder = getContentFile("examples");
+ librariesFolder = new File(getContentFile("hardware"), "libraries");
+ toolsFolder = getContentFile("tools");
+
+ // Get the sketchbook path, and make sure it's set properly
+ String sketchbookPath = Preferences.get("sketchbook.path");
+
+ // If a value is at least set, first check to see if the folder exists.
+ // If it doesn't, warn the user that the sketchbook folder is being reset.
+ if (sketchbookPath != null) {
+ File skechbookFolder = new File(sketchbookPath);
+ if (!skechbookFolder.exists()) {
+ Base.showWarning("Sketchbook folder disappeared",
+ "The sketchbook folder no longer exists.\n" +
+ "Arduino will switch to the default sketchbook\n" +
+ "location, and create a new sketchbook folder if\n" +
+ "necessary. Arduino will then stop talking about\n" +
+ "himself in the third person.", null);
+ sketchbookPath = null;
+ }
+ }
+
+ // If not path is set, get the default sketchbook folder for this platform
+ if (sketchbookPath == null) {
+ File defaultFolder = getDefaultSketchbookFolder();
+ Preferences.set("sketchbook.path", defaultFolder.getAbsolutePath());
+ if (!defaultFolder.exists()) {
+ defaultFolder.mkdirs();
+ }
+ }
+
+ // Check if there were previously opened sketches to be restored
+ boolean opened = restoreSketches();
+
+ // Check if any files were passed in on the command line
+ for (int i = 0; i < args.length; i++) {
+ String path = args[i];
+ // Fix a problem with systems that use a non-ASCII languages. Paths are
+ // being passed in with 8.3 syntax, which makes the sketch loader code
+ // unhappy, since the sketch folder naming doesn't match up correctly.
+ // http://dev.processing.org/bugs/show_bug.cgi?id=1089
+ if (isWindows()) {
+ try {
+ File file = new File(args[i]);
+ path = file.getCanonicalPath();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (handleOpen(path) != null) {
+ opened = true;
+ }
+ }
+
+ // Create a new empty window (will be replaced with any files to be opened)
+ if (!opened) {
+ handleNew();
+ }
+
+ // check for updates
+ if (Preferences.getBoolean("update.check")) {
+ new UpdateCheck(this);
+ }
+ }
+
+
+ /**
+ * Post-constructor setup for the editor area. Loads the last
+ * sketch that was used (if any), and restores other Editor settings.
+ * The complement to "storePreferences", this is called when the
+ * application is first launched.
+ */
+ protected boolean restoreSketches() {
+ // figure out window placement
+
+ Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ boolean windowPositionValid = true;
+
+ if (Preferences.get("last.screen.height") != null) {
+ // if screen size has changed, the window coordinates no longer
+ // make sense, so don't use them unless they're identical
+ int screenW = Preferences.getInteger("last.screen.width");
+ int screenH = Preferences.getInteger("last.screen.height");
+
+ if ((screen.width != screenW) || (screen.height != screenH)) {
+ windowPositionValid = false;
+ }
+ /*
+ int windowX = Preferences.getInteger("last.window.x");
+ int windowY = Preferences.getInteger("last.window.y");
+ if ((windowX < 0) || (windowY < 0) ||
+ (windowX > screenW) || (windowY > screenH)) {
+ windowPositionValid = false;
+ }
+ */
+ } else {
+ windowPositionValid = false;
+ }
+
+ // Iterate through all sketches that were open last time p5 was running.
+ // If !windowPositionValid, then ignore the coordinates found for each.
+
+ // Save the sketch path and window placement for each open sketch
+ int count = Preferences.getInteger("last.sketch.count");
+ int opened = 0;
+ for (int i = 0; i < count; i++) {
+ String path = Preferences.get("last.sketch" + i + ".path");
+ int[] location;
+ if (windowPositionValid) {
+ String locationStr = Preferences.get("last.sketch" + i + ".location");
+ location = PApplet.parseInt(PApplet.split(locationStr, ','));
+ } else {
+ location = nextEditorLocation();
+ }
+ // If file did not exist, null will be returned for the Editor
+ if (handleOpen(path, location) != null) {
+ opened++;
+ }
+ }
+ return (opened > 0);
+ }
+
+
+ /**
+ * Store list of sketches that are currently open.
+ * Called when the application is quitting and documents are still open.
+ */
+ protected void storeSketches() {
+ // Save the width and height of the screen
+ Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ Preferences.setInteger("last.screen.width", screen.width);
+ Preferences.setInteger("last.screen.height", screen.height);
+
+ String untitledPath = untitledFolder.getAbsolutePath();
+
+ // Save the sketch path and window placement for each open sketch
+ int index = 0;
+ for (Editor editor : editors) {
+ String path = editor.getSketch().getMainFilePath();
+ // In case of a crash, save untitled sketches if they contain changes.
+ // (Added this for release 0158, may not be a good idea.)
+ if (path.startsWith(untitledPath) &&
+ !editor.getSketch().isModified()) {
+ continue;
+ }
+ Preferences.set("last.sketch" + index + ".path", path);
+
+ int[] location = editor.getPlacement();
+ String locationStr = PApplet.join(PApplet.str(location), ",");
+ Preferences.set("last.sketch" + index + ".location", locationStr);
+ index++;
+ }
+ Preferences.setInteger("last.sketch.count", index);
+ }
+
+
+ // If a sketch is untitled on quit, may need to store the new name
+ // rather than the location from the temp folder.
+ protected void storeSketchPath(Editor editor, int index) {
+ String path = editor.getSketch().getMainFilePath();
+ String untitledPath = untitledFolder.getAbsolutePath();
+ if (path.startsWith(untitledPath)) {
+ path = "";
+ }
+ Preferences.set("last.sketch" + index + ".path", path);
+ }
+
+
+ /*
+ public void storeSketch(Editor editor) {
+ int index = -1;
+ for (int i = 0; i < editorCount; i++) {
+ if (editors[i] == editor) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ System.err.println("Problem storing sketch " + editor.sketch.name);
+ } else {
+ String path = editor.sketch.getMainFilePath();
+ Preferences.set("last.sketch" + index + ".path", path);
+ }
+ }
+ */
+
+
+ // .................................................................
+
+
+ // Because of variations in native windowing systems, no guarantees about
+ // changes to the focused and active Windows can be made. Developers must
+ // never assume that this Window is the focused or active Window until this
+ // Window receives a WINDOW_GAINED_FOCUS or WINDOW_ACTIVATED event.
+ protected void handleActivated(Editor whichEditor) {
+ activeEditor = whichEditor;
+
+ // set the current window to be the console that's getting output
+ EditorConsole.setEditor(activeEditor);
+ }
+
+
+ protected int[] nextEditorLocation() {
+ Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ int defaultWidth = Preferences.getInteger("default.window.width");
+ int defaultHeight = Preferences.getInteger("default.window.height");
+
+ if (activeEditor == null) {
+ // If no current active editor, use default placement
+ return new int[] {
+ (screen.width - defaultWidth) / 2,
+ (screen.height - defaultHeight) / 2,
+ defaultWidth, defaultHeight, 0
+ };
+
+ } else {
+ // With a currently active editor, open the new window
+ // using the same dimensions, but offset slightly.
+ synchronized (editors) {
+ final int OVER = 50;
+ // In release 0160, don't
+ //location = activeEditor.getPlacement();
+ Editor lastOpened = editors.get(editors.size() - 1);
+ int[] location = lastOpened.getPlacement();
+ // Just in case the bounds for that window are bad
+ location[0] += OVER;
+ location[1] += OVER;
+
+ if (location[0] == OVER ||
+ location[2] == OVER ||
+ location[0] + location[2] > screen.width ||
+ location[1] + location[3] > screen.height) {
+ // Warp the next window to a randomish location on screen.
+ return new int[] {
+ (int) (Math.random() * (screen.width - defaultWidth)),
+ (int) (Math.random() * (screen.height - defaultHeight)),
+ defaultWidth, defaultHeight, 0
+ };
+ }
+
+ return location;
+ }
+ }
+ }
+
+
+ // .................................................................
+
+
+ boolean breakTime = false;
+ String[] months = {
+ "jan", "feb", "mar", "apr", "may", "jun",
+ "jul", "aug", "sep", "oct", "nov", "dec"
+ };
+
+ /**
+ * Handle creating a sketch folder, return its base .pde file
+ * or null if the operation was canceled.
+ * @param shift whether shift is pressed, which will invert prompt setting
+ * @param noPrompt disable prompt, no matter the setting
+ */
+ protected String createNewUntitled() throws IOException {
+ File newbieDir = null;
+ String newbieName = null;
+
+ // In 0126, untitled sketches will begin in the temp folder,
+ // and then moved to a new location because Save will default to Save As.
+ File sketchbookDir = getSketchbookFolder();
+ File newbieParentDir = untitledFolder;
+
+ // Use a generic name like sketch_031008a, the date plus a char
+ int index = 0;
+ //SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
+ //SimpleDateFormat formatter = new SimpleDateFormat("MMMdd");
+ //String purty = formatter.format(new Date()).toLowerCase();
+ Calendar cal = Calendar.getInstance();
+ int day = cal.get(Calendar.DAY_OF_MONTH); // 1..31
+ int month = cal.get(Calendar.MONTH); // 0..11
+ String purty = months[month] + PApplet.nf(day, 2);
+ do {
+ if (index == 26) {
+ // In 0159, avoid running past z by sending people outdoors.
+ if (!breakTime) {
+ Base.showWarning("Time for a Break",
+ "You've reached the limit for auto naming of new sketches\n" +
+ "for the day. How about going for a walk instead?", null);
+ breakTime = true;
+ } else {
+ Base.showWarning("Sunshine",
+ "No really, time for some fresh air for you.", null);
+ }
+ return null;
+ }
+ newbieName = "sketch_" + purty + ((char) ('a' + index));
+ newbieDir = new File(newbieParentDir, newbieName);
+ index++;
+ // Make sure it's not in the temp folder *and* it's not in the sketchbook
+ } while (newbieDir.exists() || new File(sketchbookDir, newbieName).exists());
+
+ // Make the directory for the new sketch
+ newbieDir.mkdirs();
+
+ // Make an empty pde file
+ File newbieFile = new File(newbieDir, newbieName + ".pde");
+ new FileOutputStream(newbieFile); // create the file
+ return newbieFile.getAbsolutePath();
+ }
+
+
+ /**
+ * Create a new untitled document in a new sketch window.
+ */
+ public void handleNew() {
+ try {
+ String path = createNewUntitled();
+ if (path != null) {
+ Editor editor = handleOpen(path);
+ editor.untitled = true;
+ }
+
+ } catch (IOException e) {
+ if (activeEditor != null) {
+ activeEditor.statusError(e);
+ }
+ }
+ }
+
+
+ /**
+ * Replace the sketch in the current window with a new untitled document.
+ */
+ public void handleNewReplace() {
+ if (!activeEditor.checkModified(false)) {
+ return; // sketch was modified, and user canceled
+ }
+ // Close the running window, avoid window boogers with multiple sketches
+ activeEditor.internalCloseRunner();
+
+ // Actually replace things
+ handleNewReplaceImpl();
+ }
+
+
+ protected void handleNewReplaceImpl() {
+ try {
+ String path = createNewUntitled();
+ if (path != null) {
+ activeEditor.handleOpenInternal(path);
+ activeEditor.untitled = true;
+ }
+// return true;
+
+ } catch (IOException e) {
+ activeEditor.statusError(e);
+// return false;
+ }
+ }
+
+
+ /**
+ * Open a sketch, replacing the sketch in the current window.
+ * @param path Location of the primary pde file for the sketch.
+ */
+ public void handleOpenReplace(String path) {
+ if (!activeEditor.checkModified(false)) {
+ return; // sketch was modified, and user canceled
+ }
+ // Close the running window, avoid window boogers with multiple sketches
+ activeEditor.internalCloseRunner();
+
+ boolean loaded = activeEditor.handleOpenInternal(path);
+ if (!loaded) {
+ // replace the document without checking if that's ok
+ handleNewReplaceImpl();
+ }
+ }
+
+
+ /**
+ * Prompt for a sketch to open, and open it in a new window.
+ */
+ public void handleOpenPrompt() {
+ // get the frontmost window frame for placing file dialog
+ FileDialog fd = new FileDialog(activeEditor,
+ "Open an Arduino sketch...",
+ FileDialog.LOAD);
+ // This was annoying people, so disabled it in 0125.
+ //fd.setDirectory(Preferences.get("sketchbook.path"));
+ //fd.setDirectory(getSketchbookPath());
+
+ // Only show .pde files as eligible bachelors
+ fd.setFilenameFilter(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ // TODO this doesn't seem to ever be used. AWESOME.
+ //System.out.println("check filter on " + dir + " " + name);
+ return name.toLowerCase().endsWith(".pde");
+ }
+ });
+
+ fd.setVisible(true);
+
+ String directory = fd.getDirectory();
+ String filename = fd.getFile();
+
+ // User canceled selection
+ if (filename == null) return;
+
+ File inputFile = new File(directory, filename);
+ handleOpen(inputFile.getAbsolutePath());
+ }
+
+
+ /**
+ * Open a sketch in a new window.
+ * @param path Path to the pde file for the sketch in question
+ * @return the Editor object, so that properties (like 'untitled')
+ * can be set by the caller
+ */
+ public Editor handleOpen(String path) {
+ return handleOpen(path, nextEditorLocation());
+ }
+
+
+ protected Editor handleOpen(String path, int[] location) {
+ File file = new File(path);
+ if (!file.exists()) return null;
+
+ // Cycle through open windows to make sure that it's not already open.
+ for (Editor editor : editors) {
+ if (editor.getSketch().getMainFilePath().equals(path)) {
+ editor.toFront();
+ return editor;
+ }
+ }
+
+ // If the active editor window is an untitled, and un-modified document,
+ // just replace it with the file that's being opened.
+// if (activeEditor != null) {
+// Sketch activeSketch = activeEditor.sketch;
+// if (activeSketch.isUntitled() && !activeSketch.isModified()) {
+// // if it's an untitled, unmodified document, it can be replaced.
+// // except in cases where a second blank window is being opened.
+// if (!path.startsWith(untitledFolder.getAbsolutePath())) {
+// activeEditor.handleOpenUnchecked(path, 0, 0, 0, 0);
+// return activeEditor;
+// }
+// }
+// }
+
+ Editor editor = new Editor(this, path, location);
+
+ // Make sure that the sketch actually loaded
+ if (editor.getSketch() == null) {
+ return null; // Just walk away quietly
+ }
+
+// if (editors == null) {
+// editors = new Editor[5];
+// }
+// if (editorCount == editors.length) {
+// editors = (Editor[]) PApplet.expand(editors);
+// }
+// editors[editorCount++] = editor;
+ editors.add(editor);
+
+// if (markedForClose != null) {
+// Point p = markedForClose.getLocation();
+// handleClose(markedForClose, false);
+// // open the new window in
+// editor.setLocation(p);
+// }
+
+ // now that we're ready, show the window
+ // (don't do earlier, cuz we might move it based on a window being closed)
+ editor.setVisible(true);
+
+ return editor;
+ }
+
+
+ /**
+ * Close a sketch as specified by its editor window.
+ * @param editor Editor object of the sketch to be closed.
+ * @return true if succeeded in closing, false if canceled.
+ */
+ public boolean handleClose(Editor editor) {
+ // Check if modified
+ if (!editor.checkModified(false)) {
+ return false;
+ }
+
+ // Close the running window, avoid window boogers with multiple sketches
+ editor.internalCloseRunner();
+
+ if (editors.size() == 1) {
+ // For 0158, when closing the last window /and/ it was already an
+ // untitled sketch, just give up and let the user quit.
+// if (Preferences.getBoolean("sketchbook.closing_last_window_quits") ||
+// (editor.untitled && !editor.getSketch().isModified())) {
+ if (Base.isMacOS()) {
+ Object[] options = { "OK", "Cancel" };
+ String prompt =
+ " " +
+ " " +
+ "Are you sure you want to Quit?" +
+ "
Closing the last open sketch will quit Arduino.";
+
+ int result = JOptionPane.showOptionDialog(editor,
+ prompt,
+ "Quit",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+ if (result == JOptionPane.NO_OPTION ||
+ result == JOptionPane.CLOSED_OPTION) {
+ return false;
+ }
+ }
+
+ // This will store the sketch count as zero
+ editors.remove(editor);
+ storeSketches();
+
+ // Save out the current prefs state
+ Preferences.save();
+
+ // Since this wasn't an actual Quit event, call System.exit()
+ System.exit(0);
+
+ } else {
+ // More than one editor window open,
+ // proceed with closing the current window.
+ editor.setVisible(false);
+ editor.dispose();
+// for (int i = 0; i < editorCount; i++) {
+// if (editor == editors[i]) {
+// for (int j = i; j < editorCount-1; j++) {
+// editors[j] = editors[j+1];
+// }
+// editorCount--;
+// // Set to null so that garbage collection occurs
+// editors[editorCount] = null;
+// }
+// }
+ editors.remove(editor);
+ }
+ return true;
+ }
+
+
+ /**
+ * Handler for File → Quit.
+ * @return false if canceled, true otherwise.
+ */
+ public boolean handleQuit() {
+ // If quit is canceled, this will be replaced anyway
+ // by a later handleQuit() that is not canceled.
+ storeSketches();
+
+ if (handleQuitEach()) {
+ // make sure running sketches close before quitting
+ for (Editor editor : editors) {
+ editor.internalCloseRunner();
+ }
+ // Save out the current prefs state
+ Preferences.save();
+
+ if (!Base.isMacOS()) {
+ // If this was fired from the menu or an AppleEvent (the Finder),
+ // then Mac OS X will send the terminate signal itself.
+ System.exit(0);
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Attempt to close each open sketch in preparation for quitting.
+ * @return false if canceled along the way
+ */
+ protected boolean handleQuitEach() {
+ int index = 0;
+ for (Editor editor : editors) {
+ if (editor.checkModified(true)) {
+ // Update to the new/final sketch path for this fella
+ storeSketchPath(editor, index);
+ index++;
+
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * Asynchronous version of menu rebuild to be used on save and rename
+ * to prevent the interface from locking up until the menus are done.
+ */
+ protected void rebuildSketchbookMenus() {
+ //System.out.println("async enter");
+ //new Exception().printStackTrace();
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ //System.out.println("starting rebuild");
+ rebuildSketchbookMenu(Editor.sketchbookMenu);
+ rebuildToolbarMenu(Editor.toolbarMenu);
+ //System.out.println("done with rebuild");
+ }
+ });
+ //System.out.println("async exit");
+ }
+
+
+ protected void rebuildToolbarMenu(JMenu menu) {
+ JMenuItem item;
+ menu.removeAll();
+
+ //System.out.println("rebuilding toolbar menu");
+ // Add the single "Open" item
+ item = Editor.newJMenuItem("Open...", 'O');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleOpenPrompt();
+ }
+ });
+ menu.add(item);
+ menu.addSeparator();
+
+ // Add a list of all sketches and subfolders
+ try {
+ boolean sketches = addSketches(menu, getSketchbookFolder(), true);
+ if (sketches) menu.addSeparator();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ //System.out.println("rebuilding examples menu");
+ // Add each of the subfolders of examples directly to the menu
+ try {
+ boolean found = addSketches(menu, examplesFolder, true);
+ if (found) menu.addSeparator();
+ found = addSketches(menu, getSketchbookLibrariesFolder(), true);
+ if (found) menu.addSeparator();
+ addSketches(menu, librariesFolder, true);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ protected void rebuildSketchbookMenu(JMenu menu) {
+ //System.out.println("rebuilding sketchbook menu");
+ //new Exception().printStackTrace();
+ try {
+ menu.removeAll();
+ addSketches(menu, getSketchbookFolder(), false);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void rebuildImportMenu(JMenu importMenu) {
+ //System.out.println("rebuilding import menu");
+ importMenu.removeAll();
+
+ // reset the set of libraries
+ libraries = new HashSet();
+
+ // reset the table mapping imports to libraries
+ importToLibraryTable = new HashMap();
+
+ // Add libraries found in the sketchbook folder
+ try {
+ File sketchbookLibraries = getSketchbookLibrariesFolder();
+ boolean found = addLibraries(importMenu, sketchbookLibraries);
+ if (found) importMenu.addSeparator();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // Add from the "libraries" subfolder in the Processing directory
+ try {
+ addLibraries(importMenu, librariesFolder);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void rebuildExamplesMenu(JMenu menu) {
+ //System.out.println("rebuilding examples menu");
+
+ try {
+ menu.removeAll();
+ boolean found = addSketches(menu, examplesFolder, false);
+ if (found) menu.addSeparator();
+ found = addSketches(menu, getSketchbookLibrariesFolder(), false);
+ if (found) menu.addSeparator();
+ addSketches(menu, librariesFolder, false);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Scan a folder recursively, and add any sketches found to the menu
+ * specified. Set the openReplaces parameter to true when opening the sketch
+ * should replace the sketch in the current window, or false when the
+ * sketch should open in a new window.
+ */
+ protected boolean addSketches(JMenu menu, File folder,
+ final boolean openReplaces) throws IOException {
+ // skip .DS_Store files, etc (this shouldn't actually be necessary)
+ if (!folder.isDirectory()) return false;
+
+ String[] list = folder.list();
+ // If a bad folder or unreadable or whatever, this will come back null
+ if (list == null) return false;
+
+ // Alphabetize list, since it's not always alpha order
+ Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
+ //processing.core.PApplet.println("adding sketches " + folder.getAbsolutePath());
+ //PApplet.println(list);
+
+ ActionListener listener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String path = e.getActionCommand();
+ if (new File(path).exists()) {
+ if (openReplaces) {
+ handleOpenReplace(path);
+ } else {
+ handleOpen(path);
+ }
+ } else {
+ showWarning("Sketch Does Not Exist",
+ "The selected sketch no longer exists.\n" +
+ "You may need to restart Arduino to update\n" +
+ "the sketchbook menu.", null);
+ }
+ }
+ };
+ // offers no speed improvement
+ //menu.addActionListener(listener);
+
+ boolean ifound = false;
+
+ for (int i = 0; i < list.length; i++) {
+ if ((list[i].charAt(0) == '.') ||
+ list[i].equals("CVS")) continue;
+
+ File subfolder = new File(folder, list[i]);
+ if (!subfolder.isDirectory()) continue;
+
+ File entry = new File(subfolder, list[i] + ".pde");
+ // if a .pde file of the same prefix as the folder exists..
+ if (entry.exists()) {
+ //String sanityCheck = sanitizedName(list[i]);
+ //if (!sanityCheck.equals(list[i])) {
+ if (!Sketch.isSanitaryName(list[i])) {
+ if (!builtOnce) {
+ String complaining =
+ "The sketch \"" + list[i] + "\" cannot be used.\n" +
+ "Sketch names must contain only basic letters and numbers\n" +
+ "(ASCII-only with no spaces, " +
+ "and it cannot start with a number).\n" +
+ "To get rid of this message, remove the sketch from\n" +
+ entry.getAbsolutePath();
+ Base.showMessage("Ignoring sketch with bad name", complaining);
+ }
+ continue;
+ }
+
+ JMenuItem item = new JMenuItem(list[i]);
+ item.addActionListener(listener);
+ item.setActionCommand(entry.getAbsolutePath());
+ menu.add(item);
+ ifound = true;
+
+ } else {
+ // don't create an extra menu level for a folder named "examples"
+ if (subfolder.getName().equals("examples")) {
+ boolean found = addSketches(menu, subfolder, openReplaces); //, false);
+ if (found) ifound = true;
+ } else {
+ // not a sketch folder, but maybe a subfolder containing sketches
+ JMenu submenu = new JMenu(list[i]);
+ // needs to be separate var
+ // otherwise would set ifound to false
+ boolean found = addSketches(submenu, subfolder, openReplaces); //, false);
+ if (found) {
+ menu.add(submenu);
+ ifound = true;
+ }
+ }
+ }
+ }
+ return ifound; // actually ignored, but..
+ }
+
+
+ protected boolean addLibraries(JMenu menu, File folder) throws IOException {
+ if (!folder.isDirectory()) return false;
+
+ String list[] = folder.list(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ // skip .DS_Store files, .svn folders, etc
+ if (name.charAt(0) == '.') return false;
+ if (name.equals("CVS")) return false;
+ return (new File(dir, name).isDirectory());
+ }
+ });
+ // if a bad folder or something like that, this might come back null
+ if (list == null) return false;
+
+ // alphabetize list, since it's not always alpha order
+ // replaced hella slow bubble sort with this feller for 0093
+ Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
+
+ ActionListener listener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ activeEditor.getSketch().importLibrary(e.getActionCommand());
+ }
+ };
+
+ boolean ifound = false;
+
+ for (String libraryName : list) {
+ File subfolder = new File(folder, libraryName);
+// File libraryFolder = new File(subfolder, "library");
+// File libraryJar = new File(libraryFolder, libraryName + ".jar");
+// // If a .jar file of the same prefix as the folder exists
+// // inside the 'library' subfolder of the sketch
+// if (libraryJar.exists()) {
+ String sanityCheck = Sketch.sanitizeName(libraryName);
+ if (!sanityCheck.equals(libraryName)) {
+ String mess =
+ "The library \"" + libraryName + "\" cannot be used.\n" +
+ "Library names must contain only basic letters and numbers.\n" +
+ "(ascii only and no spaces, and it cannot start with a number)";
+ Base.showMessage("Ignoring bad library name", mess);
+ continue;
+ }
+
+// // get the path for all .jar files in this code folder
+// String libraryClassPath =
+// Compiler.contentsToClassPath(libraryFolder);
+// // grab all jars and classes from this folder,
+// // and append them to the library classpath
+// librariesClassPath +=
+// File.pathSeparatorChar + libraryClassPath;
+// // need to associate each import with a library folder
+// String packages[] =
+// Compiler.packageListFromClassPath(libraryClassPath);
+ libraries.add(subfolder);
+ String packages[] = Compiler.headerListFromIncludePath(subfolder.getAbsolutePath());
+ for (String pkg : packages) {
+ importToLibraryTable.put(pkg, subfolder);
+ }
+
+ JMenuItem item = new JMenuItem(libraryName);
+ item.addActionListener(listener);
+ item.setActionCommand(subfolder.getAbsolutePath());
+ menu.add(item);
+ ifound = true;
+
+// XXX: DAM: should recurse here so that library folders can be nested
+// } else { // not a library, but is still a folder, so recurse
+// JMenu submenu = new JMenu(libraryName);
+// // needs to be separate var, otherwise would set ifound to false
+// boolean found = addLibraries(submenu, subfolder);
+// if (found) {
+// menu.add(submenu);
+// ifound = true;
+// }
+// }
+ }
+ return ifound;
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * Show the About box.
+ */
+ public void handleAbout() {
+ final Image image = Base.getLibImage("about.jpg", activeEditor);
+ final Window window = new Window(activeEditor) {
+ public void paint(Graphics g) {
+ g.drawImage(image, 0, 0, null);
+
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+
+ g.setFont(new Font("SansSerif", Font.PLAIN, 11));
+ g.setColor(Color.white);
+ g.drawString(Base.VERSION_NAME, 50, 30);
+ }
+ };
+ window.addMouseListener(new MouseAdapter() {
+ public void mousePressed(MouseEvent e) {
+ window.dispose();
+ }
+ });
+ int w = image.getWidth(activeEditor);
+ int h = image.getHeight(activeEditor);
+ Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ window.setBounds((screen.width-w)/2, (screen.height-h)/2, w, h);
+ window.setVisible(true);
+ }
+
+
+ /**
+ * Show the Preferences window.
+ */
+ public void handlePrefs() {
+ if (preferencesFrame == null) preferencesFrame = new Preferences();
+ preferencesFrame.showFrame(activeEditor);
+ }
+
+
+ // ...................................................................
+
+
+ /**
+ * Get list of platform constants.
+ */
+// static public int[] getPlatforms() {
+// return platforms;
+// }
+
+
+// static public int getPlatform() {
+// String osname = System.getProperty("os.name");
+//
+// if (osname.indexOf("Mac") != -1) {
+// return PConstants.MACOSX;
+//
+// } else if (osname.indexOf("Windows") != -1) {
+// return PConstants.WINDOWS;
+//
+// } else if (osname.equals("Linux")) { // true for the ibm vm
+// return PConstants.LINUX;
+//
+// } else {
+// return PConstants.OTHER;
+// }
+// }
+
+
+ static public String getPlatformName() {
+ String osname = System.getProperty("os.name");
+
+ if (osname.indexOf("Mac") != -1) {
+ return "macosx";
+
+ } else if (osname.indexOf("Windows") != -1) {
+ return "windows";
+
+ } else if (osname.equals("Linux")) { // true for the ibm vm
+ return "linux";
+
+ } else {
+ return "other";
+ }
+ }
+
+
+ /**
+ * Map a platform constant to its name.
+ * @param which PConstants.WINDOWS, PConstants.MACOSX, PConstants.LINUX
+ * @return one of "windows", "macosx", or "linux"
+ */
+ static public String getPlatformName(int which) {
+ return platformNames.get(which);
+ }
+
+
+ static public int getPlatformIndex(String what) {
+ Integer entry = platformIndices.get(what);
+ return (entry == null) ? -1 : entry.intValue();
+ }
+
+
+ // These were changed to no longer rely on PApplet and PConstants because
+ // of conflicts that could happen with older versions of core.jar, where
+ // the MACOSX constant would instead read as the LINUX constant.
+
+
+ /**
+ * returns true if Processing is running on a Mac OS X machine.
+ */
+ static public boolean isMacOS() {
+ //return PApplet.platform == PConstants.MACOSX;
+ return System.getProperty("os.name").indexOf("Mac") != -1;
+ }
+
+
+ /**
+ * returns true if running on windows.
+ */
+ static public boolean isWindows() {
+ //return PApplet.platform == PConstants.WINDOWS;
+ return System.getProperty("os.name").indexOf("Windows") != -1;
+ }
+
+
+ /**
+ * true if running on linux.
+ */
+ static public boolean isLinux() {
+ //return PApplet.platform == PConstants.LINUX;
+ return System.getProperty("os.name").indexOf("Linux") != -1;
+ }
+
+
+ // .................................................................
+
+
+ static public File getSettingsFolder() {
+ File settingsFolder = null;
+
+ String preferencesPath = Preferences.get("settings.path");
+ if (preferencesPath != null) {
+ settingsFolder = new File(preferencesPath);
+
+ } else {
+ try {
+ settingsFolder = platform.getSettingsFolder();
+ } catch (Exception e) {
+ showError("Problem getting data folder",
+ "Error getting the Arduino data folder.", e);
+ }
+ }
+
+ // create the folder if it doesn't exist already
+ if (!settingsFolder.exists()) {
+ if (!settingsFolder.mkdirs()) {
+ showError("Settings issues",
+ "Arduino cannot run because it could not\n" +
+ "create a folder to store your settings.", null);
+ }
+ }
+ return settingsFolder;
+ }
+
+
+ /**
+ * Convenience method to get a File object for the specified filename inside
+ * the settings folder.
+ * For now, only used by Preferences to get the preferences.txt file.
+ * @param filename A file inside the settings folder.
+ * @return filename wrapped as a File object inside the settings folder
+ */
+ static public File getSettingsFile(String filename) {
+ return new File(getSettingsFolder(), filename);
+ }
+
+
+ static public File getBuildFolder() {
+ if (buildFolder == null) {
+ String buildPath = Preferences.get("build.path");
+ if (buildPath != null) {
+ buildFolder = new File(buildPath);
+
+ } else {
+ //File folder = new File(getTempFolder(), "build");
+ //if (!folder.exists()) folder.mkdirs();
+ buildFolder = createTempFolder("build");
+ buildFolder.deleteOnExit();
+ }
+ }
+ return buildFolder;
+ }
+
+
+ /**
+ * Get the path to the platform's temporary folder, by creating
+ * a temporary temporary file and getting its parent folder.
+ *
+ * Modified for revision 0094 to actually make the folder randomized
+ * to avoid conflicts in multi-user environments. (Bug 177)
+ */
+ static public File createTempFolder(String name) {
+ try {
+ File folder = File.createTempFile(name, null);
+ //String tempPath = ignored.getParent();
+ //return new File(tempPath);
+ folder.delete();
+ folder.mkdirs();
+ return folder;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ static public Set getLibraries() {
+ return libraries;
+ }
+
+
+ static public String getExamplesPath() {
+ return examplesFolder.getAbsolutePath();
+ }
+
+
+ static public String getLibrariesPath() {
+ return librariesFolder.getAbsolutePath();
+ }
+
+
+ static public File getToolsFolder() {
+ return toolsFolder;
+ }
+
+
+ static public String getToolsPath() {
+ return toolsFolder.getAbsolutePath();
+ }
+
+
+ static public File getHardwareFolder() {
+ // calculate on the fly because it's needed by Preferences.init() to find
+ // the boards.txt and programmers.txt preferences files (which happens
+ // before the other folders / paths get cached).
+ return getContentFile("hardware");
+ }
+
+
+ static public String getHardwarePath() {
+ return getHardwareFolder().getAbsolutePath();
+ }
+
+
+ static public String getAvrBasePath() {
+ if(Base.isLinux()) {
+ return ""; // avr tools are installed system-wide and in the path
+ } else {
+ return getHardwarePath() + File.separator + "tools" +
+ File.separator + "avr" + File.separator + "bin" + File.separator;
+ }
+ }
+
+
+ static public File getSketchbookFolder() {
+ return new File(Preferences.get("sketchbook.path"));
+ }
+
+
+ static public File getSketchbookLibrariesFolder() {
+ return new File(getSketchbookFolder(), "libraries");
+ }
+
+
+ static public String getSketchbookLibrariesPath() {
+ return getSketchbookLibrariesFolder().getAbsolutePath();
+ }
+
+
+ protected File getDefaultSketchbookFolder() {
+ File sketchbookFolder = null;
+ try {
+ sketchbookFolder = platform.getDefaultSketchbookFolder();
+ } catch (Exception e) { }
+
+ if (sketchbookFolder == null) {
+ sketchbookFolder = promptSketchbookLocation();
+ }
+
+ // create the folder if it doesn't exist already
+ boolean result = true;
+ if (!sketchbookFolder.exists()) {
+ result = sketchbookFolder.mkdirs();
+ }
+
+ if (!result) {
+ showError("You forgot your sketchbook",
+ "Arduino cannot run because it could not\n" +
+ "create a folder to store your sketchbook.", null);
+ }
+
+ return sketchbookFolder;
+ }
+
+
+ /**
+ * Check for a new sketchbook location.
+ */
+ static protected File promptSketchbookLocation() {
+ File folder = null;
+
+ folder = new File(System.getProperty("user.home"), "sketchbook");
+ if (!folder.exists()) {
+ folder.mkdirs();
+ return folder;
+ }
+
+ String prompt = "Select (or create new) folder for sketches...";
+ folder = Base.selectFolder(prompt, null, null);
+ if (folder == null) {
+ System.exit(0);
+ }
+ return folder;
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * Implements the cross-platform headache of opening URLs
+ * TODO This code should be replaced by PApplet.link(),
+ * however that's not a static method (because it requires
+ * an AppletContext when used as an applet), so it's mildly
+ * trickier than just removing this method.
+ */
+ static public void openURL(String url) {
+ try {
+ platform.openURL(url);
+
+ } catch (Exception e) {
+ showWarning("Problem Opening URL",
+ "Could not open the URL\n" + url, e);
+ }
+ }
+
+
+ /**
+ * Used to determine whether to disable the "Show Sketch Folder" option.
+ * @return true If a means of opening a folder is known to be available.
+ */
+ static protected boolean openFolderAvailable() {
+ return platform.openFolderAvailable();
+ }
+
+
+ /**
+ * Implements the other cross-platform headache of opening
+ * a folder in the machine's native file browser.
+ */
+ static public void openFolder(File file) {
+ try {
+ platform.openFolder(file);
+
+ } catch (Exception e) {
+ showWarning("Problem Opening Folder",
+ "Could not open the folder\n" + file.getAbsolutePath(), e);
+ }
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * Prompt for a fodler and return it as a File object (or null).
+ * Implementation for choosing directories that handles both the
+ * Mac OS X hack to allow the native AWT file dialog, or uses
+ * the JFileChooser on other platforms. Mac AWT trick obtained from
+ * this post
+ * on the OS X Java dev archive which explains the cryptic note in
+ * Apple's Java 1.4 release docs about the special System property.
+ */
+ static public File selectFolder(String prompt, File folder, Frame frame) {
+ if (Base.isMacOS()) {
+ if (frame == null) frame = new Frame(); //.pack();
+ FileDialog fd = new FileDialog(frame, prompt, FileDialog.LOAD);
+ if (folder != null) {
+ fd.setDirectory(folder.getParent());
+ //fd.setFile(folder.getName());
+ }
+ System.setProperty("apple.awt.fileDialogForDirectories", "true");
+ fd.setVisible(true);
+ System.setProperty("apple.awt.fileDialogForDirectories", "false");
+ if (fd.getFile() == null) {
+ return null;
+ }
+ return new File(fd.getDirectory(), fd.getFile());
+
+ } else {
+ JFileChooser fc = new JFileChooser();
+ fc.setDialogTitle(prompt);
+ if (folder != null) {
+ fc.setSelectedFile(folder);
+ }
+ fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+
+ int returned = fc.showOpenDialog(new JDialog());
+ if (returned == JFileChooser.APPROVE_OPTION) {
+ return fc.getSelectedFile();
+ }
+ }
+ return null;
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * Give this Frame a Processing icon.
+ */
+ static public void setIcon(Frame frame) {
+ Image image = Toolkit.getDefaultToolkit().createImage(PApplet.ICON_IMAGE);
+ frame.setIconImage(image);
+ }
+
+
+ // someone needs to be slapped
+ //static KeyStroke closeWindowKeyStroke;
+
+ /**
+ * Return true if the key event was a Ctrl-W or an ESC,
+ * both indicators to close the window.
+ * Use as part of a keyPressed() event handler for frames.
+ */
+ /*
+ static public boolean isCloseWindowEvent(KeyEvent e) {
+ if (closeWindowKeyStroke == null) {
+ int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ closeWindowKeyStroke = KeyStroke.getKeyStroke('W', modifiers);
+ }
+ return ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
+ KeyStroke.getKeyStrokeForEvent(e).equals(closeWindowKeyStroke));
+ }
+ */
+
+
+ /**
+ * Registers key events for a Ctrl-W and ESC with an ActionListener
+ * that will take care of disposing the window.
+ */
+ static public void registerWindowCloseKeys(JRootPane root, //Window window,
+ ActionListener disposer) {
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ root.registerKeyboardAction(disposer, stroke,
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ stroke = KeyStroke.getKeyStroke('W', modifiers);
+ root.registerKeyboardAction(disposer, stroke,
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+ }
+
+
+ // .................................................................
+
+
+ static public void showReference(String filename) {
+ File referenceFolder = Base.getContentFile("reference");
+ File referenceFile = new File(referenceFolder, filename);
+ openURL(referenceFile.getAbsolutePath());
+ }
+
+ static public void showGettingStarted() {
+ if (Base.isMacOS()) {
+ Base.showReference("Guide_MacOSX.html");
+ } else if (Base.isWindows()) {
+ Base.showReference("Guide_Windows.html");
+ } else {
+ Base.openURL("http://www.arduino.cc/playground/Learning/Linux");
+ }
+ }
+
+ static public void showReference() {
+ showReference("index.html");
+ }
+
+
+ static public void showEnvironment() {
+ showReference("Guide_Environment.html");
+ }
+
+
+ static public void showPlatforms() {
+ showReference("environment" + File.separator + "platforms.html");
+ }
+
+
+ static public void showTroubleshooting() {
+ showReference("Guide_Troubleshooting.html");
+ }
+
+
+ static public void showFAQ() {
+ showReference("faq.html");
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * "No cookie for you" type messages. Nothing fatal or all that
+ * much of a bummer, but something to notify the user about.
+ */
+ static public void showMessage(String title, String message) {
+ if (title == null) title = "Message";
+
+ if (commandLine) {
+ System.out.println(title + ": " + message);
+
+ } else {
+ JOptionPane.showMessageDialog(new Frame(), message, title,
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+ }
+
+
+ /**
+ * Non-fatal error message with optional stack trace side dish.
+ */
+ static public void showWarning(String title, String message, Exception e) {
+ if (title == null) title = "Warning";
+
+ if (commandLine) {
+ System.out.println(title + ": " + message);
+
+ } else {
+ JOptionPane.showMessageDialog(new Frame(), message, title,
+ JOptionPane.WARNING_MESSAGE);
+ }
+ if (e != null) e.printStackTrace();
+ }
+
+
+ /**
+ * Show an error message that's actually fatal to the program.
+ * This is an error that can't be recovered. Use showWarning()
+ * for errors that allow P5 to continue running.
+ */
+ static public void showError(String title, String message, Throwable e) {
+ if (title == null) title = "Error";
+
+ if (commandLine) {
+ System.err.println(title + ": " + message);
+
+ } else {
+ JOptionPane.showMessageDialog(new Frame(), message, title,
+ JOptionPane.ERROR_MESSAGE);
+ }
+ if (e != null) e.printStackTrace();
+ System.exit(1);
+ }
+
+
+ // ...................................................................
+
+
+ /**
+ * Retrieve a path to something in the Processing folder. Eventually this
+ * may refer to the Contents subfolder of Processing.app, if we bundle things
+ * up as a single .app file with no additional folders.
+ */
+// static public String getContentsPath(String filename) {
+// String basePath = System.getProperty("user.dir");
+// /*
+// // do this later, when moving to .app package
+// if (PApplet.platform == PConstants.MACOSX) {
+// basePath = System.getProperty("processing.contents");
+// }
+// */
+// return basePath + File.separator + filename;
+// }
+
+
+ /**
+ * Get a path for something in the Processing lib folder.
+ */
+ /*
+ static public String getLibContentsPath(String filename) {
+ String libPath = getContentsPath("lib/" + filename);
+ File libDir = new File(libPath);
+ if (libDir.exists()) {
+ return libPath;
+ }
+// was looking into making this run from Eclipse, but still too much mess
+// libPath = getContents("build/shared/lib/" + what);
+// libDir = new File(libPath);
+// if (libDir.exists()) {
+// return libPath;
+// }
+ return null;
+ }
+ */
+
+ static public File getContentFile(String name) {
+ String path = System.getProperty("user.dir");
+
+ // Get a path to somewhere inside the .app folder
+ if (Base.isMacOS()) {
+// javaroot
+// $JAVAROOT
+ String javaroot = System.getProperty("javaroot");
+ if (javaroot != null) {
+ path = javaroot;
+ }
+ }
+ File working = new File(path);
+ return new File(working, name);
+ }
+
+
+ /**
+ * Get an image associated with the current color theme.
+ */
+ static public Image getThemeImage(String name, Component who) {
+ return getLibImage("theme/" + name, who);
+ }
+
+
+ /**
+ * Return an Image object from inside the Processing lib folder.
+ */
+ static public Image getLibImage(String name, Component who) {
+ Image image = null;
+ Toolkit tk = Toolkit.getDefaultToolkit();
+
+ File imageLocation = new File(getContentFile("lib"), name);
+ image = tk.getImage(imageLocation.getAbsolutePath());
+ MediaTracker tracker = new MediaTracker(who);
+ tracker.addImage(image, 0);
+ try {
+ tracker.waitForAll();
+ } catch (InterruptedException e) { }
+ return image;
+ }
+
+
+ /**
+ * Return an InputStream for a file inside the Processing lib folder.
+ */
+ static public InputStream getLibStream(String filename) throws IOException {
+ return new FileInputStream(new File(getContentFile("lib"), filename));
+ }
+
+
+ // ...................................................................
+
+
+ /**
+ * Get the number of lines in a file by counting the number of newline
+ * characters inside a String (and adding 1).
+ */
+ static public int countLines(String what) {
+ int count = 1;
+ for (char c : what.toCharArray()) {
+ if (c == '\n') count++;
+ }
+ return count;
+ }
+
+
+ /**
+ * Same as PApplet.loadBytes(), however never does gzip decoding.
+ */
+ static public byte[] loadBytesRaw(File file) throws IOException {
+ int size = (int) file.length();
+ FileInputStream input = new FileInputStream(file);
+ byte buffer[] = new byte[size];
+ int offset = 0;
+ int bytesRead;
+ while ((bytesRead = input.read(buffer, offset, size-offset)) != -1) {
+ offset += bytesRead;
+ if (bytesRead == 0) break;
+ }
+ input.close(); // weren't properly being closed
+ input = null;
+ return buffer;
+ }
+
+
+ static public void copyFile(File sourceFile,
+ File targetFile) throws IOException {
+ InputStream from =
+ new BufferedInputStream(new FileInputStream(sourceFile));
+ OutputStream to =
+ new BufferedOutputStream(new FileOutputStream(targetFile));
+ byte[] buffer = new byte[16 * 1024];
+ int bytesRead;
+ while ((bytesRead = from.read(buffer)) != -1) {
+ to.write(buffer, 0, bytesRead);
+ }
+ to.flush();
+ from.close(); // ??
+ from = null;
+ to.close(); // ??
+ to = null;
+
+ targetFile.setLastModified(sourceFile.lastModified());
+ }
+
+
+ /**
+ * Grab the contents of a file as a string.
+ */
+ static public String loadFile(File file) throws IOException {
+ return PApplet.join(PApplet.loadStrings(file), "\n");
+
+ /*
+ // empty code file.. no worries, might be getting filled up later
+ if (file.length() == 0) return "";
+
+ //FileInputStream fis = new FileInputStream(file);
+ //InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+ //BufferedReader reader = new BufferedReader(isr);
+ BufferedReader reader = PApplet.createReader(file);
+
+ StringBuffer buffer = new StringBuffer();
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+// char[] cc = line.toCharArray();
+// for (int i = 0; i < cc.length; i++) {
+// char c = cc[i];
+// if (c < 32 || c > 126) System.out.println("found " + c + " " + ((int) c));
+// }
+//
+ buffer.append(line);
+ buffer.append('\n');
+ }
+ reader.close();
+ return buffer.toString();
+ */
+ }
+
+
+ /**
+ * Spew the contents of a String object out to a file.
+ */
+ static public void saveFile(String str, File file) throws IOException {
+ PApplet.saveStrings(file, new String[] { str });
+ /*
+ ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
+ InputStreamReader isr = new InputStreamReader(bis);
+ BufferedReader reader = new BufferedReader(isr);
+
+ FileOutputStream fos = new FileOutputStream(file);
+ OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
+ PrintWriter writer = new PrintWriter(osw);
+
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ writer.println(line);
+ }
+ writer.flush();
+ writer.close();
+ */
+ }
+
+
+ /**
+ * Copy a folder from one place to another. This ignores all dot files and
+ * folders found in the source directory, to avoid copying silly .DS_Store
+ * files and potentially troublesome .svn folders.
+ */
+ static public void copyDir(File sourceDir,
+ File targetDir) throws IOException {
+ targetDir.mkdirs();
+ String files[] = sourceDir.list();
+ for (int i = 0; i < files.length; i++) {
+ // Ignore dot files (.DS_Store), dot folders (.svn) while copying
+ if (files[i].charAt(0) == '.') continue;
+ //if (files[i].equals(".") || files[i].equals("..")) continue;
+ File source = new File(sourceDir, files[i]);
+ File target = new File(targetDir, files[i]);
+ if (source.isDirectory()) {
+ //target.mkdirs();
+ copyDir(source, target);
+ target.setLastModified(source.lastModified());
+ } else {
+ copyFile(source, target);
+ }
+ }
+ }
+
+
+ /**
+ * Remove all files in a directory and the directory itself.
+ */
+ static public void removeDir(File dir) {
+ if (dir.exists()) {
+ removeDescendants(dir);
+ if (!dir.delete()) {
+ System.err.println("Could not delete " + dir);
+ }
+ }
+ }
+
+
+ /**
+ * Recursively remove all files within a directory,
+ * used with removeDir(), or when the contents of a dir
+ * should be removed, but not the directory itself.
+ * (i.e. when cleaning temp files from lib/build)
+ */
+ static public void removeDescendants(File dir) {
+ if (!dir.exists()) return;
+
+ String files[] = dir.list();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].equals(".") || files[i].equals("..")) continue;
+ File dead = new File(dir, files[i]);
+ if (!dead.isDirectory()) {
+ if (!Preferences.getBoolean("compiler.save_build_files")) {
+ if (!dead.delete()) {
+ // temporarily disabled
+ System.err.println("Could not delete " + dead);
+ }
+ }
+ } else {
+ removeDir(dead);
+ //dead.delete();
+ }
+ }
+ }
+
+
+ /**
+ * Calculate the size of the contents of a folder.
+ * Used to determine whether sketches are empty or not.
+ * Note that the function calls itself recursively.
+ */
+ static public int calcFolderSize(File folder) {
+ int size = 0;
+
+ String files[] = folder.list();
+ // null if folder doesn't exist, happens when deleting sketch
+ if (files == null) return -1;
+
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].equals(".") || (files[i].equals("..")) ||
+ files[i].equals(".DS_Store")) continue;
+ File fella = new File(folder, files[i]);
+ if (fella.isDirectory()) {
+ size += calcFolderSize(fella);
+ } else {
+ size += (int) fella.length();
+ }
+ }
+ return size;
+ }
+
+
+ /**
+ * Recursively creates a list of all files within the specified folder,
+ * and returns a list of their relative paths.
+ * Ignores any files/folders prefixed with a dot.
+ */
+ static public String[] listFiles(String path, boolean relative) {
+ return listFiles(new File(path), relative);
+ }
+
+
+ static public String[] listFiles(File folder, boolean relative) {
+ String path = folder.getAbsolutePath();
+ Vector vector = new Vector();
+ listFiles(relative ? (path + File.separator) : "", path, vector);
+ String outgoing[] = new String[vector.size()];
+ vector.copyInto(outgoing);
+ return outgoing;
+ }
+
+
+ static protected void listFiles(String basePath,
+ String path, Vector vector) {
+ File folder = new File(path);
+ String list[] = folder.list();
+ if (list == null) return;
+
+ for (int i = 0; i < list.length; i++) {
+ if (list[i].charAt(0) == '.') continue;
+
+ File file = new File(path, list[i]);
+ String newPath = file.getAbsolutePath();
+ if (newPath.startsWith(basePath)) {
+ newPath = newPath.substring(basePath.length());
+ }
+ vector.add(newPath);
+ if (file.isDirectory()) {
+ listFiles(basePath, newPath, vector);
+ }
+ }
+ }
+}
diff --git a/app/src/processing/app/Commander.java.disabled b/app/src/processing/app/Commander.java.disabled
new file mode 100644
index 000000000..88d9cb598
--- /dev/null
+++ b/app/src/processing/app/Commander.java.disabled
@@ -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.
+ *
+ * --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).
+ *
+ *
+ * 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= Specify the sketch folder (required)");
+ out.println("--output= 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= Specify a preferences file to use (optional).");
+ }
+}
\ No newline at end of file
diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java
new file mode 100644
index 000000000..392efdc38
--- /dev/null
+++ b/app/src/processing/app/Editor.java
@@ -0,0 +1,2514 @@
+/* -*- 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.debug.*;
+import processing.app.syntax.*;
+import processing.app.tools.*;
+import processing.core.*;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.awt.print.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.zip.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.undo.*;
+
+import gnu.io.*;
+
+
+/**
+ * Main editor panel for the Processing Development Environment.
+ */
+public class Editor extends JFrame implements RunnerListener {
+
+ Base base;
+
+ // otherwise, if the window is resized with the message label
+ // set to blank, it's preferredSize() will be fukered
+ static protected final String EMPTY =
+ " " +
+ " " +
+ " ";
+
+ /** Command on Mac OS X, Ctrl on Windows and Linux */
+ static final int SHORTCUT_KEY_MASK =
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ /** Command-W on Mac OS X, Ctrl-W on Windows and Linux */
+ static final KeyStroke WINDOW_CLOSE_KEYSTROKE =
+ KeyStroke.getKeyStroke('W', SHORTCUT_KEY_MASK);
+ /** Command-Option on Mac OS X, Ctrl-Alt on Windows and Linux */
+ static final int SHORTCUT_ALT_KEY_MASK = ActionEvent.ALT_MASK |
+ Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+
+ /**
+ * true if this file has not yet been given a name by the user
+ */
+ boolean untitled;
+
+ PageFormat pageFormat;
+ PrinterJob printerJob;
+
+ // file, sketch, and tools menus for re-inserting items
+ JMenu fileMenu;
+ JMenu sketchMenu;
+ JMenu toolsMenu;
+
+ int numTools = 0;
+
+ EditorToolbar toolbar;
+ // these menus are shared so that they needn't be rebuilt for all windows
+ // each time a sketch is created, renamed, or moved.
+ static JMenu toolbarMenu;
+ static JMenu sketchbookMenu;
+ static JMenu examplesMenu;
+ static JMenu importMenu;
+
+ // these menus are shared so that the board and serial port selections
+ // are the same for all windows (since the board and serial port that are
+ // actually used are determined by the preferences, which are shared)
+ static JMenu boardsMenu;
+ static JMenu serialMenu;
+
+ static SerialMenuListener serialMenuListener;
+ static SerialMonitor serialMonitor;
+
+ EditorHeader header;
+ EditorStatus status;
+ EditorConsole console;
+
+ JSplitPane splitPane;
+ JPanel consolePanel;
+
+ JLabel lineNumberComponent;
+
+ // currently opened program
+ Sketch sketch;
+
+ EditorLineStatus lineStatus;
+
+ JEditTextArea textarea;
+ EditorListener listener;
+
+ // runtime information and window placement
+ Point sketchWindowLocation;
+ Runner runtime;
+
+ JMenuItem exportAppItem;
+ JMenuItem saveMenuItem;
+ JMenuItem saveAsMenuItem;
+
+ boolean running;
+ boolean presenting;
+ boolean uploading;
+
+ // undo fellers
+ JMenuItem undoItem, redoItem;
+ protected UndoAction undoAction;
+ protected RedoAction redoAction;
+ UndoManager undo;
+ // used internally, and only briefly
+ CompoundEdit compoundEdit;
+
+ FindReplace find;
+
+
+ public Editor(Base ibase, String path, int[] location) {
+ super("Arduino");
+ this.base = ibase;
+
+ //Base.setIcon(this);
+
+ // add listener to handle window close box hit event
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ base.handleClose(Editor.this);
+ }
+ });
+ // don't close the window when clicked, the app will take care
+ // of that via the handleQuitInternal() methods
+ // http://dev.processing.org/bugs/show_bug.cgi?id=440
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+
+ // When bringing a window to front, let the Base know
+ addWindowListener(new WindowAdapter() {
+ public void windowActivated(WindowEvent e) {
+ base.handleActivated(Editor.this);
+
+ // re-add the sub-menus that are shared by all windows
+ fileMenu.insert(sketchbookMenu, 2);
+ fileMenu.insert(examplesMenu, 3);
+ sketchMenu.insert(importMenu, 4);
+ toolsMenu.insert(boardsMenu, numTools);
+ toolsMenu.insert(serialMenu, numTools + 1);
+ }
+ });
+
+ //PdeKeywords keywords = new PdeKeywords();
+ //sketchbook = new Sketchbook(this);
+
+ if (serialMonitor == null)
+ serialMonitor = new SerialMonitor(Preferences.get("serial.port"));
+
+ buildMenuBar();
+
+ // For rev 0120, placing things inside a JPanel
+ Container contentPain = getContentPane();
+ contentPain.setLayout(new BorderLayout());
+ JPanel pain = new JPanel();
+ pain.setLayout(new BorderLayout());
+ contentPain.add(pain, BorderLayout.CENTER);
+
+ Box box = Box.createVerticalBox();
+ Box upper = Box.createVerticalBox();
+
+ if (toolbarMenu == null) {
+ toolbarMenu = new JMenu();
+ base.rebuildToolbarMenu(toolbarMenu);
+ }
+ toolbar = new EditorToolbar(this, toolbarMenu);
+ upper.add(toolbar);
+
+ header = new EditorHeader(this);
+ upper.add(header);
+
+ textarea = new JEditTextArea(new PdeTextAreaDefaults());
+ textarea.setRightClickPopup(new TextAreaPopup());
+ textarea.setHorizontalOffset(6);
+
+ // assemble console panel, consisting of status area and the console itself
+ consolePanel = new JPanel();
+ consolePanel.setLayout(new BorderLayout());
+
+ status = new EditorStatus(this);
+ consolePanel.add(status, BorderLayout.NORTH);
+
+ console = new EditorConsole(this);
+ // windows puts an ugly border on this guy
+ console.setBorder(null);
+ consolePanel.add(console, BorderLayout.CENTER);
+
+ lineStatus = new EditorLineStatus(textarea);
+ consolePanel.add(lineStatus, BorderLayout.SOUTH);
+
+ upper.add(textarea);
+ splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+ upper, consolePanel);
+
+ splitPane.setOneTouchExpandable(true);
+ // repaint child panes while resizing
+ splitPane.setContinuousLayout(true);
+ // if window increases in size, give all of increase to
+ // the textarea in the uppper pane
+ splitPane.setResizeWeight(1D);
+
+ // to fix ugliness.. normally macosx java 1.3 puts an
+ // ugly white border around this object, so turn it off.
+ splitPane.setBorder(null);
+
+ // the default size on windows is too small and kinda ugly
+ int dividerSize = Preferences.getInteger("editor.divider.size");
+ if (dividerSize != 0) {
+ splitPane.setDividerSize(dividerSize);
+ }
+
+ splitPane.setMinimumSize(new Dimension(600, 400));
+ box.add(splitPane);
+
+ // hopefully these are no longer needed w/ swing
+ // (har har har.. that was wishful thinking)
+ listener = new EditorListener(this, textarea);
+ pain.add(box);
+
+ pain.setTransferHandler(new TransferHandler() {
+
+ public boolean canImport(JComponent dest, DataFlavor[] flavors) {
+ return true;
+ }
+
+ public boolean importData(JComponent src, Transferable transferable) {
+ int successful = 0;
+
+ try {
+ DataFlavor uriListFlavor =
+ new DataFlavor("text/uri-list;class=java.lang.String");
+
+ if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
+ java.util.List list = (java.util.List)
+ transferable.getTransferData(DataFlavor.javaFileListFlavor);
+ for (int i = 0; i < list.size(); i++) {
+ File file = (File) list.get(i);
+ if (sketch.addFile(file)) {
+ successful++;
+ }
+ }
+ } else if (transferable.isDataFlavorSupported(uriListFlavor)) {
+ //System.out.println("uri list");
+ String data = (String)transferable.getTransferData(uriListFlavor);
+ String[] pieces = PApplet.splitTokens(data, "\r\n");
+ //PApplet.println(pieces);
+ for (int i = 0; i < pieces.length; i++) {
+ if (pieces[i].startsWith("#")) continue;
+
+ String path = null;
+ if (pieces[i].startsWith("file:///")) {
+ path = pieces[i].substring(7);
+ } else if (pieces[i].startsWith("file:/")) {
+ path = pieces[i].substring(5);
+ }
+ if (sketch.addFile(new File(path))) {
+ successful++;
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ if (successful == 0) {
+ statusError("No files were added to the sketch.");
+
+ } else if (successful == 1) {
+ statusNotice("One file added to the sketch.");
+
+ } else {
+ statusNotice(successful + " files added to the sketch.");
+ }
+ return true;
+ }
+ });
+
+// System.out.println("t1");
+
+ // Finish preparing Editor (formerly found in Base)
+ pack();
+
+// System.out.println("t2");
+
+ // Set the window bounds and the divider location before setting it visible
+ setPlacement(location);
+
+// System.out.println("t3");
+
+ // Bring back the general options for the editor
+ applyPreferences();
+
+// System.out.println("t4");
+
+ // Open the document that was passed in
+ boolean loaded = handleOpenInternal(path);
+ if (!loaded) sketch = null;
+
+// System.out.println("t5");
+
+ // All set, now show the window
+ //setVisible(true);
+ }
+
+
+ protected void setPlacement(int[] location) {
+ setBounds(location[0], location[1], location[2], location[3]);
+ if (location[4] != 0) {
+ splitPane.setDividerLocation(location[4]);
+ }
+ }
+
+
+ protected int[] getPlacement() {
+ int[] location = new int[5];
+
+ // Get the dimensions of the Frame
+ Rectangle bounds = getBounds();
+ location[0] = bounds.x;
+ location[1] = bounds.y;
+ location[2] = bounds.width;
+ location[3] = bounds.height;
+
+ // Get the current placement of the divider
+ location[4] = splitPane.getDividerLocation();
+
+ return location;
+ }
+
+
+ /**
+ * Hack for #@#)$(* Mac OS X 10.2.
+ *
+ * This appears to only be required on OS X 10.2, and is not
+ * even being called on later versions of OS X or Windows.
+ */
+ public Dimension getMinimumSize() {
+ //System.out.println("getting minimum size");
+ return new Dimension(500, 550);
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Read and apply new values from the preferences, either because
+ * the app is just starting up, or the user just finished messing
+ * with things in the Preferences window.
+ */
+ protected void applyPreferences() {
+
+ // apply the setting for 'use external editor'
+ boolean external = Preferences.getBoolean("editor.external");
+
+ textarea.setEditable(!external);
+ saveMenuItem.setEnabled(!external);
+ saveAsMenuItem.setEnabled(!external);
+
+ TextAreaPainter painter = textarea.getPainter();
+ if (external) {
+ // disable line highlight and turn off the caret when disabling
+ Color color = Theme.getColor("editor.external.bgcolor");
+ painter.setBackground(color);
+ painter.setLineHighlightEnabled(false);
+ textarea.setCaretVisible(false);
+
+ } else {
+ Color color = Theme.getColor("editor.bgcolor");
+ painter.setBackground(color);
+ boolean highlight = Preferences.getBoolean("editor.linehighlight");
+ painter.setLineHighlightEnabled(highlight);
+ textarea.setCaretVisible(true);
+ }
+
+ // apply changes to the font size for the editor
+ //TextAreaPainter painter = textarea.getPainter();
+ painter.setFont(Preferences.getFont("editor.font"));
+ //Font font = painter.getFont();
+ //textarea.getPainter().setFont(new Font("Courier", Font.PLAIN, 36));
+
+ // in case tab expansion stuff has changed
+ listener.applyPreferences();
+
+ // in case moved to a new location
+ // For 0125, changing to async version (to be implemented later)
+ //sketchbook.rebuildMenus();
+ // For 0126, moved into Base, which will notify all editors.
+ //base.rebuildMenusAsync();
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ protected void buildMenuBar() {
+ JMenuBar menubar = new JMenuBar();
+ menubar = new JMenuBar();
+ menubar.add(buildFileMenu());
+ menubar.add(buildEditMenu());
+ menubar.add(buildSketchMenu());
+ menubar.add(buildToolsMenu());
+ menubar.add(buildHelpMenu());
+ setJMenuBar(menubar);
+ }
+
+
+ protected JMenu buildFileMenu() {
+ JMenuItem item;
+ fileMenu = new JMenu("File");
+
+ item = newJMenuItem("New", 'N');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ base.handleNew();
+ }
+ });
+ fileMenu.add(item);
+
+ item = Editor.newJMenuItem("Open...", 'O');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ base.handleOpenPrompt();
+ }
+ });
+ fileMenu.add(item);
+
+ if (sketchbookMenu == null) {
+ sketchbookMenu = new JMenu("Sketchbook");
+ base.rebuildSketchbookMenu(sketchbookMenu);
+ }
+ fileMenu.add(sketchbookMenu);
+
+ if (examplesMenu == null) {
+ examplesMenu = new JMenu("Examples");
+ base.rebuildExamplesMenu(examplesMenu);
+ }
+ fileMenu.add(examplesMenu);
+
+ item = Editor.newJMenuItem("Close", 'W');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ base.handleClose(Editor.this);
+ }
+ });
+ fileMenu.add(item);
+
+ saveMenuItem = newJMenuItem("Save", 'S');
+ saveMenuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleSave(false);
+ }
+ });
+ fileMenu.add(saveMenuItem);
+
+ saveAsMenuItem = newJMenuItemShift("Save As...", 'S');
+ saveAsMenuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleSaveAs();
+ }
+ });
+ fileMenu.add(saveAsMenuItem);
+
+ item = newJMenuItem("Upload to I/O Board", 'U');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleExport();
+ }
+ });
+ fileMenu.add(item);
+
+ fileMenu.addSeparator();
+
+ item = newJMenuItemShift("Page Setup", 'P');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handlePageSetup();
+ }
+ });
+ fileMenu.add(item);
+
+ item = newJMenuItem("Print", 'P');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handlePrint();
+ }
+ });
+ fileMenu.add(item);
+
+ // macosx already has its own preferences and quit menu
+ if (!Base.isMacOS()) {
+ fileMenu.addSeparator();
+
+ item = newJMenuItem("Preferences", ',');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ base.handlePrefs();
+ }
+ });
+ fileMenu.add(item);
+
+ fileMenu.addSeparator();
+
+ item = newJMenuItem("Quit", 'Q');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ base.handleQuit();
+ }
+ });
+ fileMenu.add(item);
+ }
+ return fileMenu;
+ }
+
+
+ protected JMenu buildSketchMenu() {
+ JMenuItem item;
+ sketchMenu = new JMenu("Sketch");
+
+ item = newJMenuItem("Verify / Compile", 'R');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleRun(false);
+ }
+ });
+ sketchMenu.add(item);
+
+// item = newJMenuItemShift("Present", 'R');
+// item.addActionListener(new ActionListener() {
+// public void actionPerformed(ActionEvent e) {
+// handleRun(true);
+// }
+// });
+// sketchMenu.add(item);
+
+ item = new JMenuItem("Stop");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleStop();
+ }
+ });
+ sketchMenu.add(item);
+
+ sketchMenu.addSeparator();
+
+ if (importMenu == null) {
+ importMenu = new JMenu("Import Library...");
+ base.rebuildImportMenu(importMenu);
+ }
+ sketchMenu.add(importMenu);
+
+ item = newJMenuItem("Show Sketch Folder", 'K');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.openFolder(sketch.getFolder());
+ }
+ });
+ sketchMenu.add(item);
+ item.setEnabled(Base.openFolderAvailable());
+
+ item = new JMenuItem("Add File...");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ sketch.handleAddFile();
+ }
+ });
+ sketchMenu.add(item);
+
+ return sketchMenu;
+ }
+
+
+ protected JMenu buildToolsMenu() {
+ toolsMenu = new JMenu("Tools");
+ JMenu menu = toolsMenu;
+ JMenuItem item;
+
+ addInternalTools(menu);
+ addTools(menu, Base.getToolsFolder());
+ File sketchbookTools = new File(Base.getSketchbookFolder(), "tools");
+ addTools(menu, sketchbookTools);
+
+ menu.addSeparator();
+
+ numTools = menu.getItemCount();
+
+ // XXX: DAM: these should probably be implemented using the Tools plugin
+ // API, if possible (i.e. if it supports custom actions, etc.)
+
+ if (boardsMenu == null) {
+ boardsMenu = new JMenu("Board");
+ ButtonGroup boardGroup = new ButtonGroup();
+ for (Iterator i = Preferences.getSubKeys("boards"); i.hasNext(); ) {
+ String board = (String) i.next();
+ Action action = new BoardMenuAction(board);
+ item = new JRadioButtonMenuItem(action);
+ if (board.equals(Preferences.get("board")))
+ item.setSelected(true);
+ boardGroup.add(item);
+ boardsMenu.add(item);
+ }
+ }
+ menu.add(boardsMenu);
+
+ if (serialMenuListener == null)
+ serialMenuListener = new SerialMenuListener();
+ if (serialMenu == null)
+ serialMenu = new JMenu("Serial Port");
+ populateSerialMenu();
+ menu.add(serialMenu);
+
+ menu.addSeparator();
+
+ JMenu bootloaderMenu = new JMenu("Burn Bootloader");
+ for (Iterator i = Preferences.getSubKeys("programmers"); i.hasNext(); ) {
+ String programmer = (String) i.next();
+ Action action = new BootloaderMenuAction(programmer);
+ item = new JMenuItem(action);
+ bootloaderMenu.add(item);
+ }
+ menu.add(bootloaderMenu);
+
+ menu.addMenuListener(new MenuListener() {
+ public void menuCanceled(MenuEvent e) {}
+ public void menuDeselected(MenuEvent e) {}
+ public void menuSelected(MenuEvent e) {
+ //System.out.println("Tools menu selected.");
+ populateSerialMenu();
+ }
+ });
+
+ return menu;
+ }
+
+
+ protected void addTools(JMenu menu, File sourceFolder) {
+ HashMap toolItems = new HashMap();
+
+ File[] folders = sourceFolder.listFiles(new FileFilter() {
+ public boolean accept(File folder) {
+ if (folder.isDirectory()) {
+ //System.out.println("checking " + folder);
+ File subfolder = new File(folder, "tool");
+ return subfolder.exists();
+ }
+ return false;
+ }
+ });
+
+ if (folders == null || folders.length == 0) {
+ return;
+ }
+
+ for (int i = 0; i < folders.length; i++) {
+ File toolDirectory = new File(folders[i], "tool");
+
+ try {
+ // add dir to classpath for .classes
+ //urlList.add(toolDirectory.toURL());
+
+ // add .jar files to classpath
+ File[] archives = toolDirectory.listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return (name.toLowerCase().endsWith(".jar") ||
+ name.toLowerCase().endsWith(".zip"));
+ }
+ });
+
+ URL[] urlList = new URL[archives.length];
+ for (int j = 0; j < urlList.length; j++) {
+ urlList[j] = archives[j].toURL();
+ }
+ URLClassLoader loader = new URLClassLoader(urlList);
+
+ String className = null;
+ for (int j = 0; j < archives.length; j++) {
+ className = findClassInZipFile(folders[i].getName(), archives[j]);
+ if (className != null) break;
+ }
+
+ /*
+ // Alternatively, could use manifest files with special attributes:
+ // http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html
+ // Example code for loading from a manifest file:
+ // http://forums.sun.com/thread.jspa?messageID=3791501
+ File infoFile = new File(toolDirectory, "tool.txt");
+ if (!infoFile.exists()) continue;
+
+ String[] info = PApplet.loadStrings(infoFile);
+ //Main-Class: org.poo.shoe.AwesomerTool
+ //String className = folders[i].getName();
+ String className = null;
+ for (int k = 0; k < info.length; k++) {
+ if (info[k].startsWith(";")) continue;
+
+ String[] pieces = PApplet.splitTokens(info[k], ": ");
+ if (pieces.length == 2) {
+ if (pieces[0].equals("Main-Class")) {
+ className = pieces[1];
+ }
+ }
+ }
+ */
+ // If no class name found, just move on.
+ if (className == null) continue;
+
+ Class toolClass = Class.forName(className, true, loader);
+ final Tool tool = (Tool) toolClass.newInstance();
+
+ tool.init(Editor.this);
+
+ String title = tool.getMenuTitle();
+ JMenuItem item = new JMenuItem(title);
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ SwingUtilities.invokeLater(tool);
+ }
+ });
+ //menu.add(item);
+ toolItems.put(title, item);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ ArrayList toolList = new ArrayList(toolItems.keySet());
+ if (toolList.size() == 0) return;
+
+ menu.addSeparator();
+ Collections.sort(toolList);
+ for (String title : toolList) {
+ menu.add((JMenuItem) toolItems.get(title));
+ }
+ }
+
+
+ protected String findClassInZipFile(String base, File file) {
+ // Class file to search for
+ String classFileName = "/" + base + ".class";
+
+ try {
+ ZipFile zipFile = new ZipFile(file);
+ Enumeration entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+
+ if (!entry.isDirectory()) {
+ String name = entry.getName();
+ //System.out.println("entry: " + name);
+
+ if (name.endsWith(classFileName)) {
+ //int slash = name.lastIndexOf('/');
+ //String packageName = (slash == -1) ? "" : name.substring(0, slash);
+ // Remove .class and convert slashes to periods.
+ return name.substring(0, name.length() - 6).replace('/', '.');
+ }
+ }
+ }
+ } catch (IOException e) {
+ //System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")");
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ protected JMenuItem createToolMenuItem(String className) {
+ try {
+ Class toolClass = Class.forName(className);
+ final Tool tool = (Tool) toolClass.newInstance();
+
+ JMenuItem item = new JMenuItem(tool.getMenuTitle());
+
+ tool.init(Editor.this);
+
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ SwingUtilities.invokeLater(tool);
+ }
+ });
+ return item;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ protected JMenu addInternalTools(JMenu menu) {
+ JMenuItem item;
+
+ item = createToolMenuItem("processing.app.tools.AutoFormat");
+ int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ item.setAccelerator(KeyStroke.getKeyStroke('T', modifiers));
+ menu.add(item);
+
+ //menu.add(createToolMenuItem("processing.app.tools.CreateFont"));
+ //menu.add(createToolMenuItem("processing.app.tools.ColorSelector"));
+ menu.add(createToolMenuItem("processing.app.tools.Archiver"));
+ menu.add(createToolMenuItem("processing.app.tools.FixEncoding"));
+
+ return menu;
+ }
+
+
+ class SerialMenuListener implements ActionListener {
+ //public SerialMenuListener() { }
+
+ public void actionPerformed(ActionEvent e) {
+ if(serialMenu == null) {
+ System.out.println("serialMenu is null");
+ return;
+ }
+ int count = serialMenu.getItemCount();
+ for (int i = 0; i < count; i++) {
+ ((JCheckBoxMenuItem)serialMenu.getItem(i)).setState(false);
+ }
+ JCheckBoxMenuItem item = (JCheckBoxMenuItem)e.getSource();
+ item.setState(true);
+ String name = item.getText();
+ //System.out.println(item.getLabel());
+ Preferences.set("serial.port", name);
+ serialMonitor.closeSerialPort();
+ serialMonitor.setVisible(false);
+ serialMonitor = new SerialMonitor(Preferences.get("serial.port"));
+ //System.out.println("set to " + get("serial.port"));
+ }
+
+ /*
+ public void actionPerformed(ActionEvent e) {
+ System.out.println(e.getSource());
+ String name = e.getActionCommand();
+ PdeBase.properties.put("serial.port", name);
+ System.out.println("set to " + get("serial.port"));
+ //editor.skOpen(path + File.separator + name, name);
+ // need to push "serial.port" into PdeBase.properties
+ }
+ */
+ }
+
+
+ class BoardMenuAction extends AbstractAction {
+ private String board;
+ public BoardMenuAction(String board) {
+ super(Preferences.get("boards." + board + ".name"));
+ this.board = board;
+ }
+ public void actionPerformed(ActionEvent actionevent) {
+ //System.out.println("Switching to " + board);
+ Preferences.set("board", board);
+ }
+ }
+
+ class BootloaderMenuAction extends AbstractAction {
+ private String programmer;
+ public BootloaderMenuAction(String programmer) {
+ super("w/ " + Preferences.get("programmers." + programmer + ".name"));
+ this.programmer = programmer;
+ }
+ public void actionPerformed(ActionEvent actionevent) {
+ handleBurnBootloader(programmer);
+ }
+ }
+
+
+ protected void populateSerialMenu() {
+ // getting list of ports
+
+ JMenuItem rbMenuItem;
+
+ //System.out.println("Clearing serial port menu.");
+
+ serialMenu.removeAll();
+ boolean empty = true;
+
+ try
+ {
+ for (Enumeration enumeration = CommPortIdentifier.getPortIdentifiers(); enumeration.hasMoreElements();)
+ {
+ CommPortIdentifier commportidentifier = (CommPortIdentifier)enumeration.nextElement();
+ //System.out.println("Found communication port: " + commportidentifier);
+ if (commportidentifier.getPortType() == CommPortIdentifier.PORT_SERIAL)
+ {
+ //System.out.println("Adding port to serial port menu: " + commportidentifier);
+ String curr_port = commportidentifier.getName();
+ rbMenuItem = new JCheckBoxMenuItem(curr_port, curr_port.equals(Preferences.get("serial.port")));
+ rbMenuItem.addActionListener(serialMenuListener);
+ //serialGroup.add(rbMenuItem);
+ serialMenu.add(rbMenuItem);
+ empty = false;
+ }
+ }
+ if (!empty) {
+ //System.out.println("enabling the serialMenu");
+ serialMenu.setEnabled(true);
+ }
+
+ }
+
+ catch (Exception exception)
+ {
+ System.out.println("error retrieving port list");
+ exception.printStackTrace();
+ }
+
+ if (serialMenu.getItemCount() == 0) {
+ serialMenu.setEnabled(false);
+ }
+
+ //serialMenu.addSeparator();
+ //serialMenu.add(item);
+ }
+
+
+ protected JMenu buildHelpMenu() {
+ JMenu menu = new JMenu("Help");
+ JMenuItem item;
+
+ /*
+ // testing internal web server to serve up docs from a zip file
+ item = new JMenuItem("Web Server Test");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ //WebServer ws = new WebServer();
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ int port = WebServer.launch("/Users/fry/coconut/processing/build/shared/reference.zip");
+ Base.openURL("http://127.0.0.1:" + port + "/reference/setup_.html");
+
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ });
+ }
+ });
+ menu.add(item);
+ */
+
+ /*
+ item = new JMenuItem("Browser Test");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ //Base.openURL("http://processing.org/learning/gettingstarted/");
+ //JFrame browserFrame = new JFrame("Browser");
+ BrowserStartup bs = new BrowserStartup("jar:file:/Users/fry/coconut/processing/build/shared/reference.zip!/reference/setup_.html");
+ bs.initUI();
+ bs.launch();
+ }
+ });
+ menu.add(item);
+ */
+
+ item = new JMenuItem("Getting Started");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.showGettingStarted();
+ }
+ });
+ menu.add(item);
+
+ item = new JMenuItem("Environment");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.showEnvironment();
+ }
+ });
+ menu.add(item);
+
+ item = new JMenuItem("Troubleshooting");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.showTroubleshooting();
+ }
+ });
+ menu.add(item);
+
+ item = new JMenuItem("Reference");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.showReference();
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItemShift("Find in Reference", 'F');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (textarea.isSelectionActive()) {
+ handleFindReference();
+ }
+ }
+ });
+ menu.add(item);
+
+ item = new JMenuItem("Frequently Asked Questions");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.showFAQ();
+ }
+ });
+ menu.add(item);
+
+ item = new JMenuItem("Visit Arduino.cc");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Base.openURL("http://arduino.cc/");
+ }
+ });
+ menu.add(item);
+
+ // macosx already has its own about menu
+ if (!Base.isMacOS()) {
+ menu.addSeparator();
+ item = new JMenuItem("About Arduino");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ base.handleAbout();
+ }
+ });
+ menu.add(item);
+ }
+
+ return menu;
+ }
+
+
+ protected JMenu buildEditMenu() {
+ JMenu menu = new JMenu("Edit");
+ JMenuItem item;
+
+ undoItem = newJMenuItem("Undo", 'Z');
+ undoItem.addActionListener(undoAction = new UndoAction());
+ menu.add(undoItem);
+
+ redoItem = newJMenuItem("Redo", 'Y');
+ redoItem.addActionListener(redoAction = new RedoAction());
+ menu.add(redoItem);
+
+ menu.addSeparator();
+
+ // TODO "cut" and "copy" should really only be enabled
+ // if some text is currently selected
+ item = newJMenuItem("Cut", 'X');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleCut();
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItem("Copy", 'C');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ textarea.copy();
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItemShift("Copy for Forum", 'C');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+// SwingUtilities.invokeLater(new Runnable() {
+// public void run() {
+ new DiscourseFormat(Editor.this, false).show();
+// }
+// });
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItemAlt("Copy as HTML", 'C');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+// SwingUtilities.invokeLater(new Runnable() {
+// public void run() {
+ new DiscourseFormat(Editor.this, true).show();
+// }
+// });
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItem("Paste", 'V');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ textarea.paste();
+ sketch.setModified(true);
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItem("Select All", 'A');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ textarea.selectAll();
+ }
+ });
+ menu.add(item);
+
+ menu.addSeparator();
+
+ item = newJMenuItem("Comment/Uncomment", '/');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleCommentUncomment();
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItem("Increase Indent", ']');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleIndentOutdent(true);
+ }
+ });
+ menu.add(item);
+
+ item = newJMenuItem("Decrease Indent", '[');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleIndentOutdent(false);
+ }
+ });
+ menu.add(item);
+
+ menu.addSeparator();
+
+ item = newJMenuItem("Find...", 'F');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (find == null) {
+ find = new FindReplace(Editor.this);
+ }
+ //new FindReplace(Editor.this).show();
+ find.setVisible(true);
+ //find.setVisible(true);
+ }
+ });
+ menu.add(item);
+
+ // TODO find next should only be enabled after a
+ // search has actually taken place
+ item = newJMenuItem("Find Next", 'G');
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (find != null) {
+ //find.find(true);
+ //FindReplace find = new FindReplace(Editor.this); //.show();
+ find.find(true);
+ }
+ }
+ });
+ menu.add(item);
+
+ return menu;
+ }
+
+
+ /**
+ * A software engineer, somewhere, needs to have his abstraction
+ * taken away. In some countries they jail or beat people for writing
+ * the sort of API that would require a five line helper function
+ * just to set the command key for a menu item.
+ */
+ static public JMenuItem newJMenuItem(String title, int what) {
+ JMenuItem menuItem = new JMenuItem(title);
+ int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers));
+ return menuItem;
+ }
+
+
+ /**
+ * Like newJMenuItem() but adds shift as a modifier for the key command.
+ */
+ static public JMenuItem newJMenuItemShift(String title, int what) {
+ JMenuItem menuItem = new JMenuItem(title);
+ int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ modifiers |= ActionEvent.SHIFT_MASK;
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers));
+ return menuItem;
+ }
+
+
+ /**
+ * Same as newJMenuItem(), but adds the ALT (on Linux and Windows)
+ * or OPTION (on Mac OS X) key as a modifier.
+ */
+ static public JMenuItem newJMenuItemAlt(String title, int what) {
+ JMenuItem menuItem = new JMenuItem(title);
+ //int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ //menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(what, SHORTCUT_ALT_KEY_MASK));
+ return menuItem;
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ class UndoAction extends AbstractAction {
+ public UndoAction() {
+ super("Undo");
+ this.setEnabled(false);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ undo.undo();
+ } catch (CannotUndoException ex) {
+ //System.out.println("Unable to undo: " + ex);
+ //ex.printStackTrace();
+ }
+ updateUndoState();
+ redoAction.updateRedoState();
+ }
+
+ protected void updateUndoState() {
+ if (undo.canUndo()) {
+ this.setEnabled(true);
+ undoItem.setEnabled(true);
+ undoItem.setText(undo.getUndoPresentationName());
+ putValue(Action.NAME, undo.getUndoPresentationName());
+ if (sketch != null) {
+ sketch.setModified(true); // 0107
+ }
+ } else {
+ this.setEnabled(false);
+ undoItem.setEnabled(false);
+ undoItem.setText("Undo");
+ putValue(Action.NAME, "Undo");
+ if (sketch != null) {
+ sketch.setModified(false); // 0107
+ }
+ }
+ }
+ }
+
+
+ class RedoAction extends AbstractAction {
+ public RedoAction() {
+ super("Redo");
+ this.setEnabled(false);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ undo.redo();
+ } catch (CannotRedoException ex) {
+ //System.out.println("Unable to redo: " + ex);
+ //ex.printStackTrace();
+ }
+ updateRedoState();
+ undoAction.updateUndoState();
+ }
+
+ protected void updateRedoState() {
+ if (undo.canRedo()) {
+ redoItem.setEnabled(true);
+ redoItem.setText(undo.getRedoPresentationName());
+ putValue(Action.NAME, undo.getRedoPresentationName());
+ } else {
+ this.setEnabled(false);
+ redoItem.setEnabled(false);
+ redoItem.setText("Redo");
+ putValue(Action.NAME, "Redo");
+ }
+ }
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Gets the current sketch object.
+ */
+ public Sketch getSketch() {
+ return sketch;
+ }
+
+
+ /**
+ * Get the JEditTextArea object for use (not recommended). This should only
+ * be used in obscure cases that really need to hack the internals of the
+ * JEditTextArea. Most tools should only interface via the get/set functions
+ * found in this class. This will maintain compatibility with future releases,
+ * which will not use JEditTextArea.
+ */
+ public JEditTextArea getTextArea() {
+ return textarea;
+ }
+
+
+ /**
+ * Get the contents of the current buffer. Used by the Sketch class.
+ */
+ public String getText() {
+ return textarea.getText();
+ }
+
+
+ /**
+ * Get a range of text from the current buffer.
+ */
+ public String getText(int start, int stop) {
+ return textarea.getText(start, stop - start);
+ }
+
+
+ /**
+ * Replace the entire contents of the front-most tab.
+ */
+ public void setText(String what) {
+ startCompoundEdit();
+ textarea.setText(what);
+ stopCompoundEdit();
+ }
+
+
+ public void insertText(String what) {
+ startCompoundEdit();
+ int caret = getCaretOffset();
+ setSelection(caret, caret);
+ textarea.setSelectedText(what);
+ stopCompoundEdit();
+ }
+
+
+ /**
+ * Called to update the text but not switch to a different set of code
+ * (which would affect the undo manager).
+ */
+// public void setText2(String what, int start, int stop) {
+// beginCompoundEdit();
+// textarea.setText(what);
+// endCompoundEdit();
+//
+// // make sure that a tool isn't asking for a bad location
+// start = Math.max(0, Math.min(start, textarea.getDocumentLength()));
+// stop = Math.max(0, Math.min(start, textarea.getDocumentLength()));
+// textarea.select(start, stop);
+//
+// textarea.requestFocus(); // get the caret blinking
+// }
+
+
+ public String getSelectedText() {
+ return textarea.getSelectedText();
+ }
+
+
+ public void setSelectedText(String what) {
+ textarea.setSelectedText(what);
+ }
+
+
+ public void setSelection(int start, int stop) {
+ // make sure that a tool isn't asking for a bad location
+ start = PApplet.constrain(start, 0, textarea.getDocumentLength());
+ stop = PApplet.constrain(stop, 0, textarea.getDocumentLength());
+
+ textarea.select(start, stop);
+ }
+
+
+ /**
+ * Get the position (character offset) of the caret. With text selected,
+ * this will be the last character actually selected, no matter the direction
+ * of the selection. That is, if the user clicks and drags to select lines
+ * 7 up to 4, then the caret position will be somewhere on line four.
+ */
+ public int getCaretOffset() {
+ return textarea.getCaretPosition();
+ }
+
+
+ /**
+ * True if some text is currently selected.
+ */
+ public boolean isSelectionActive() {
+ return textarea.isSelectionActive();
+ }
+
+
+ /**
+ * Get the beginning point of the current selection.
+ */
+ public int getSelectionStart() {
+ return textarea.getSelectionStart();
+ }
+
+
+ /**
+ * Get the end point of the current selection.
+ */
+ public int getSelectionStop() {
+ return textarea.getSelectionStop();
+ }
+
+
+ /**
+ * Get text for a specified line.
+ */
+ public String getLineText(int line) {
+ return textarea.getLineText(line);
+ }
+
+
+ /**
+ * Replace the text on a specified line.
+ */
+ public void setLineText(int line, String what) {
+ startCompoundEdit();
+ textarea.select(getLineStartOffset(line), getLineStopOffset(line));
+ textarea.setSelectedText(what);
+ stopCompoundEdit();
+ }
+
+
+ /**
+ * Get character offset for the start of a given line of text.
+ */
+ public int getLineStartOffset(int line) {
+ return textarea.getLineStartOffset(line);
+ }
+
+
+ /**
+ * Get character offset for end of a given line of text.
+ */
+ public int getLineStopOffset(int line) {
+ return textarea.getLineStopOffset(line);
+ }
+
+
+ /**
+ * Get the number of lines in the currently displayed buffer.
+ */
+ public int getLineCount() {
+ return textarea.getLineCount();
+ }
+
+
+ /**
+ * Use before a manipulating text to group editing operations together as a
+ * single undo. Use stopCompoundEdit() once finished.
+ */
+ public void startCompoundEdit() {
+ compoundEdit = new CompoundEdit();
+ }
+
+
+ /**
+ * Use with startCompoundEdit() to group edit operations in a single undo.
+ */
+ public void stopCompoundEdit() {
+ compoundEdit.end();
+ undo.addEdit(compoundEdit);
+ undoAction.updateUndoState();
+ redoAction.updateRedoState();
+ compoundEdit = null;
+ }
+
+
+ public int getScrollPosition() {
+ return textarea.getScrollPosition();
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Switch between tabs, this swaps out the Document object
+ * that's currently being manipulated.
+ */
+ protected void setCode(SketchCode code) {
+ SyntaxDocument document = (SyntaxDocument) code.getDocument();
+
+ if (document == null) { // this document not yet inited
+ document = new SyntaxDocument();
+ code.setDocument(document);
+
+ // turn on syntax highlighting
+ document.setTokenMarker(new PdeKeywords());
+
+ // insert the program text into the document object
+ try {
+ document.insertString(0, code.getProgram(), null);
+ } catch (BadLocationException bl) {
+ bl.printStackTrace();
+ }
+
+ // set up this guy's own undo manager
+// code.undo = new UndoManager();
+
+ // connect the undo listener to the editor
+ document.addUndoableEditListener(new UndoableEditListener() {
+ public void undoableEditHappened(UndoableEditEvent e) {
+ if (compoundEdit != null) {
+ compoundEdit.addEdit(e.getEdit());
+
+ } else if (undo != null) {
+ undo.addEdit(e.getEdit());
+ undoAction.updateUndoState();
+ redoAction.updateRedoState();
+ }
+ }
+ });
+ }
+
+ // update the document object that's in use
+ textarea.setDocument(document,
+ code.getSelectionStart(), code.getSelectionStop(),
+ code.getScrollPosition());
+
+ textarea.requestFocus(); // get the caret blinking
+
+ this.undo = code.getUndo();
+ undoAction.updateUndoState();
+ redoAction.updateRedoState();
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Implements Edit → Cut.
+ */
+ public void handleCut() {
+ textarea.cut();
+ sketch.setModified(true);
+ }
+
+
+ /**
+ * Implements Edit → Copy.
+ */
+ public void handleCopy() {
+ textarea.copy();
+ }
+
+
+ protected void handleDiscourseCopy() {
+ new DiscourseFormat(Editor.this, false).show();
+ }
+
+
+ protected void handleHTMLCopy() {
+ new DiscourseFormat(Editor.this, true).show();
+ }
+
+
+ /**
+ * Implements Edit → Paste.
+ */
+ public void handlePaste() {
+ textarea.paste();
+ sketch.setModified(true);
+ }
+
+
+ /**
+ * Implements Edit → Select All.
+ */
+ public void handleSelectAll() {
+ textarea.selectAll();
+ }
+
+
+ protected void handleCommentUncomment() {
+ startCompoundEdit();
+
+ int startLine = textarea.getSelectionStartLine();
+ int stopLine = textarea.getSelectionStopLine();
+
+ int lastLineStart = textarea.getLineStartOffset(stopLine);
+ int selectionStop = textarea.getSelectionStop();
+ // If the selection ends at the beginning of the last line,
+ // then don't (un)comment that line.
+ if (selectionStop == lastLineStart) {
+ // Though if there's no selection, don't do that
+ if (textarea.isSelectionActive()) {
+ stopLine--;
+ }
+ }
+
+ // If the text is empty, ignore the user.
+ // Also ensure that all lines are commented (not just the first)
+ // when determining whether to comment or uncomment.
+ int length = textarea.getDocumentLength();
+ boolean commented = true;
+ for (int i = startLine; commented && (i <= stopLine); i++) {
+ int pos = textarea.getLineStartOffset(i);
+ if (pos + 2 > length) {
+ commented = false;
+ } else {
+ // Check the first two characters to see if it's already a comment.
+ String begin = textarea.getText(pos, 2);
+ //System.out.println("begin is '" + begin + "'");
+ commented = begin.equals("//");
+ }
+ }
+
+ for (int line = startLine; line <= stopLine; line++) {
+ int location = textarea.getLineStartOffset(line);
+ if (commented) {
+ // remove a comment
+ textarea.select(location, location+2);
+ if (textarea.getSelectedText().equals("//")) {
+ textarea.setSelectedText("");
+ }
+ } else {
+ // add a comment
+ textarea.select(location, location);
+ textarea.setSelectedText("//");
+ }
+ }
+ // Subtract one from the end, otherwise selects past the current line.
+ // (Which causes subsequent calls to keep expanding the selection)
+ textarea.select(textarea.getLineStartOffset(startLine),
+ textarea.getLineStopOffset(stopLine) - 1);
+ stopCompoundEdit();
+ }
+
+
+ protected void handleIndentOutdent(boolean indent) {
+ int tabSize = Preferences.getInteger("editor.tabs.size");
+ String tabString = Editor.EMPTY.substring(0, tabSize);
+
+ startCompoundEdit();
+
+ int startLine = textarea.getSelectionStartLine();
+ int stopLine = textarea.getSelectionStopLine();
+
+ // If the selection ends at the beginning of the last line,
+ // then don't (un)comment that line.
+ int lastLineStart = textarea.getLineStartOffset(stopLine);
+ int selectionStop = textarea.getSelectionStop();
+ if (selectionStop == lastLineStart) {
+ // Though if there's no selection, don't do that
+ if (textarea.isSelectionActive()) {
+ stopLine--;
+ }
+ }
+
+ for (int line = startLine; line <= stopLine; line++) {
+ int location = textarea.getLineStartOffset(line);
+
+ if (indent) {
+ textarea.select(location, location);
+ textarea.setSelectedText(tabString);
+
+ } else { // outdent
+ textarea.select(location, location + tabSize);
+ // Don't eat code if it's not indented
+ if (textarea.getSelectedText().equals(tabString)) {
+ textarea.setSelectedText("");
+ }
+ }
+ }
+ // Subtract one from the end, otherwise selects past the current line.
+ // (Which causes subsequent calls to keep expanding the selection)
+ textarea.select(textarea.getLineStartOffset(startLine),
+ textarea.getLineStopOffset(stopLine) - 1);
+ stopCompoundEdit();
+ }
+
+
+ protected void handleFindReference() {
+ String text = textarea.getSelectedText().trim();
+
+ if (text.length() == 0) {
+ statusNotice("First select a word to find in the reference.");
+
+ } else {
+ String referenceFile = PdeKeywords.getReference(text);
+ //System.out.println("reference file is " + referenceFile);
+ if (referenceFile == null) {
+ statusNotice("No reference available for \"" + text + "\"");
+ } else {
+ Base.showReference(referenceFile + ".html");
+ }
+ }
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Implements Sketch → Run.
+ * @param present Set true to run in full screen (present mode).
+ */
+ public void handleRun(boolean present) {
+ internalCloseRunner();
+ running = true;
+ toolbar.activate(EditorToolbar.RUN);
+ statusNotice("Compiling...");
+
+ // do this to advance/clear the terminal window / dos prompt / etc
+ for (int i = 0; i < 10; i++) System.out.println();
+
+ // clear the console on each run, unless the user doesn't want to
+ if (Preferences.getBoolean("console.auto_clear")) {
+ console.clear();
+ }
+
+ presenting = present;
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ sketch.compile(new Target(
+ Base.getHardwarePath() + File.separator + "cores",
+ Preferences.get("boards." + Preferences.get("board") + ".build.core")));
+ statusNotice("Done compiling.");
+ } catch (RunnerException e) {
+ //statusError("Error compiling...");
+ statusError(e);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ toolbar.deactivate(EditorToolbar.RUN);
+ }
+ });
+ }
+
+
+ /**
+ * Set the location of the sketch run window. Used by Runner to update the
+ * Editor about window drag events while the sketch is running.
+ */
+ public void setSketchLocation(Point p) {
+ sketchWindowLocation = p;
+ }
+
+
+ /**
+ * Get the last location of the sketch's run window. Used by Runner to make
+ * the window show up in the same location as when it was last closed.
+ */
+ public Point getSketchLocation() {
+ return sketchWindowLocation;
+ }
+
+
+ /**
+ * Implements Sketch → Stop, or pressing Stop on the toolbar.
+ */
+ public void handleStop() { // called by menu or buttons
+ toolbar.activate(EditorToolbar.STOP);
+
+ internalCloseRunner();
+
+ toolbar.deactivate(EditorToolbar.RUN);
+ toolbar.deactivate(EditorToolbar.STOP);
+
+ // focus the PDE again after quitting presentation mode [toxi 030903]
+ toFront();
+ }
+
+
+ /**
+ * Called by Runner to notify that the sketch has stopped running.
+ * Tools should not call this function, use handleStop() instead.
+ */
+ public void internalRunnerClosed() {
+ running = false;
+ toolbar.deactivate(EditorToolbar.RUN);
+ }
+
+
+ /**
+ * Handle internal shutdown of the runner.
+ */
+ public void internalCloseRunner() {
+ running = false;
+
+ try {
+ if (runtime != null) {
+ runtime.close(); // kills the window
+ runtime = null; // will this help?
+ }
+ } catch (Exception e) { }
+
+ sketch.cleanup();
+ }
+
+
+ /**
+ * Check if the sketch is modified and ask user to save changes.
+ * Immediately should be set true when quitting, or when the save should
+ * not happen asynchronously. Come to think of it, that's always now?
+ * @return false if canceling the close/quit operation
+ */
+ protected boolean checkModified(boolean immediately) {
+ if (!sketch.isModified()) return true;
+
+ String prompt = "Save changes to " + sketch.getName() + "? ";
+
+ if (!Base.isMacOS()) {
+ int result =
+ JOptionPane.showConfirmDialog(this, prompt, "Close",
+ JOptionPane.YES_NO_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (result == JOptionPane.YES_OPTION) {
+ return handleSave(immediately);
+
+ } else if (result == JOptionPane.NO_OPTION) {
+ return true; // ok to continue
+
+ } else if (result == JOptionPane.CANCEL_OPTION) {
+ return false;
+ } else {
+ throw new IllegalStateException();
+ }
+
+ } else {
+ // This code is disabled unless Java 1.5 is being used on Mac OS X
+ // because of a Java bug that prevents the initial value of the
+ // dialog from being set properly (at least on my MacBook Pro).
+ // The bug causes the "Don't Save" option to be the highlighted,
+ // blinking, default. This sucks. But I'll tell you what doesn't
+ // suck--workarounds for the Mac and Apple's snobby attitude about it!
+ // I think it's nifty that they treat their developers like dirt.
+
+ // Pane formatting adapted from the quaqua guide
+ // http://www.randelshofer.ch/quaqua/guide/joptionpane.html
+ JOptionPane pane =
+ new JOptionPane(" " +
+ " " +
+ "Do you want to save changes to this sketch " +
+ " before closing?" +
+ "
If you don't save, your changes will be lost.",
+ JOptionPane.QUESTION_MESSAGE);
+
+ String[] options = new String[] {
+ "Save", "Cancel", "Don't Save"
+ };
+ pane.setOptions(options);
+
+ // highlight the safest option ala apple hig
+ pane.setInitialValue(options[0]);
+
+ // on macosx, setting the destructive property places this option
+ // away from the others at the lefthand side
+ pane.putClientProperty("Quaqua.OptionPane.destructiveOption",
+ new Integer(2));
+
+ JDialog dialog = pane.createDialog(this, null);
+ dialog.setVisible(true);
+
+ Object result = pane.getValue();
+ if (result == options[0]) { // save (and close/quit)
+ return handleSave(immediately);
+
+ } else if (result == options[2]) { // don't save (still close/quit)
+ return true;
+
+ } else { // cancel?
+ return false;
+ }
+ }
+ }
+
+
+ /**
+ * Open a sketch from a particular path, but don't check to save changes.
+ * Used by Sketch.saveAs() to re-open a sketch after the "Save As"
+ */
+ protected void handleOpenUnchecked(String path, int codeIndex,
+ int selStart, int selStop, int scrollPos) {
+ internalCloseRunner();
+ handleOpenInternal(path);
+ // Replacing a document that may be untitled. If this is an actual
+ // untitled document, then editor.untitled will be set by Base.
+ untitled = false;
+
+ sketch.setCurrentCode(codeIndex);
+ textarea.select(selStart, selStop);
+ textarea.setScrollPosition(scrollPos);
+ }
+
+
+ /**
+ * Second stage of open, occurs after having checked to see if the
+ * modifications (if any) to the previous sketch need to be saved.
+ */
+ protected boolean handleOpenInternal(String path) {
+ // check to make sure that this .pde file is
+ // in a folder of the same name
+ File file = new File(path);
+ File parentFile = new File(file.getParent());
+ String parentName = parentFile.getName();
+ String pdeName = parentName + ".pde";
+ File altFile = new File(file.getParent(), pdeName);
+
+ if (pdeName.equals(file.getName())) {
+ // no beef with this guy
+
+ } else if (altFile.exists()) {
+ // user selected a .java from the same sketch,
+ // but open the .pde instead
+ path = altFile.getAbsolutePath();
+ //System.out.println("found alt file in same folder");
+
+ } else if (!path.endsWith(".pde")) {
+ Base.showWarning("Bad file selected",
+ "Processing can only open its own sketches\n" +
+ "and other files ending in .pde", null);
+ return false;
+
+ } else {
+ String properParent =
+ file.getName().substring(0, file.getName().length() - 4);
+
+ Object[] options = { "OK", "Cancel" };
+ String prompt =
+ "The file \"" + file.getName() + "\" needs to be inside\n" +
+ "a sketch folder named \"" + properParent + "\".\n" +
+ "Create this folder, move the file, and continue?";
+
+ int result = JOptionPane.showOptionDialog(this,
+ prompt,
+ "Moving",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+
+ if (result == JOptionPane.YES_OPTION) {
+ // create properly named folder
+ File properFolder = new File(file.getParent(), properParent);
+ if (properFolder.exists()) {
+ Base.showWarning("Error",
+ "A folder named \"" + properParent + "\" " +
+ "already exists. Can't open sketch.", null);
+ return false;
+ }
+ if (!properFolder.mkdirs()) {
+ //throw new IOException("Couldn't create sketch folder");
+ Base.showWarning("Error",
+ "Could not create the sketch folder.", null);
+ return false;
+ }
+ // copy the sketch inside
+ File properPdeFile = new File(properFolder, file.getName());
+ File origPdeFile = new File(path);
+ try {
+ Base.copyFile(origPdeFile, properPdeFile);
+ } catch (IOException e) {
+ Base.showWarning("Error", "Could not copy to a proper location.", e);
+ return false;
+ }
+
+ // remove the original file, so user doesn't get confused
+ origPdeFile.delete();
+
+ // update with the new path
+ path = properPdeFile.getAbsolutePath();
+
+ } else if (result == JOptionPane.NO_OPTION) {
+ return false;
+ }
+ }
+
+ try {
+ sketch = new Sketch(this, path);
+ } catch (IOException e) {
+ Base.showWarning("Error", "Could not create the sketch.", e);
+ return false;
+ }
+ header.rebuild();
+ // Set the title of the window to "sketch_070752a - Processing 0126"
+ setTitle(sketch.getName() + " | Arduino " + Base.VERSION_NAME);
+ // Disable untitled setting from previous document, if any
+ untitled = false;
+
+ // Store information on who's open and running
+ // (in case there's a crash or something that can't be recovered)
+ base.storeSketches();
+ Preferences.save();
+
+ // opening was successful
+ return true;
+
+// } catch (Exception e) {
+// e.printStackTrace();
+// statusError(e);
+// return false;
+// }
+ }
+
+
+ /**
+ * Actually handle the save command. If 'immediately' is set to false,
+ * this will happen in another thread so that the message area
+ * will update and the save button will stay highlighted while the
+ * save is happening. If 'immediately' is true, then it will happen
+ * immediately. This is used during a quit, because invokeLater()
+ * won't run properly while a quit is happening. This fixes
+ * Bug 276.
+ */
+ public boolean handleSave(boolean immediately) {
+ //stopRunner();
+ handleStop(); // 0136
+
+ if (untitled) {
+ return handleSaveAs();
+ // need to get the name, user might also cancel here
+
+ } else if (immediately) {
+ handleSave2();
+
+ } else {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ handleSave2();
+ }
+ });
+ }
+ return true;
+ }
+
+
+ protected void handleSave2() {
+ toolbar.activate(EditorToolbar.SAVE);
+ statusNotice("Saving...");
+ try {
+ if (sketch.save()) {
+ statusNotice("Done Saving.");
+ } else {
+ statusEmpty();
+ }
+ // rebuild sketch menu in case a save-as was forced
+ // Disabling this for 0125, instead rebuild the menu inside
+ // the Save As method of the Sketch object, since that's the
+ // only one who knows whether something was renamed.
+ //sketchbook.rebuildMenus();
+ //sketchbook.rebuildMenusAsync();
+
+ } catch (Exception e) {
+ // show the error as a message in the window
+ statusError(e);
+
+ // zero out the current action,
+ // so that checkModified2 will just do nothing
+ //checkModifiedMode = 0;
+ // this is used when another operation calls a save
+ }
+ //toolbar.clear();
+ toolbar.deactivate(EditorToolbar.SAVE);
+ }
+
+
+ public boolean handleSaveAs() {
+ //stopRunner(); // formerly from 0135
+ handleStop();
+
+ toolbar.activate(EditorToolbar.SAVE);
+
+ //SwingUtilities.invokeLater(new Runnable() {
+ //public void run() {
+ statusNotice("Saving...");
+ try {
+ if (sketch.saveAs()) {
+ statusNotice("Done Saving.");
+ // Disabling this for 0125, instead rebuild the menu inside
+ // the Save As method of the Sketch object, since that's the
+ // only one who knows whether something was renamed.
+ //sketchbook.rebuildMenusAsync();
+ } else {
+ statusNotice("Save Canceled.");
+ return false;
+ }
+ } catch (Exception e) {
+ // show the error as a message in the window
+ statusError(e);
+
+ } finally {
+ // make sure the toolbar button deactivates
+ toolbar.deactivate(EditorToolbar.SAVE);
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Called by Sketch → Export.
+ * Handles calling the export() function on sketch, and
+ * queues all the gui status stuff that comes along with it.
+ *
+ * Made synchronized to (hopefully) avoid problems of people
+ * hitting export twice, quickly, and horking things up.
+ */
+ /**
+ * Handles calling the export() function on sketch, and
+ * queues all the gui status stuff that comes along with it.
+ *
+ * Made synchronized to (hopefully) avoid problems of people
+ * hitting export twice, quickly, and horking things up.
+ */
+ synchronized public void handleExport() {
+ //if (!handleExportCheckModified()) return;
+ toolbar.activate(EditorToolbar.EXPORT);
+
+ console.clear();
+ statusNotice("Uploading to I/O Board...");
+
+ //SwingUtilities.invokeLater(new Runnable() {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ try {
+ serialMonitor.closeSerialPort();
+ serialMonitor.setVisible(false);
+
+ uploading = true;
+
+ boolean success = sketch.exportApplet(new Target(
+ Base.getHardwarePath() + File.separator + "cores",
+ Preferences.get("boards." + Preferences.get("board") + ".build.core")));
+ if (success) {
+ statusNotice("Done uploading.");
+ } else {
+ // error message will already be visible
+ }
+ } catch (RunnerException e) {
+ //statusError("Error during upload.");
+ //e.printStackTrace();
+ statusError(e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ uploading = false;
+ //toolbar.clear();
+ toolbar.deactivate(EditorToolbar.EXPORT);
+ }});
+ t.start();
+ }
+
+
+ /**
+ * Checks to see if the sketch has been modified, and if so,
+ * asks the user to save the sketch or cancel the export.
+ * This prevents issues where an incomplete version of the sketch
+ * would be exported, and is a fix for
+ * Bug 157
+ */
+ protected boolean handleExportCheckModified() {
+ if (!sketch.isModified()) return true;
+
+ Object[] options = { "OK", "Cancel" };
+ int result = JOptionPane.showOptionDialog(this,
+ "Save changes before export?",
+ "Save",
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+
+ if (result == JOptionPane.OK_OPTION) {
+ handleSave(true);
+
+ } else {
+ // why it's not CANCEL_OPTION is beyond me (at least on the mac)
+ // but f-- it.. let's get this shite done..
+ //} else if (result == JOptionPane.CANCEL_OPTION) {
+ statusNotice("Export canceled, changes must first be saved.");
+ //toolbar.clear();
+ return false;
+ }
+ return true;
+ }
+
+
+ public void handleSerial() {
+ if (uploading) return;
+ serialMonitor.setVisible(true);
+ serialMonitor.openSerialPort();
+ }
+
+
+ protected void handleBurnBootloader(final String programmer) {
+ console.clear();
+ statusNotice("Burning bootloader to I/O Board (this may take a minute)...");
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ Uploader uploader = new AvrdudeUploader();
+ if (uploader.burnBootloader(programmer)) {
+ statusNotice("Done burning bootloader.");
+ } else {
+ statusError("Error while burning bootloader.");
+ // error message will already be visible
+ }
+ } catch (RunnerException e) {
+ statusError("Error while burning bootloader.");
+ e.printStackTrace();
+ //statusError(e);
+ } catch (Exception e) {
+ statusError("Error while burning bootloader.");
+ e.printStackTrace();
+ }
+ }});
+ }
+
+
+ /**
+ * Handler for File → Page Setup.
+ */
+ public void handlePageSetup() {
+ //printerJob = null;
+ if (printerJob == null) {
+ printerJob = PrinterJob.getPrinterJob();
+ }
+ if (pageFormat == null) {
+ pageFormat = printerJob.defaultPage();
+ }
+ pageFormat = printerJob.pageDialog(pageFormat);
+ //System.out.println("page format is " + pageFormat);
+ }
+
+
+ /**
+ * Handler for File → Print.
+ */
+ public void handlePrint() {
+ statusNotice("Printing...");
+ //printerJob = null;
+ if (printerJob == null) {
+ printerJob = PrinterJob.getPrinterJob();
+ }
+ if (pageFormat != null) {
+ //System.out.println("setting page format " + pageFormat);
+ printerJob.setPrintable(textarea.getPainter(), pageFormat);
+ } else {
+ printerJob.setPrintable(textarea.getPainter());
+ }
+ // set the name of the job to the code name
+ printerJob.setJobName(sketch.getCurrentCode().getPrettyName());
+
+ if (printerJob.printDialog()) {
+ try {
+ printerJob.print();
+ statusNotice("Done printing.");
+
+ } catch (PrinterException pe) {
+ statusError("Error while printing.");
+ pe.printStackTrace();
+ }
+ } else {
+ statusNotice("Printing canceled.");
+ }
+ //printerJob = null; // clear this out?
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Show an error int the status bar.
+ */
+ public void statusError(String what) {
+ status.error(what);
+ //new Exception("deactivating RUN").printStackTrace();
+ toolbar.deactivate(EditorToolbar.RUN);
+ }
+
+
+ /**
+ * Show an exception in the editor status bar.
+ */
+ public void statusError(Exception e) {
+ e.printStackTrace();
+// if (e == null) {
+// System.err.println("Editor.statusError() was passed a null exception.");
+// return;
+// }
+
+ if (e instanceof RunnerException) {
+ RunnerException re = (RunnerException) e;
+ if (re.hasCodeIndex()) {
+ sketch.setCurrentCode(re.getCodeIndex());
+ }
+ if (re.hasCodeLine()) {
+ int line = re.getCodeLine();
+ // subtract one from the end so that the \n ain't included
+ if (line >= textarea.getLineCount()) {
+ // The error is at the end of this current chunk of code,
+ // so the last line needs to be selected.
+ line = textarea.getLineCount() - 1;
+ if (textarea.getLineText(line).length() == 0) {
+ // The last line may be zero length, meaning nothing to select.
+ // If so, back up one more line.
+ line--;
+ }
+ }
+ if (line < 0 || line >= textarea.getLineCount()) {
+ System.err.println("Bad error line: " + line);
+ } else {
+ textarea.select(textarea.getLineStartOffset(line),
+ textarea.getLineStopOffset(line) - 1);
+ }
+ }
+ }
+
+ // Since this will catch all Exception types, spend some time figuring
+ // out which kind and try to give a better error message to the user.
+ String mess = e.getMessage();
+ if (mess != null) {
+ String javaLang = "java.lang.";
+ if (mess.indexOf(javaLang) == 0) {
+ mess = mess.substring(javaLang.length());
+ }
+ String rxString = "RuntimeException: ";
+ if (mess.indexOf(rxString) == 0) {
+ mess = mess.substring(rxString.length());
+ }
+ statusError(mess);
+ }
+ e.printStackTrace();
+ }
+
+
+ /**
+ * Show a notice message in the editor status bar.
+ */
+ public void statusNotice(String msg) {
+ status.notice(msg);
+ }
+
+
+ /**
+ * Clear the status area.
+ */
+ public void statusEmpty() {
+ statusNotice(EMPTY);
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ /**
+ * Returns the edit popup menu.
+ */
+ class TextAreaPopup extends JPopupMenu {
+ //String currentDir = System.getProperty("user.dir");
+ String referenceFile = null;
+
+ JMenuItem cutItem;
+ JMenuItem copyItem;
+ JMenuItem discourseItem;
+ JMenuItem referenceItem;
+
+
+ public TextAreaPopup() {
+ JMenuItem item;
+
+ cutItem = new JMenuItem("Cut");
+ cutItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleCut();
+ }
+ });
+ this.add(cutItem);
+
+ copyItem = new JMenuItem("Copy");
+ copyItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleCopy();
+ }
+ });
+ this.add(copyItem);
+
+ discourseItem = new JMenuItem("Copy for Forum");
+ discourseItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleDiscourseCopy();
+ }
+ });
+ this.add(discourseItem);
+
+ discourseItem = new JMenuItem("Copy as HTML");
+ discourseItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleHTMLCopy();
+ }
+ });
+ this.add(discourseItem);
+
+ item = new JMenuItem("Paste");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handlePaste();
+ }
+ });
+ this.add(item);
+
+ item = new JMenuItem("Select All");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleSelectAll();
+ }
+ });
+ this.add(item);
+
+ this.addSeparator();
+
+ item = new JMenuItem("Comment/Uncomment");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleCommentUncomment();
+ }
+ });
+ this.add(item);
+
+ item = new JMenuItem("Increase Indent");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleIndentOutdent(true);
+ }
+ });
+ this.add(item);
+
+ item = new JMenuItem("Decrease Indent");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleIndentOutdent(false);
+ }
+ });
+ this.add(item);
+
+ this.addSeparator();
+
+ referenceItem = new JMenuItem("Find in Reference");
+ referenceItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ handleFindReference();
+ }
+ });
+ this.add(referenceItem);
+ }
+
+ // if no text is selected, disable copy and cut menu items
+ public void show(Component component, int x, int y) {
+ if (textarea.isSelectionActive()) {
+ cutItem.setEnabled(true);
+ copyItem.setEnabled(true);
+ discourseItem.setEnabled(true);
+
+ String sel = textarea.getSelectedText().trim();
+ referenceFile = PdeKeywords.getReference(sel);
+ referenceItem.setEnabled(referenceFile != null);
+
+ } else {
+ cutItem.setEnabled(false);
+ copyItem.setEnabled(false);
+ discourseItem.setEnabled(false);
+ referenceItem.setEnabled(false);
+ }
+ super.show(component, x, y);
+ }
+ }
+}
+
diff --git a/app/EditorConsole.java b/app/src/processing/app/EditorConsole.java
similarity index 76%
rename from app/EditorConsole.java
rename to app/src/processing/app/EditorConsole.java
index 27a5abaee..e8dc578f1 100644
--- a/app/EditorConsole.java
+++ b/app/src/processing/app/EditorConsole.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2004-05 Ben Fry and Casey Reas
+ 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
@@ -30,6 +30,7 @@ import javax.swing.*;
import javax.swing.text.*;
import java.util.*;
+
/**
* Message console that sits below the editing area.
*
@@ -48,15 +49,18 @@ public class EditorConsole extends JScrollPane {
boolean cerror;
- //int maxCharCount;
int maxLineCount;
static File errFile;
static File outFile;
static File tempFolder;
- static PrintStream systemOut;
- static PrintStream systemErr;
+ // 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;
@@ -64,6 +68,8 @@ public class EditorConsole extends JScrollPane {
static OutputStream stdoutFile;
static OutputStream stderrFile;
+ static EditorConsole currentConsole;
+
public EditorConsole(Editor editor) {
this.editor = editor;
@@ -80,10 +86,10 @@ public class EditorConsole extends JScrollPane {
consoleDoc.setParagraphAttributes(0, 0, standard, true);
// build styles for different types of console output
- Color bgColor = Preferences.getColor("console.color");
- Color fgColorOut = Preferences.getColor("console.output.color");
- Color fgColorErr = Preferences.getColor("console.error.color");
- Font font = Preferences.getFont("console.font");
+ 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);
@@ -119,32 +125,32 @@ public class EditorConsole extends JScrollPane {
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);
- //outFile.deleteOnExit();
}
String errFileName = Preferences.get("console.error.file");
if (errFileName != null) {
errFile = new File(tempFolder, errFileName);
stderrFile = new FileOutputStream(errFile);
- //errFile.deleteOnExit();
}
} 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(this, false, stdoutFile));
- consoleErr =
- new PrintStream(new EditorConsoleStream(this, true, stderrFile));
-
+ consoleOut = new PrintStream(new EditorConsoleStream(false));
+ consoleErr = new PrintStream(new EditorConsoleStream(true));
+
if (Preferences.getBoolean("console")) {
try {
System.setOut(consoleOut);
@@ -176,6 +182,11 @@ public class EditorConsole extends JScrollPane {
}).start();
}
+
+ static public void setEditor(Editor editor) {
+ currentConsole = editor.console;
+ }
+
/**
* Close the streams so that the temporary files can be deleted.
@@ -229,8 +240,10 @@ public class EditorConsole extends JScrollPane {
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) {
@@ -242,14 +255,14 @@ public class EditorConsole extends JScrollPane {
}
}
- // to console display
+ // to console display
appendText(what, err);
// moved down here since something is punting
}
/**
- * append a piece of text to the console.
+ * Append a piece of text to the console.
*
* Swing components are NOT thread-safe, and since the MessageSiphon
* instantiates new threads, and in those callbacks, they often print
@@ -264,6 +277,7 @@ public class EditorConsole extends JScrollPane {
consoleDoc.appendString(txt, e ? errStyle : stdStyle);
}
+
public void clear() {
try {
consoleDoc.remove(0, consoleDoc.getLength());
@@ -272,68 +286,96 @@ public class EditorConsole extends JScrollPane {
// 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;
+ }
-class EditorConsoleStream extends OutputStream {
- EditorConsole parent;
- boolean err; // whether stderr or stdout
- byte single[] = new byte[1];
- OutputStream echo;
+ public void close() { }
- public EditorConsoleStream(EditorConsole parent,
- boolean err, OutputStream echo) {
- this.parent = parent;
- this.err = err;
- this.echo = echo;
- }
+ public void flush() { }
- public void close() { }
+ 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);
+// }
+// }
- public void flush() { }
-
- public void write(byte b[]) { // appears never to be used
- parent.write(b, 0, b.length, err);
- if (echo != null) {
- try {
- echo.write(b); //, 0, b.length);
- echo.flush();
- } catch (IOException e) {
- e.printStackTrace();
- echo = null;
+ 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) {
- parent.write(b, offset, length, err);
- if (echo != null) {
- try {
- echo.write(b, offset, length);
- 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;
- parent.write(single, 0, 1, err);
- if (echo != null) {
- try {
- echo.write(b);
- 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
diff --git a/app/EditorHeader.java b/app/src/processing/app/EditorHeader.java
similarity index 69%
rename from app/EditorHeader.java
rename to app/src/processing/app/EditorHeader.java
index e4ca49b4e..1dc7d4422 100644
--- a/app/EditorHeader.java
+++ b/app/src/processing/app/EditorHeader.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2004-05 Ben Fry and Casey Reas
+ 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
@@ -25,10 +25,8 @@ package processing.app;
import java.awt.*;
import java.awt.event.*;
-import java.io.*;
import javax.swing.*;
-import javax.swing.event.*;
/**
@@ -50,8 +48,6 @@ public class EditorHeader extends JComponent {
JMenu menu;
JPopupMenu popup;
- JMenuItem hideItem;
-
int menuLeft;
int menuRight;
@@ -69,7 +65,7 @@ public class EditorHeader extends JComponent {
static final int PIECE_WIDTH = 4;
- Image[][] pieces;
+ static Image[][] pieces;
//
@@ -81,24 +77,23 @@ public class EditorHeader extends JComponent {
public EditorHeader(Editor eddie) {
this.editor = eddie; // weird name for listener
- pieces = new Image[STATUS.length][WHERE.length];
- for (int i = 0; i < STATUS.length; i++) {
- for (int j = 0; j < WHERE.length; j++) {
- pieces[i][j] = Base.getImage("tab-" + STATUS[i] + "-" +
- WHERE[j] + ".gif", this);
+ 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 =
- //Preferences.getColor("header.bgcolor");
- // hardcoding new blue color scheme for consistency with images,
- // see EditorStatus.java for details.
- backgroundColor = new Color(0x21, 0x68, 0x86);
+ backgroundColor =
+ Theme.getColor("header.bgcolor");
textColor[SELECTED] =
- Preferences.getColor("header.text.selected.color");
+ Theme.getColor("header.text.selected.color");
textColor[UNSELECTED] =
- Preferences.getColor("header.text.unselected.color");
+ Theme.getColor("header.text.unselected.color");
}
addMouseListener(new MouseAdapter() {
@@ -110,9 +105,10 @@ public class EditorHeader extends JComponent {
popup.show(EditorHeader.this, x, y);
} else {
- for (int i = 0; i < editor.sketch.codeCount; i++) {
+ Sketch sketch = editor.getSketch();
+ for (int i = 0; i < sketch.getCodeCount(); i++) {
if ((x > tabLeft[i]) && (x < tabRight[i])) {
- editor.sketch.setCurrent(i);
+ sketch.setCurrentCode(i);
repaint();
}
}
@@ -125,7 +121,7 @@ public class EditorHeader extends JComponent {
public void paintComponent(Graphics screen) {
if (screen == null) return;
- Sketch sketch = editor.sketch;
+ Sketch sketch = editor.getSketch();
if (sketch == null) return; // ??
Dimension size = getSize();
@@ -140,7 +136,6 @@ public class EditorHeader extends JComponent {
// who cares, just resize
sizeW = size.width;
sizeH = size.height;
- //userLeft = 0; // reset
}
}
@@ -154,7 +149,7 @@ public class EditorHeader extends JComponent {
Graphics g = offscreen.getGraphics();
if (font == null) {
- font = Preferences.getFont("header.text.font");
+ font = Theme.getFont("header.text.font");
}
g.setFont(font); // need to set this each time through
metrics = g.getFontMetrics();
@@ -169,28 +164,22 @@ public class EditorHeader extends JComponent {
g.setColor(backgroundColor);
g.fillRect(0, 0, imageW, imageH);
- if ((tabLeft == null) ||
- (tabLeft.length < sketch.codeCount)) {
- tabLeft = new int[sketch.codeCount];
- tabRight = new int[sketch.codeCount];
+ int codeCount = sketch.getCodeCount();
+ if ((tabLeft == null) || (tabLeft.length < codeCount)) {
+ tabLeft = new int[codeCount];
+ tabRight = new int[codeCount];
}
- // disable hide on the first tab
- hideItem.setEnabled(sketch.current != sketch.code[0]);
-
- //int x = 0; //Preferences.GUI_SMALL;
- //int x = (Base.platform == Base.MACOSX) ? 0 : 1;
int x = 6; // offset from left edge of the component
- for (int i = 0; i < sketch.codeCount; i++) {
- SketchCode code = sketch.code[i];
+ for (int i = 0; i < sketch.getCodeCount(); i++) {
+ SketchCode code = sketch.getCode(i);
- String codeName = (code.flavor == Sketch.PDE) ?
- code.name : code.file.getName();
+ 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.modified ? " \u00A7" : " ");
+ String text = " " + codeName + (code.isModified() ? " \u00A7" : " ");
- //int textWidth = metrics.stringWidth(text);
Graphics2D g2 = (Graphics2D) g;
int textWidth = (int)
font.getStringBounds(text, g2.getFontRenderContext()).getWidth();
@@ -198,7 +187,7 @@ public class EditorHeader extends JComponent {
int pieceCount = 2 + (textWidth / PIECE_WIDTH);
int pieceWidth = pieceCount * PIECE_WIDTH;
- int state = (code == sketch.current) ? SELECTED : UNSELECTED;
+ int state = (code == sketch.getCurrentCode()) ? SELECTED : UNSELECTED;
g.drawImage(pieces[state][LEFT], x, 0, null);
x += PIECE_WIDTH;
@@ -237,6 +226,7 @@ public class EditorHeader extends JComponent {
//System.out.println("rebuilding editor header");
rebuildMenu();
repaint();
+ Toolkit.getDefaultToolkit().sync();
}
@@ -297,10 +287,11 @@ public class EditorHeader extends JComponent {
menu.addSeparator();
*/
- item = new JMenuItem("New Tab");
+ //item = new JMenuItem("New Tab");
+ item = Editor.newJMenuItemShift("New Tab", 'N');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- editor.sketch.newCode();
+ editor.getSketch().handleNewCode();
}
});
menu.add(item);
@@ -308,10 +299,13 @@ public class EditorHeader extends JComponent {
item = new JMenuItem("Rename");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- editor.sketch.renameCode();
+ 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);
@@ -319,59 +313,19 @@ public class EditorHeader extends JComponent {
item = new JMenuItem("Delete");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- editor.sketch.deleteCode();
+ editor.getSketch().handleDeleteCode();
}
});
menu.add(item);
- item = new JMenuItem("Hide");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- editor.sketch.hideCode();
- }
- });
- menu.add(item);
- hideItem = item;
-
- JMenu unhide = new JMenu("Unhide");
- ActionListener unhideListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- String which = (String) e.getActionCommand();
- editor.sketch.unhideCode(which);
- rebuildMenu();
- }
- };
- Sketch sketch = editor.sketch;
- if (sketch != null) {
- for (int i = 0; i < sketch.hiddenCount; i++) {
- item = new JMenuItem(sketch.hidden[i].name +
- Sketch.flavorExtensionsShown[sketch.hidden[i].flavor]);
- item.setActionCommand(sketch.hidden[i].name +
- Sketch.flavorExtensionsShown[sketch.hidden[i].flavor]);
- item.addActionListener(unhideListener);
- unhide.add(item);
- }
- }
- if (unhide.getItemCount() == 0) {
- unhide.setEnabled(false);
- }
-
- menu.add(unhide);
menu.addSeparator();
// KeyEvent.VK_LEFT and VK_RIGHT will make Windows beep
- int ctrlAlt = ActionEvent.ALT_MASK |
- Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-
- //item = Editor.newJMenuItem("Previous Tab", '[', true);
item = new JMenuItem("Previous Tab");
- //int shortcut = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- KeyStroke ctrlAltLeft = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAlt);
+ KeyStroke ctrlAltLeft =
+ KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Editor.SHORTCUT_ALT_KEY_MASK);
item.setAccelerator(ctrlAltLeft);
- //int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- //KeyStroke tabby = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, modifiers);
-
// this didn't want to work consistently
/*
item.addActionListener(new ActionListener() {
@@ -382,9 +336,9 @@ public class EditorHeader extends JComponent {
*/
menu.add(item);
- //item = Editor.newJMenuItem("Next Tab", ']', true);
item = new JMenuItem("Next Tab");
- KeyStroke ctrlAltRight = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAlt);
+ KeyStroke ctrlAltRight =
+ KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Editor.SHORTCUT_ALT_KEY_MASK);
item.setAccelerator(ctrlAltRight);
/*
item.addActionListener(new ActionListener() {
@@ -395,17 +349,17 @@ public class EditorHeader extends JComponent {
*/
menu.add(item);
+ Sketch sketch = editor.getSketch();
if (sketch != null) {
menu.addSeparator();
ActionListener jumpListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
- editor.sketch.setCurrent(e.getActionCommand());
+ editor.getSketch().setCurrentCode(e.getActionCommand());
}
};
- for (int i = 0; i < sketch.codeCount; i++) {
- item = new JMenuItem(sketch.code[i].name +
- Sketch.flavorExtensionsShown[sketch.code[i].flavor]);
+ for (SketchCode code : sketch.getCode()) {
+ item = new JMenuItem(code.getPrettyName());
item.addActionListener(jumpListener);
menu.add(item);
}
@@ -417,10 +371,12 @@ public class EditorHeader extends JComponent {
repaint();
}
+
public Dimension getPreferredSize() {
return getMinimumSize();
}
+
public Dimension getMinimumSize() {
if (Base.isMacOS()) {
return new Dimension(300, Preferences.GRID_SIZE);
@@ -428,6 +384,7 @@ public class EditorHeader extends JComponent {
return new Dimension(300, Preferences.GRID_SIZE - 1);
}
+
public Dimension getMaximumSize() {
if (Base.isMacOS()) {
return new Dimension(3000, Preferences.GRID_SIZE);
diff --git a/app/EditorLineStatus.java b/app/src/processing/app/EditorLineStatus.java
similarity index 80%
rename from app/EditorLineStatus.java
rename to app/src/processing/app/EditorLineStatus.java
index 7547390ea..f28175ff0 100644
--- a/app/EditorLineStatus.java
+++ b/app/src/processing/app/EditorLineStatus.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2005 Ben Fry and Casey Reas
+ 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
@@ -25,10 +25,7 @@ package processing.app;
import processing.app.syntax.*;
import java.awt.*;
-import java.awt.event.*;
-
import javax.swing.*;
-import javax.swing.event.*;
/**
@@ -52,16 +49,13 @@ public class EditorLineStatus extends JComponent {
this.textarea = textarea;
textarea.editorLineStatus = this;
- // hardcoding new blue color scheme for consistency with images,
- // see EditorStatus.java for details.
- //background = Preferences.getColor("linestatus.bgcolor");
- background = new Color(0x04, 0x4F, 0x6F);
- font = Preferences.getFont("linestatus.font");
- foreground = Preferences.getColor("linestatus.color");
- high = Preferences.getInteger("linestatus.height");
+ 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.getImage("resize.gif", this);
+ resize = Base.getThemeImage("resize.gif", this);
}
//linestatus.bgcolor = #000000
//linestatus.font = SansSerif,plain,10
diff --git a/app/EditorListener.java b/app/src/processing/app/EditorListener.java
similarity index 83%
rename from app/EditorListener.java
rename to app/src/processing/app/EditorListener.java
index b8b9e791c..ffd05b022 100644
--- a/app/EditorListener.java
+++ b/app/src/processing/app/EditorListener.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2004-05 Ben Fry and Casey Reas
+ 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
@@ -28,10 +28,6 @@ import processing.app.syntax.*;
import java.awt.*;
import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.text.*;
-import javax.swing.event.*;
-
/**
* Filters key events for tab expansion/indent/etc.
@@ -47,18 +43,18 @@ import javax.swing.event.*;
* smarter parser/formatter, rather than continuing to hack this class.
*/
public class EditorListener {
- Editor editor;
- JEditTextArea textarea;
+ private Editor editor;
+ private JEditTextArea textarea;
- boolean externalEditor;
- boolean tabsExpand;
- boolean tabsIndent;
- int tabSize;
- String tabString;
- boolean autoIndent;
+ private boolean externalEditor;
+ private boolean tabsExpand;
+ private boolean tabsIndent;
+ private int tabSize;
+ private String tabString;
+ private boolean autoIndent;
- int selectionStart, selectionEnd;
- int position;
+// 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 |
@@ -97,6 +93,7 @@ public class EditorListener {
* 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
@@ -106,15 +103,17 @@ public class EditorListener {
char c = event.getKeyChar();
int code = event.getKeyCode();
- //System.out.println(c + " " + code + " " + event);
+ //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) {
- editor.sketch.prevCode();
+ sketch.handlePrevCode();
return true;
} else if (code == KeyEvent.VK_RIGHT) {
- editor.sketch.nextCode();
+ sketch.handleNextCode();
return true;
}
}
@@ -125,10 +124,10 @@ public class EditorListener {
}
// TODO i don't like these accessors. clean em up later.
- if (!editor.sketch.modified) {
+ if (!editor.getSketch().isModified()) {
if ((code == KeyEvent.VK_BACK_SPACE) || (code == KeyEvent.VK_TAB) ||
(code == KeyEvent.VK_ENTER) || ((c >= 32) && (c < 128))) {
- editor.sketch.setModified(true);
+ sketch.setModified(true);
}
}
@@ -209,8 +208,12 @@ public class EditorListener {
switch ((int) c) {
- case 9:
- if (tabsExpand) { // expand tabs
+ 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;
@@ -371,11 +374,11 @@ public class EditorListener {
if (spaceCount < 0) {
// for rev 0122, actually delete extra space
//textarea.setSelectionStart(origIndex + 1);
- textarea.setSelectionEnd(textarea.getSelectionEnd() - spaceCount);
+ textarea.setSelectionEnd(textarea.getSelectionStop() - spaceCount);
textarea.setSelectedText("\n");
} else {
- String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
- textarea.setSelectedText(insertion);
+ String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
+ textarea.setSelectedText(insertion);
}
// not gonna bother handling more than one brace
@@ -394,19 +397,22 @@ public class EditorListener {
}
}
}
-
- // mark this event as already handled
- event.consume();
- return true;
+ } 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));
}
- break;
+ // 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.getSelectionEnd()) {
+ if (textarea.getSelectionStart() != textarea.getSelectionStop()) {
textarea.setSelectedText("");
}
@@ -435,59 +441,9 @@ public class EditorListener {
if (!finished) return false; // brace with no start
int lineStartIndex = index;
- /*
- // 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.
- index = prevCharIndex;
- int braceDepth = 1;
- 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++;
- index--;
- } else if (contents[index] == '{') {
- braceDepth--;
- if (braceDepth == 0) {
- finished = true;
- } // otherwise just teasing, keep going..
- } else {
- index--;
- }
- }
- // never found a proper brace, be safe and don't do anything
- if (!finished) return false;
-
- // check how many spaces on the line with the matching open brace
- int pairedSpaceCount = calcSpaceCount(index, contents);
- //System.out.println(pairedSpaceCount);
- */
int pairedSpaceCount = calcBraceIndent(prevCharIndex, contents); //, 1);
if (pairedSpaceCount == -1) return false;
- /*
- // now walk forward and figure out how many spaces there are
- while ((index < contents.length) && (index >= 0) &&
- (contents[index++] == ' ')) {
- spaceCount++;
- }
- */
-
- // number of spaces found on this line
- //int newSpaceCount = Math.max(0, spaceCount - tabSize);
- // number of spaces on this current line
- //int spaceCount = calcSpaces(caretIndex, contents);
- //System.out.println("spaces is " + spaceCount);
- //String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
- //int differential = newSpaceCount - spaceCount;
- //System.out.println("diff is " + differential);
- //int newStart = textarea.getSelectionStart() + differential;
- //textarea.setSelectionStart(newStart);
- //textarea.setSelectedText("}");
textarea.setSelectionStart(lineStartIndex);
textarea.setSelectedText(Editor.EMPTY.substring(0, pairedSpaceCount));
@@ -501,32 +457,19 @@ public class EditorListener {
}
- /** Cmd-Shift or Ctrl-Shift depending on the platform */
- //static final int CMD_SHIFT = ActionEvent.SHIFT_MASK |
- // Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- /** ctrl-alt on windows and linux, cmd-alt on mac os x */
- //static final int CTRL_ALT = ActionEvent.ALT_MASK |
- // Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-
- /*
public boolean keyTyped(KeyEvent event) {
char c = event.getKeyChar();
- int code = event.getKeyCode();
- if ((event.getModifiers() & CMD_ALT) == CMD_ALT) {
- if (code == KeyEvent.VK_LEFT) {
- //if (c == '[') {
- editor.sketch.prevCode();
- return true;
- } else if (code == KeyEvent.VK_RIGHT) {
- //} else if (c == ']') {
- editor.sketch.nextCode();
+ 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;
}
- */
+
/**
@@ -535,7 +478,7 @@ public class EditorListener {
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;
+ /*int spaceCount = 0;*/
boolean finished = false;
while ((index != -1) && (!finished)) {
if ((contents[index] == 10) ||
diff --git a/app/src/processing/app/EditorStatus.java b/app/src/processing/app/EditorStatus.java
new file mode 100644
index 000000000..a7035ab7c
--- /dev/null
+++ b/app/src/processing/app/EditorStatus.java
@@ -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();
+ }
+ }
+ }
+}
diff --git a/app/EditorButtons.java b/app/src/processing/app/EditorToolbar.java
similarity index 72%
rename from app/EditorButtons.java
rename to app/src/processing/app/EditorToolbar.java
index 781902606..43347c516 100644
--- a/app/EditorButtons.java
+++ b/app/src/processing/app/EditorToolbar.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2004-05 Ben Fry and Casey Reas
+ 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
@@ -25,8 +25,6 @@ package processing.app;
import java.awt.*;
import java.awt.event.*;
-import java.awt.font.*;
-import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;
@@ -34,18 +32,19 @@ import javax.swing.event.*;
/**
* run/stop/etc buttons for the ide
*/
-public class EditorButtons extends JComponent implements MouseInputListener {
+public class EditorToolbar extends JComponent implements MouseInputListener {
static final String title[] = {
- "Verify", "Stop", "New", "Open", "Save", "Upload to I/O Board", "Serial Monitor"
+ "Verify", "Stop", "New", "Open", "Save", "Upload", "Serial Monitor"
};
static final int BUTTON_COUNT = title.length;
- /// height, width of the toolbar buttons
+ /** Width of each toolbar button. */
static final int BUTTON_WIDTH = 27;
+ /** Height of each toolbar button. */
static final int BUTTON_HEIGHT = 32;
- /// amount of space between groups of buttons on the toolbar
- static final int BUTTON_GAP = 15;
+ /** 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;
@@ -54,6 +53,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
static final int OPEN = 3;
static final int SAVE = 4;
static final int EXPORT = 5;
+
static final int SERIAL = 6;
static final int INACTIVE = 0;
@@ -61,7 +61,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
static final int ACTIVE = 2;
Editor editor;
- //boolean disableRun;
+ //boolean disableRun; // this was for library
//Label status;
Image offscreen;
@@ -69,14 +69,15 @@ public class EditorButtons extends JComponent implements MouseInputListener {
Color bgcolor;
- Image buttons;
- Image inactive[];
- Image rollover[];
- Image active[];
+ 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];
@@ -89,12 +90,15 @@ public class EditorButtons extends JComponent implements MouseInputListener {
String status;
Font statusFont;
Color statusColor;
- //int statusY;
- public EditorButtons(Editor editor) {
+ public EditorToolbar(Editor editor, JMenu menu) {
this.editor = editor;
- buttons = Base.getImage("buttons.gif", this);
+ this.menu = menu;
+
+ if (buttons == null) {
+ buttons = Base.getThemeImage("buttons.gif", this);
+ }
buttonCount = 0;
which = new int[BUTTON_COUNT];
@@ -110,17 +114,12 @@ public class EditorButtons extends JComponent implements MouseInputListener {
currentRollover = -1;
- // hardcoding new blue color scheme for consistency with images,
- // see EditorStatus.java for details.
- //bgcolor = Preferences.getColor("buttons.bgcolor");
- bgcolor = new Color(0x04, 0x4F, 0x6F);
+ bgcolor = Theme.getColor("buttons.bgcolor");
status = "";
- statusFont = Preferences.getFont("buttons.status.font");
- statusColor = Preferences.getColor("buttons.status.color");
-
- //statusY = (BUTTON_COUNT + 1) * BUTTON_HEIGHT;
+ statusFont = Theme.getFont("buttons.status.font");
+ statusColor = Theme.getColor("buttons.status.color");
addMouseListener(this);
addMouseMotionListener(this);
@@ -128,6 +127,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
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];
@@ -148,13 +148,21 @@ public class EditorButtons extends JComponent implements MouseInputListener {
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)) {
@@ -162,16 +170,10 @@ public class EditorButtons extends JComponent implements MouseInputListener {
width = size.width;
height = size.height;
- y1 = 0;
- y2 = BUTTON_HEIGHT;
-
- x1 = new int[buttonCount];
- x2 = new int[buttonCount];
-
int offsetX = 3;
for (int i = 0; i < buttonCount; i++) {
x1[i] = offsetX;
- if (i == 2) x1[i] += BUTTON_GAP;
+ if (i == 2 || i == 6) x1[i] += BUTTON_GAP;
x2[i] = x1[i] + BUTTON_WIDTH;
offsetX = x2[i];
}
@@ -197,7 +199,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
*/
//int statusY = (BUTTON_HEIGHT + statusFont.getAscent()) / 2;
int statusY = (BUTTON_HEIGHT + g.getFontMetrics().getAscent()) / 2;
- g.drawString(status, buttonCount * BUTTON_WIDTH + 2 * BUTTON_GAP, statusY);
+ g.drawString(status, buttonCount * BUTTON_WIDTH + 3 * BUTTON_GAP, statusY);
screen.drawImage(offscreen, 0, 0, null);
}
@@ -275,7 +277,12 @@ public class EditorButtons extends JComponent implements MouseInputListener {
message(title[which[slot]]);
break;
}
- if (updateAfter) repaint(); // changed for swing from update();
+ 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();
+ }
}
@@ -308,57 +315,24 @@ public class EditorButtons extends JComponent implements MouseInputListener {
///if (sel == -1) return false;
if (sel == -1) return;
currentRollover = -1;
- //int currentSelection = sel;
- //if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
- // moving the handling of this over into the editor
- //setState(sel, ACTIVE, true);
- //}
- //if (currentSelection == OPEN) {
- //switch (currentSelection) {
switch (sel) {
case RUN:
- //if (!disableRun) {
editor.handleRun(e.isShiftDown());
- //}
break;
case STOP:
- //if (!disableRun) {
- //setState(RUN, INACTIVE, true);
- //setInactive();
editor.handleStop();
- //}
break;
case OPEN:
- if (popup == null) {
- //popup = new JPopupMenu();
- popup = editor.sketchbook.getPopupMenu();
- // no events properly being fired, so nevermind
- /*
- popup.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- System.out.println("action " + e);
- }
- });
- popup.addComponentListener(new ComponentAdapter() {
- public void componentHidden(ComponentEvent e) {
- System.out.println("hidden " + e);
- }
- });
- */
- add(popup);
- }
- //activate(OPEN);
- //SwingUtilities.invokeLater(new Runnable() {
- //public void run() {
- popup.show(EditorButtons.this, x, y);
- //}});
+ popup = menu.getPopupMenu();
+ popup.show(EditorToolbar.this, x, y);
break;
case NEW:
- editor.handleNew(e.isShiftDown());
+ //editor.base.handleNew(e.isShiftDown());
+ editor.base.handleNewReplace();
break;
case SAVE:
@@ -372,7 +346,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
case SERIAL:
editor.handleSerial();
break;
- }
+ }
}
@@ -382,24 +356,10 @@ public class EditorButtons extends JComponent implements MouseInputListener {
public void mouseReleased(MouseEvent e) {
/*
switch (currentSelection) {
- case RUN:
- if (!disableRun) {
- editor.handleRun(e.isShiftDown());
- }
- break;
- case STOP:
- if (!disableRun) {
- setState(RUN, INACTIVE, true);
- editor.handleStop();
- }
+ case OPEN:
+ setState(OPEN, INACTIVE, true);
break;
-
- case OPEN: setState(OPEN, INACTIVE, true); break;
- case NEW: editor.handleNew(e.isShiftDown()); break;
- case SAVE: editor.handleSave(); break;
- case EXPORT: editor.handleExport(); break;
- case SERIAL: editor.handleSerial(); break;
}
currentSelection = -1;
*/
@@ -419,39 +379,47 @@ public class EditorButtons extends JComponent implements MouseInputListener {
}
*/
-
- public void running(boolean yesno) {
- setState(RUN, yesno ? ACTIVE : INACTIVE, 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;
-
- // 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 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) {
@@ -467,13 +435,12 @@ public class EditorButtons extends JComponent implements MouseInputListener {
public Dimension getPreferredSize() {
- return new Dimension((BUTTON_COUNT + 1)*BUTTON_WIDTH, BUTTON_HEIGHT);
- //return new Dimension(BUTTON_WIDTH, (BUTTON_COUNT + 1)*BUTTON_HEIGHT);
+ return getMinimumSize();
}
public Dimension getMinimumSize() {
- return getPreferredSize();
+ return new Dimension((BUTTON_COUNT + 1)*BUTTON_WIDTH, BUTTON_HEIGHT);
}
diff --git a/app/FindReplace.java b/app/src/processing/app/FindReplace.java
similarity index 94%
rename from app/FindReplace.java
rename to app/src/processing/app/FindReplace.java
index 1dccf214d..112eca3ad 100644
--- a/app/FindReplace.java
+++ b/app/src/processing/app/FindReplace.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2004-05 Ben Fry and Casey Reas
+ 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
@@ -206,12 +206,13 @@ public class FindReplace extends JFrame implements ActionListener {
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();
+ /*boolean ok =*/ findField.requestFocusInWindow();
//System.out.println("got " + ok);
findField.selectAll();
}
@@ -225,7 +226,7 @@ public class FindReplace extends JFrame implements ActionListener {
replaceString = replaceField.getText();
// this object should eventually become dereferenced
- hide();
+ setVisible(false);
}
@@ -273,7 +274,7 @@ public class FindReplace extends JFrame implements ActionListener {
// this will catch "find next" being called when no search yet
if (search.length() == 0) return;
- String text = editor.textarea.getText();
+ String text = editor.getText();
if (ignoreCase) {
search = search.toLowerCase();
@@ -281,7 +282,7 @@ public class FindReplace extends JFrame implements ActionListener {
}
//int selectionStart = editor.textarea.getSelectionStart();
- int selectionEnd = editor.textarea.getSelectionEnd();
+ int selectionEnd = editor.getSelectionStop();
int nextIndex = text.indexOf(search, selectionEnd);
if (nextIndex == -1) {
@@ -301,7 +302,7 @@ public class FindReplace extends JFrame implements ActionListener {
found = true;
replaceButton.setEnabled(true);
replaceFindButton.setEnabled(true);
- editor.textarea.select(nextIndex, nextIndex + search.length());
+ editor.setSelection(nextIndex, nextIndex + search.length());
}
@@ -314,7 +315,7 @@ public class FindReplace extends JFrame implements ActionListener {
// check to see if the document has wrapped around
// otherwise this will cause an infinite loop
- String sel = editor.textarea.getSelectedText();
+ String sel = editor.getSelectedText();
if (sel.equals(replaceField.getText())) {
found = false;
replaceButton.setEnabled(false);
@@ -322,10 +323,10 @@ public class FindReplace extends JFrame implements ActionListener {
return;
}
- editor.textarea.setSelectedText(replaceField.getText());
+ editor.setSelectedText(replaceField.getText());
//editor.setSketchModified(true);
//editor.sketch.setCurrentModified(true);
- editor.sketch.setModified(true);
+ editor.getSketch().setModified(true); // TODO is this necessary?
// don't allow a double replace
replaceButton.setEnabled(false);
@@ -339,7 +340,7 @@ public class FindReplace extends JFrame implements ActionListener {
*/
public void replaceAll() {
// move to the beginning
- editor.textarea.select(0, 0);
+ editor.setSelection(0, 0);
do {
find(false);
diff --git a/app/src/processing/app/Platform.java b/app/src/processing/app/Platform.java
new file mode 100644
index 000000000..28fe66c99
--- /dev/null
+++ b/app/src/processing/app/Platform.java
@@ -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, ".arduino");
+ 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);
+ }
+}
\ No newline at end of file
diff --git a/app/Preferences.java b/app/src/processing/app/Preferences.java
similarity index 60%
rename from app/Preferences.java
rename to app/src/processing/app/Preferences.java
index 67ce3e442..623ff807f 100644
--- a/app/Preferences.java
+++ b/app/src/processing/app/Preferences.java
@@ -1,11 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
- Part of the Arduino project - http://arduino.berlios.de
+ Part of the Processing project - http://processing.org
- Based on the Processing project - http://www.processing.org
-
- Copyright (c) 2004-05 Ben Fry and Casey Reas
+ 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
@@ -25,28 +23,17 @@
package processing.app;
-import processing.app.syntax.*;
-
import java.awt.*;
import java.awt.event.*;
import java.io.*;
-import java.net.*;
import java.util.*;
-import java.util.zip.*;
import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.event.*;
-import javax.swing.filechooser.*;
-import javax.swing.text.*;
-import javax.swing.undo.*;
-import processing.core.PApplet;
+import processing.app.syntax.*;
+import processing.core.*;
-// TODO change this to use the Java Preferences API
-// http://www.onjava.com/pub/a/onjava/synd/2001/10/17/j2se.html
-// http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter10/Preferences.html
/**
@@ -56,9 +43,25 @@ import processing.core.PApplet;
* properties files are iso8859-1, which is highly likely to
* be a problem when trying to save sketch folders and locations.
*
- * This is very poorly put together, that the prefs panel and the
- * actual prefs i/o is part of the same code. But there hasn't yet
- * been a compelling reason to bother with the separation.
+ * 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.
+ *
+ * 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.
+ *
+ * Would also be possible to change this to use the Java Preferences API.
+ * Some useful articles
+ * here and
+ * here.
+ * 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 {
@@ -69,9 +72,9 @@ public class Preferences {
// platform strings (used to get settings for specific platforms)
- static final String platforms[] = {
- "other", "windows", "macos9", "macosx", "linux"
- };
+ //static final String platforms[] = {
+ // "other", "windows", "macosx", "linux"
+ //};
// prompt text stuff
@@ -80,14 +83,13 @@ public class Preferences {
static final String PROMPT_NO = "No";
static final String PROMPT_CANCEL = "Cancel";
static final String PROMPT_OK = "OK";
- static final String PROMPT_SEND = "Send";
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 Linux needs 76, so 76 seems proper.
+ * Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper.
*/
- static public int BUTTON_WIDTH = 76;
+ static public int BUTTON_WIDTH = 80;
/**
* Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29,
@@ -119,119 +121,126 @@ public class Preferences {
// gui elements
- //JDialog dialog;
JFrame dialog;
int wide, high;
JTextField sketchbookLocationField;
JCheckBox exportSeparateBox;
- JCheckBox sketchPromptBox;
- JCheckBox sketchCleanBox;
+ 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
- // we have multiple preference files, one main one and a few subsidiary
- // ones with prefixes. the preferences from the main file go in table
- // and are saved back to the main file. the preferences from the
- // subsidiary files are stored in prefixes (which maps a prefix string to
- // a Hashtable mapping unprefixed keys to values) and are not saved.
- static Hashtable table = new Hashtable();
+
+ static Hashtable defaults;
+ static Hashtable table = new Hashtable();;
static Hashtable prefixes = new Hashtable();
static File preferencesFile;
- static public void init() {
+ static protected void init(String commandLinePrefs) {
// start by loading the defaults, in case something
// important was deleted from the user prefs
-
try {
- load(Base.getStream("preferences.txt"));
-
+ load(Base.getLibStream("preferences.txt"));
} catch (Exception e) {
Base.showError(null, "Could not read default settings.\n" +
- "You'll need to reinstall Arduino.", e);
+ "You'll need to reinstall Arduino.", e);
}
// check for platform-specific properties in the defaults
-
- String platformExtension = "." +
- platforms[processing.core.PApplet.platform];
- int extensionLength = platformExtension.length();
-
- Enumeration e = table.keys(); //properties.propertyNames();
+ 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(platformExtension)) {
+ if (key.endsWith(platformExt)) {
// this is a key specific to a particular platform
- String actualKey = key.substring(0, key.length() - extensionLength);
+ 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);
-
- // 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
-
+ // Load a prefs file if specified on the command line
+ if (commandLinePrefs != null) {
try {
- load(new FileInputStream(preferencesFile));
+ load(new FileInputStream(commandLinePrefs));
- } catch (Exception ex) {
- Base.showError("Error reading preferences",
- "Error reading the preferences file. " +
- "Please delete (or move)\n" +
- preferencesFile.getAbsolutePath() +
- " and restart Arduino.", ex);
+ } 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 Arduino.", 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);
+// }
}
try {
- load(new FileInputStream(new File(
- System.getProperty("user.dir") +
- File.separator + "hardware" +
- File.separator + "boards.txt")),
- "boards");
+ load(new FileInputStream(new File(Base.getHardwareFolder(), "boards.txt")),
+ "boards");
} catch (Exception ex) {
Base.showError("Error reading board definitions",
- "Error reading the board definitions file. " +
+ "Error reading the board definitions file (" +
+ new File(Base.getHardwareFolder(), "boards.txt").getAbsolutePath() + "). " +
"Please re-download or re-unzip Arduino.\n", ex);
}
try {
- load(new FileInputStream(new File(
- System.getProperty("user.dir") +
- File.separator + "hardware" +
- File.separator + "programmers.txt")),
+ load(new FileInputStream(new File(Base.getHardwareFolder(), "programmers.txt")),
"programmers");
} catch (Exception ex) {
Base.showError("Error reading programmers definitions",
"Error reading the programmers definitions file. " +
"Please re-download or re-unzip Arduino.\n", ex);
- }
+ }
}
@@ -251,31 +260,47 @@ public class Preferences {
int right = 0;
JLabel label;
- JButton button, button2;
- JComboBox combo;
- Dimension d, d2, d3;
- int h, v, vmax;
+ 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, d.height);
+ 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, d.height);
+ sketchCleanBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
+ */
// Sketchbook location:
@@ -349,12 +374,23 @@ public class Preferences {
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, d.height);
+ externalEditorBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
@@ -364,15 +400,43 @@ public class Preferences {
checkUpdatesBox = new JCheckBox("Check for updates on startup");
pain.add(checkUpdatesBox);
d = checkUpdatesBox.getPreferredSize();
- checkUpdatesBox.setBounds(left, top, d.width, d.height);
+ 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 Arduino");
+ 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);
@@ -446,12 +510,12 @@ public class Preferences {
}
};
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,
@@ -462,6 +526,7 @@ public class Preferences {
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))) {
@@ -503,7 +568,7 @@ public class Preferences {
/**
* Close the window after an OK or Cancel.
*/
- public void disposeFrame() {
+ protected void disposeFrame() {
dialog.dispose();
}
@@ -512,14 +577,39 @@ public class Preferences {
* 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.
*/
- public void applyFrame() {
+ protected void applyFrame() {
// put each of the settings into the table
- setBoolean("sketchbook.prompt", sketchPromptBox.isSelected());
- setBoolean("sketchbook.auto_clean", sketchCleanBox.isSelected());
- set("sketchbook.path", sketchbookLocationField.getText());
+ 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());
+ /*
+ // 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());
@@ -530,43 +620,72 @@ public class Preferences {
} 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();
}
- public void showFrame(Editor editor) {
+ protected void showFrame(Editor editor) {
this.editor = editor;
// set all settings entry boxes to their actual status
- 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"));
+ deletePreviousBox.
+ setSelected(getBoolean("export.delete_target_folder"));
- dialog.show();
+ //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"));
+
+ if (autoAssociateBox != null) {
+ autoAssociateBox.
+ setSelected(getBoolean("platform.auto_file_type_associations"));
+ }
+
+ if (menubarWorkaroundBox != null) {
+ menubarWorkaroundBox.
+ setSelected(!getBoolean("apple.laf.useScreenMenuBar"));
+ }
+
+ dialog.setVisible(true);
}
// .................................................................
- static public void load(InputStream input) throws IOException {
- load(input, null);
+
+ static protected void load(InputStream input) throws IOException {
+ load(input, table);
}
-
- static public void load(InputStream input, String prefix) throws IOException {
- BufferedReader reader =
- new BufferedReader(new InputStreamReader(input));
- Map table = Preferences.table;
-
- if (prefix != null) {
- table = new LinkedHashMap();
- prefixes.put(prefix, table);
- }
-
- //table = new Hashtable();
- String line = null;
- while ((line = reader.readLine()) != null) {
+
+ static protected void load(InputStream input, String prefix) throws IOException {
+ Map table = new LinkedHashMap();
+ prefixes.put(prefix, table);
+ load(input, table);
+ }
+
+ static protected void load(InputStream input, Map table) throws IOException {
+ String[] lines = PApplet.loadStrings(input); // Reads as UTF-8
+ for (String line : lines) {
if ((line.length() == 0) ||
(line.charAt(0) == '#')) continue;
@@ -578,86 +697,34 @@ public class Preferences {
table.put(key, value);
}
}
- reader.close();
}
// .................................................................
- static public void save() {
- try {
- FileOutputStream output = new FileOutputStream(preferencesFile);
- PrintWriter writer = new PrintWriter(new OutputStreamWriter(output));
+ 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;
- Enumeration e = table.keys(); //properties.propertyNames();
- while (e.hasMoreElements()) {
- String key = (String) e.nextElement();
- writer.println(key + "=" + ((String) table.get(key)));
- }
+ // Fix for 0163 to properly use Unicode when writing preferences.txt
+ PrintWriter writer = PApplet.createWriter(preferencesFile);
- writer.flush();
- writer.close();
-
- /*
- FileOutputStream output = null;
-
- if ((Base.platform == Base.MACOSX) ||
- (Base.platform == Base.MACOS9)) {
- output = new FileOutputStream("lib/preferences.txt");
-
- } else { // win95/98/ME doesn't set cwd properly
- URL url = getClass().getResource("buttons.gif");
- String urlstr = url.getFile();
- urlstr = urlstr.substring(0, urlstr.lastIndexOf("/") + 1) +
- ".properties";
- output = new FileOutputStream(URLDecoder.decode(urlstr));
- }
- */
-
- /*
- //base.storePreferences();
-
- Properties skprops = new Properties();
-
- //Rectangle window = Base.frame.getBounds();
- Rectangle window = editor.getBounds();
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
-
- skprops.put("last.window.x", String.valueOf(window.x));
- skprops.put("last.window.y", String.valueOf(window.y));
- skprops.put("last.window.w", String.valueOf(window.width));
- skprops.put("last.window.h", String.valueOf(window.height));
-
- skprops.put("last.screen.w", String.valueOf(screen.width));
- skprops.put("last.screen.h", String.valueOf(screen.height));
-
- skprops.put("last.sketch.name", sketchName);
- skprops.put("last.sketch.directory", sketchDir.getAbsolutePath());
- //skprops.put("user.name", userName);
-
- skprops.put("last.divider.location",
- String.valueOf(splitPane.getDividerLocation()));
-
- //
-
- skprops.put("editor.external", externalEditor ? "true" : "false");
-
- //skprops.put("serial.port", Preferences.get("serial.port", "unspecified"));
-
- // save() is deprecated, and didn't properly
- // throw exceptions when it wasn't working
- skprops.store(output, "Settings for arduino. " +
- "See lib/preferences.txt for defaults.");
-
- // need to close the stream.. didn't do this before
- skprops.close();
- */
-
- } catch (IOException ex) {
- Base.showWarning(null, "Error while saving the settings file", ex);
- //e.printStackTrace();
+ 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);
+// }
}
@@ -693,7 +760,8 @@ public class Preferences {
defaultValue : value;
*/
}
-
+
+
/**
* Get the top-level key prefixes defined in the subsidiary file loaded with
* the given prefix. For example, if the file contains:
@@ -716,8 +784,12 @@ public class Preferences {
}
+ static public String getDefault(String attribute) {
+ return (String) defaults.get(attribute);
+ }
+
+
static public void set(String attribute, String value) {
- //preferences.put(attribute, value);
table.put(attribute, value);
}
@@ -772,42 +844,63 @@ public class Preferences {
}
- static public Color getColor(String name /*, Color otherwise*/) {
- Color parsed = null;
- String s = get(name); //, null);
- //System.out.println(name + " = " + s);
+ static public Color getColor(String name) {
+ Color parsed = Color.GRAY; // set a default
+ 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) {
- }
+ parsed = new Color(Integer.parseInt(s.substring(1), 16));
+ } catch (Exception e) { }
}
- //if (parsed == null) return otherwise;
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));
+// 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 which /*, Font otherwise*/) {
- //System.out.println("getting font '" + which + "'");
- String str = get(which);
- //if (str == null) return otherwise; // ENABLE LATER
- StringTokenizer st = new StringTokenizer(str, ",");
- String fontname = st.nextToken();
- String fontstyle = st.nextToken();
- return new Font(fontname,
- ((fontstyle.indexOf("bold") != -1) ? Font.BOLD : 0) |
- ((fontstyle.indexOf("italic") != -1) ? Font.ITALIC : 0),
- Integer.parseInt(st.nextToken()));
+ 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;
}
@@ -818,7 +911,10 @@ public class Preferences {
String s = st.nextToken();
if (s.indexOf("#") == 0) s = s.substring(1);
- Color color = new Color(Integer.parseInt(s, 16));
+ 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);
@@ -828,66 +924,3 @@ public class Preferences {
return new SyntaxStyle(color, italic, bold);
}
}
-
-
- // Default serial port: [ COM1 + ]
-
- /*
- label = new JLabel("Default serial port:");
- pain.add(label);
- d = label.getPreferredSize();
-
- Vector list = buildPortList();
- combo = new JComboBox(list);
- pain.add(combo);
- d2 = combo.getPreferredSize();
-
- if (list.size() == 0) {
- label.setEnabled(false);
- combo.setEnabled(false);
-
- } else {
- String defaultName = Preferences.get("serial.port", "unspecified");
- combo.setSelectedItem(defaultName);
- }
-
- vmax = Math.max(d.height, d2.height);
- label.setBounds(left, top + (vmax-d.height)/2,
- d.width, d.height);
- h = left + d.width + BETWEEN;
- combo.setBounds(h, top + (vmax-d2.height)/2,
- d2.width, d2.height);
- right = Math.max(right, h + d2.width + BIG);
- top += vmax + BETWEEN;
- */
-
- // open the last-used sketch, etc
-
- //public void init() {
-
- //String what = path + File.separator + name + ".pde";
-
- ///String serialPort = skprops.getProperty("serial.port");
- //if (serialPort != null) {
- // properties.put("serial.port", serialPort);
- //}
-
- //boolean ee = new Boolean(skprops.getProperty("editor.external", "false")).booleanValue();
- //editor.setExternalEditor(ee);
-
- ///} catch (Exception e) {
- // this exception doesn't matter, it's just the normal course of things
- // the app reaches here when no sketch.properties file exists
- //e.printStackTrace();
-
- // indicator that this is the first time this feller has used p5
- //firstTime = true;
-
- // even if folder for 'default' user doesn't exist, or
- // sketchbook itself is missing, mkdirs() will make it happy
- //userName = "default";
-
- // doesn't exist, not available, make my own
- //skNew();
- //}
- //}
diff --git a/app/PresentMode.java b/app/src/processing/app/PresentMode.java
similarity index 96%
rename from app/PresentMode.java
rename to app/src/processing/app/PresentMode.java
index 5018efb83..63f4578d9 100644
--- a/app/PresentMode.java
+++ b/app/src/processing/app/PresentMode.java
@@ -1,9 +1,9 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
- Copyright (c) 2005- Ben Fry and Casey Reas
+ 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
diff --git a/app/Serial.java b/app/src/processing/app/Serial.java
similarity index 98%
rename from app/Serial.java
rename to app/src/processing/app/Serial.java
index 0baab4546..53f206544 100755
--- a/app/Serial.java
+++ b/app/src/processing/app/Serial.java
@@ -25,6 +25,8 @@
package processing.app;
//import processing.core.*;
+import processing.app.debug.MessageConsumer;
+
import gnu.io.*;
import java.io.*;
@@ -58,6 +60,8 @@ public class Serial implements SerialPortEventListener {
byte buffer[] = new byte[32768];
int bufferIndex;
int bufferLast;
+
+ MessageConsumer consumer;
public Serial(boolean monitor) throws SerialException {
this(Preferences.get("serial.port"),
@@ -189,6 +193,11 @@ public class Serial implements SerialPortEventListener {
}
port = null;
}
+
+
+ public void addListener(MessageConsumer consumer) {
+ this.consumer = consumer;
+ }
synchronized public void serialEvent(SerialPortEvent serialEvent) {
@@ -217,6 +226,8 @@ public class Serial implements SerialPortEventListener {
//buffer[bufferLast++] = (byte) input.read();
if(monitor == true)
System.out.print((char) input.read());
+ if (this.consumer != null)
+ this.consumer.message("" + (char) input.read());
/*
System.err.println(input.available() + " " +
diff --git a/app/SerialException.java b/app/src/processing/app/SerialException.java
similarity index 100%
rename from app/SerialException.java
rename to app/src/processing/app/SerialException.java
diff --git a/app/src/processing/app/SerialMonitor.java b/app/src/processing/app/SerialMonitor.java
new file mode 100644
index 000000000..ddcc4d792
--- /dev/null
+++ b/app/src/processing/app/SerialMonitor.java
@@ -0,0 +1,160 @@
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ 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.debug.MessageConsumer;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+
+public class SerialMonitor extends JFrame implements MessageConsumer {
+ private Serial serial;
+ private String port;
+ private JTextArea textArea;
+ private JTextField textField;
+ private JButton sendButton;
+ private JComboBox serialRates;
+ private JLabel statusLabel;
+ private int serialRate;
+
+ public SerialMonitor(String port) {
+ super(port);
+
+ this.port = port;
+
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ closeSerialPort();
+ }
+ });
+
+ // obvious, no?
+ KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE;
+ getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(wc, "close");
+ getRootPane().getActionMap().put("close", new AbstractAction() {
+ public void actionPerformed(ActionEvent e) {
+ closeSerialPort();
+ setVisible(false);
+ }});
+
+ getContentPane().setLayout(new BorderLayout());
+
+ Font font = Theme.getFont("console.font");
+
+ textArea = new JTextArea(16, 40);
+ textArea.setEditable(false);
+ textArea.setFont(font);
+
+ getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER);
+
+ JPanel pane = new JPanel(new BorderLayout(4, 0));
+ pane.setBorder(new EmptyBorder(4, 4, 4, 4));
+
+ textField = new JTextField(40);
+ textField.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ send(textField.getText());
+ textField.setText("");
+ }});
+
+ sendButton = new JButton("Send");
+ sendButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ send(textField.getText());
+ textField.setText("");
+ }});
+
+ pane.add(textField, BorderLayout.CENTER);
+ pane.add(sendButton, BorderLayout.EAST);
+
+ getContentPane().add(pane, BorderLayout.NORTH);
+
+ pane = new JPanel(new BorderLayout(4, 0));
+ pane.setBorder(new EmptyBorder(4, 4, 4, 4));
+
+ statusLabel = new JLabel();
+
+ pane.add(statusLabel, BorderLayout.CENTER);
+
+ String[] serialRateStrings = {
+ "300","1200","2400","4800","9600","14400",
+ "19200","28800","38400","57600","115200"
+ };
+
+ serialRates = new JComboBox();
+ for (int i = 0; i < serialRateStrings.length; i++)
+ serialRates.addItem(serialRateStrings[i] + " baud");
+
+ serialRate = Preferences.getInteger("serial.debug_rate");
+ serialRates.setSelectedItem(serialRate + " baud");
+ serialRates.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String wholeString = (String) serialRates.getSelectedItem();
+ String rateString = wholeString.substring(0, wholeString.indexOf(' '));
+ serialRate = Integer.parseInt(rateString);
+ Preferences.set("serial.debug_rate", rateString);
+ closeSerialPort();
+ openSerialPort();
+ }});
+
+ pane.add(serialRates, BorderLayout.EAST);
+
+ getContentPane().add(pane, BorderLayout.SOUTH);
+
+ pack();
+ }
+
+ private void send(String s) {
+ if (serial != null)
+ serial.write(s);
+ }
+
+ public void openSerialPort() {
+ if (serial != null) return;
+
+ try {
+ statusLabel.setText("opening...");
+ serial = new Serial(port, serialRate);
+ serial.addListener(this);
+ statusLabel.setText("");
+ } catch (SerialException e) {
+ statusLabel.setText(e.getMessage());
+ }
+ }
+
+ public void closeSerialPort() {
+ if (serial != null) {
+ statusLabel.setText("closing...");
+ textArea.setText("");
+ serial.dispose();
+ serial = null;
+ statusLabel.setText("");
+ }
+ }
+
+ public void message(final String s) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ textArea.append(s);
+ }});
+ }
+}
\ No newline at end of file
diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java
new file mode 100644
index 000000000..a07ddc250
--- /dev/null
+++ b/app/src/processing/app/Sketch.java
@@ -0,0 +1,2018 @@
+/* -*- 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.debug.AvrdudeUploader;
+import processing.app.debug.Compiler;
+import processing.app.debug.RunnerException;
+import processing.app.debug.Sizer;
+import processing.app.debug.Target;
+import processing.app.debug.Uploader;
+import processing.app.preproc.*;
+import processing.core.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.TitledBorder;
+
+
+/**
+ * Stores information about files in the current sketch
+ */
+public class Sketch {
+ static private File tempBuildFolder;
+
+ private Editor editor;
+
+ /** main pde file for this sketch. */
+ private File primaryFile;
+
+ /**
+ * Name of sketch, which is the name of main file
+ * (without .pde or .java extension)
+ */
+ private String name;
+
+ /** true if any of the files have been modified. */
+ private boolean modified;
+
+ /** folder that contains this sketch */
+ private File folder;
+
+ /** data folder location for this sketch (may not exist yet) */
+ private File dataFolder;
+
+ /** code folder location for this sketch (may not exist yet) */
+ private File codeFolder;
+
+ private SketchCode current;
+ private int currentIndex;
+ /**
+ * Number of sketchCode objects (tabs) in the current sketch. Note that this
+ * will be the same as code.length, because the getCode() method returns
+ * just the code[] array, rather than a copy of it, or an array that's been
+ * resized to just the relevant files themselves.
+ * http://dev.processing.org/bugs/show_bug.cgi?id=940
+ */
+ private int codeCount;
+ private SketchCode[] code;
+
+ /** Class name for the PApplet, as determined by the preprocessor. */
+ private String appletClassName;
+ /** Class path determined during build. */
+ private String classPath;
+
+ /**
+ * This is *not* the "Processing" libraries path, this is the Java libraries
+ * path, as in java.library.path=BlahBlah, which identifies search paths for
+ * DLLs or JNILIBs.
+ */
+ private String libraryPath;
+ private ArrayList importedLibraries;
+
+ /**
+ * path is location of the main .pde file, because this is also
+ * simplest to use when opening the file from the finder/explorer.
+ */
+ public Sketch(Editor editor, String path) throws IOException {
+ this.editor = editor;
+
+ primaryFile = new File(path);
+
+ // get the name of the sketch by chopping .pde or .java
+ // off of the main file name
+ String mainFilename = primaryFile.getName();
+ int suffixLength = getDefaultExtension().length() + 1;
+ name = mainFilename.substring(0, mainFilename.length() - suffixLength);
+
+ // lib/build must exist when the application is started
+ // it is added to the CLASSPATH by default, but if it doesn't
+ // exist when the application is started, then java will remove
+ // the entry from the CLASSPATH, causing Runner to fail.
+ //
+ /*
+ tempBuildFolder = new File(TEMP_BUILD_PATH);
+ if (!tempBuildFolder.exists()) {
+ tempBuildFolder.mkdirs();
+ Base.showError("Required folder missing",
+ "A required folder was missing from \n" +
+ "from your installation of Processing.\n" +
+ "It has now been replaced, please restart \n" +
+ "the application to complete the repair.", null);
+ }
+ */
+ tempBuildFolder = Base.getBuildFolder();
+ //Base.addBuildFolderToClassPath();
+
+ folder = new File(new File(path).getParent());
+ //System.out.println("sketch dir is " + folder);
+
+ load();
+ }
+
+
+ /**
+ * Build the list of files.
+ *
+ * Generally this is only done once, rather than
+ * each time a change is made, because otherwise it gets to be
+ * a nightmare to keep track of what files went where, because
+ * not all the data will be saved to disk.
+ *
+ * This also gets called when the main sketch file is renamed,
+ * because the sketch has to be reloaded from a different folder.
+ *
+ * Another exception is when an external editor is in use,
+ * in which case the load happens each time "run" is hit.
+ */
+ protected void load() {
+ codeFolder = new File(folder, "code");
+ dataFolder = new File(folder, "data");
+
+ // get list of files in the sketch folder
+ String list[] = folder.list();
+
+ // reset these because load() may be called after an
+ // external editor event. (fix for 0099)
+ codeCount = 0;
+
+ code = new SketchCode[list.length];
+
+ String[] extensions = getExtensions();
+
+ for (String filename : list) {
+ // Ignoring the dot prefix files is especially important to avoid files
+ // with the ._ prefix on Mac OS X. (You'll see this with Mac files on
+ // non-HFS drives, i.e. a thumb drive formatted FAT32.)
+ if (filename.startsWith(".")) continue;
+
+ // Don't let some wacko name a directory blah.pde or bling.java.
+ if (new File(folder, filename).isDirectory()) continue;
+
+ // figure out the name without any extension
+ String base = filename;
+ // now strip off the .pde and .java extensions
+ for (String extension : extensions) {
+ if (base.toLowerCase().endsWith("." + extension)) {
+ base = base.substring(0, base.length() - (extension.length() + 1));
+
+ // Don't allow people to use files with invalid names, since on load,
+ // it would be otherwise possible to sneak in nasty filenames. [0116]
+ if (Sketch.isSanitaryName(base)) {
+ code[codeCount++] =
+ new SketchCode(new File(folder, filename), extension);
+ }
+ }
+ }
+ }
+ // Remove any code that wasn't proper
+ code = (SketchCode[]) PApplet.subset(code, 0, codeCount);
+
+ // move the main class to the first tab
+ // start at 1, if it's at zero, don't bother
+ for (int i = 1; i < codeCount; i++) {
+ //if (code[i].file.getName().equals(mainFilename)) {
+ if (code[i].getFile().equals(primaryFile)) {
+ SketchCode temp = code[0];
+ code[0] = code[i];
+ code[i] = temp;
+ break;
+ }
+ }
+
+ // sort the entries at the top
+ sortCode();
+
+ // set the main file to be the current tab
+ if (editor != null) {
+ setCurrentCode(0);
+ }
+ }
+
+
+ protected void replaceCode(SketchCode newCode) {
+ for (int i = 0; i < codeCount; i++) {
+ if (code[i].getFileName().equals(newCode.getFileName())) {
+ code[i] = newCode;
+ break;
+ }
+ }
+ }
+
+
+ protected void insertCode(SketchCode newCode) {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ // add file to the code/codeCount list, resort the list
+ if (codeCount == code.length) {
+ code = (SketchCode[]) PApplet.append(code, newCode);
+ }
+ code[codeCount++] = newCode;
+ }
+
+
+ protected void sortCode() {
+ // cheap-ass sort of the rest of the files
+ // it's a dumb, slow sort, but there shouldn't be more than ~5 files
+ for (int i = 1; i < codeCount; i++) {
+ int who = i;
+ for (int j = i + 1; j < codeCount; j++) {
+ if (code[j].getFileName().compareTo(code[who].getFileName()) < 0) {
+ who = j; // this guy is earlier in the alphabet
+ }
+ }
+ if (who != i) { // swap with someone if changes made
+ SketchCode temp = code[who];
+ code[who] = code[i];
+ code[i] = temp;
+ }
+ }
+ }
+
+
+ boolean renamingCode;
+
+ /**
+ * Handler for the New Code menu option.
+ */
+ public void handleNewCode() {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ // if read-only, give an error
+ if (isReadOnly()) {
+ // if the files are read-only, need to first do a "save as".
+ Base.showMessage("Sketch is Read-Only",
+ "Some files are marked \"read-only\", so you'll\n" +
+ "need to re-save the sketch in another location,\n" +
+ "and try again.");
+ return;
+ }
+
+ renamingCode = false;
+ editor.status.edit("Name for new file:", "");
+ }
+
+
+ /**
+ * Handler for the Rename Code menu option.
+ */
+ public void handleRenameCode() {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ if (currentIndex == 0 && editor.untitled) {
+ Base.showMessage("Sketch is Untitled",
+ "How about saving the sketch first \n" +
+ "before trying to rename it?");
+ return;
+ }
+
+ // if read-only, give an error
+ if (isReadOnly()) {
+ // if the files are read-only, need to first do a "save as".
+ Base.showMessage("Sketch is Read-Only",
+ "Some files are marked \"read-only\", so you'll\n" +
+ "need to re-save the sketch in another location,\n" +
+ "and try again.");
+ return;
+ }
+
+ // ask for new name of file (internal to window)
+ // TODO maybe just popup a text area?
+ renamingCode = true;
+ String prompt = (currentIndex == 0) ?
+ "New name for sketch:" : "New name for file:";
+ String oldName = (current.isExtension("pde")) ?
+ current.getPrettyName() : current.getFileName();
+ editor.status.edit(prompt, oldName);
+ }
+
+
+ /**
+ * This is called upon return from entering a new file name.
+ * (that is, from either newCode or renameCode after the prompt)
+ * This code is almost identical for both the newCode and renameCode
+ * cases, so they're kept merged except for right in the middle
+ * where they diverge.
+ */
+ protected void nameCode(String newName) {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ // Add the extension here, this simplifies some of the logic below.
+ if (newName.indexOf('.') == -1) {
+ newName += "." + getDefaultExtension();
+ }
+
+ // if renaming to the same thing as before, just ignore.
+ // also ignoring case here, because i don't want to write
+ // a bunch of special stuff for each platform
+ // (osx is case insensitive but preserving, windows insensitive,
+ // *nix is sensitive and preserving.. argh)
+ if (renamingCode) {
+ if (newName.equalsIgnoreCase(current.getFileName())) {
+ // exit quietly for the 'rename' case.
+ // if it's a 'new' then an error will occur down below
+ return;
+ }
+ }
+
+ newName = newName.trim();
+ if (newName.equals("")) return;
+
+ int dot = newName.indexOf('.');
+ if (dot == 0) {
+ Base.showWarning("Problem with rename",
+ "The name cannot start with a period.", null);
+ return;
+ }
+
+ String newExtension = newName.substring(dot+1).toLowerCase();
+ if (!validExtension(newExtension)) {
+ Base.showWarning("Problem with rename",
+ "\"." + newExtension + "\"" +
+ "is not a valid extension.", null);
+ return;
+ }
+
+ // Don't let the user create the main tab as a .java file instead of .pde
+ if (!isDefaultExtension(newExtension)) {
+ if (renamingCode) { // If creating a new tab, don't show this error
+ if (current == code[0]) { // If this is the main tab, disallow
+ Base.showWarning("Problem with rename",
+ "The main file can't use an extension.\n" +
+ "(It may be time for your to graduate to a\n" +
+ "\"real\" programming environment)", null);
+ return;
+ }
+ }
+ }
+
+ // dots are allowed for the .pde and .java, but not in the name
+ // make sure the user didn't name things poo.time.pde
+ // or something like that (nothing against poo time)
+ String shortName = newName.substring(0, dot);
+ String sanitaryName = Sketch.sanitizeName(shortName);
+ if (!shortName.equals(sanitaryName)) {
+ newName = sanitaryName + "." + newExtension;
+ }
+
+ // Make sure no .pde *and* no .java files with the same name already exist
+ // http://dev.processing.org/bugs/show_bug.cgi?id=543
+ for (SketchCode c : code) {
+ if (sanitaryName.equals(c.getPrettyName())) {
+ Base.showMessage("Nope",
+ "A file named \"" + c.getFileName() + "\" already exists\n" +
+ "in \"" + folder.getAbsolutePath() + "\"");
+ return;
+ }
+ }
+
+ File newFile = new File(folder, newName);
+// if (newFile.exists()) { // yay! users will try anything
+// Base.showMessage("Nope",
+// "A file named \"" + newFile + "\" already exists\n" +
+// "in \"" + folder.getAbsolutePath() + "\"");
+// return;
+// }
+
+// File newFileHidden = new File(folder, newName + ".x");
+// if (newFileHidden.exists()) {
+// // don't let them get away with it if they try to create something
+// // with the same name as something hidden
+// Base.showMessage("No Way",
+// "A hidden tab with the same name already exists.\n" +
+// "Use \"Unhide\" to bring it back.");
+// return;
+// }
+
+ if (renamingCode) {
+ if (currentIndex == 0) {
+ // get the new folder name/location
+ String folderName = newName.substring(0, newName.indexOf('.'));
+ File newFolder = new File(folder.getParentFile(), folderName);
+ if (newFolder.exists()) {
+ Base.showWarning("Cannot Rename",
+ "Sorry, a sketch (or folder) named " +
+ "\"" + newName + "\" already exists.", null);
+ return;
+ }
+
+ // unfortunately this can't be a "save as" because that
+ // only copies the sketch files and the data folder
+ // however this *will* first save the sketch, then rename
+
+ // first get the contents of the editor text area
+ if (current.isModified()) {
+ current.setProgram(editor.getText());
+ try {
+ // save this new SketchCode
+ current.save();
+ } catch (Exception e) {
+ Base.showWarning("Error", "Could not rename the sketch. (0)", e);
+ return;
+ }
+ }
+
+ if (!current.renameTo(newFile, newExtension)) {
+ Base.showWarning("Error",
+ "Could not rename \"" + current.getFileName() +
+ "\" to \"" + newFile.getName() + "\"", null);
+ return;
+ }
+
+ // save each of the other tabs because this is gonna be re-opened
+ try {
+ for (int i = 1; i < codeCount; i++) {
+ code[i].save();
+ }
+ } catch (Exception e) {
+ Base.showWarning("Error", "Could not rename the sketch. (1)", e);
+ return;
+ }
+
+ // now rename the sketch folder and re-open
+ boolean success = folder.renameTo(newFolder);
+ if (!success) {
+ Base.showWarning("Error", "Could not rename the sketch. (2)", null);
+ return;
+ }
+ // if successful, set base properties for the sketch
+
+ File newMainFile = new File(newFolder, newName + ".pde");
+ String newMainFilePath = newMainFile.getAbsolutePath();
+
+ // having saved everything and renamed the folder and the main .pde,
+ // use the editor to re-open the sketch to re-init state
+ // (unfortunately this will kill positions for carets etc)
+ editor.handleOpenUnchecked(newMainFilePath,
+ currentIndex,
+ editor.getSelectionStart(),
+ editor.getSelectionStop(),
+ editor.getScrollPosition());
+
+ // get the changes into the sketchbook menu
+ // (re-enabled in 0115 to fix bug #332)
+ editor.base.rebuildSketchbookMenus();
+
+ } else { // else if something besides code[0]
+ if (!current.renameTo(newFile, newExtension)) {
+ Base.showWarning("Error",
+ "Could not rename \"" + current.getFileName() +
+ "\" to \"" + newFile.getName() + "\"", null);
+ return;
+ }
+ }
+
+ } else { // creating a new file
+ try {
+ if (!newFile.createNewFile()) {
+ // Already checking for IOException, so make our own.
+ throw new IOException("createNewFile() returned false");
+ }
+ } catch (IOException e) {
+ Base.showWarning("Error",
+ "Could not create the file \"" + newFile + "\"\n" +
+ "in \"" + folder.getAbsolutePath() + "\"", e);
+ return;
+ }
+ SketchCode newCode = new SketchCode(newFile, newExtension);
+ //System.out.println("new code is named " + newCode.getPrettyName() + " " + newCode.getFile());
+ insertCode(newCode);
+ }
+
+ // sort the entries
+ sortCode();
+
+ // set the new guy as current
+ setCurrentCode(newName);
+
+ // update the tabs
+ editor.header.rebuild();
+ }
+
+
+ /**
+ * Remove a piece of code from the sketch and from the disk.
+ */
+ public void handleDeleteCode() {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ // if read-only, give an error
+ if (isReadOnly()) {
+ // if the files are read-only, need to first do a "save as".
+ Base.showMessage("Sketch is Read-Only",
+ "Some files are marked \"read-only\", so you'll\n" +
+ "need to re-save the sketch in another location,\n" +
+ "and try again.");
+ return;
+ }
+
+ // confirm deletion with user, yes/no
+ Object[] options = { "OK", "Cancel" };
+ String prompt = (currentIndex == 0) ?
+ "Are you sure you want to delete this sketch?" :
+ "Are you sure you want to delete \"" + current.getPrettyName() + "\"?";
+ int result = JOptionPane.showOptionDialog(editor,
+ prompt,
+ "Delete",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+ if (result == JOptionPane.YES_OPTION) {
+ if (currentIndex == 0) {
+ // need to unset all the modified flags, otherwise tries
+ // to do a save on the handleNew()
+
+ // delete the entire sketch
+ Base.removeDir(folder);
+
+ // get the changes into the sketchbook menu
+ //sketchbook.rebuildMenus();
+
+ // make a new sketch, and i think this will rebuild the sketch menu
+ //editor.handleNewUnchecked();
+ //editor.handleClose2();
+ editor.base.handleClose(editor);
+
+ } else {
+ // delete the file
+ if (!current.deleteFile()) {
+ Base.showMessage("Couldn't do it",
+ "Could not delete \"" +
+ current.getFileName() + "\".");
+ return;
+ }
+
+ // remove code from the list
+ removeCode(current);
+
+ // just set current tab to the main tab
+ setCurrentCode(0);
+
+ // update the tabs
+ editor.header.repaint();
+ }
+ }
+ }
+
+
+ protected void removeCode(SketchCode which) {
+ // remove it from the internal list of files
+ // resort internal list of files
+ for (int i = 0; i < codeCount; i++) {
+ if (code[i] == which) {
+ for (int j = i; j < codeCount-1; j++) {
+ code[j] = code[j+1];
+ }
+ codeCount--;
+ return;
+ }
+ }
+ System.err.println("removeCode: internal error.. could not find code");
+ }
+
+
+ /**
+ * Move to the previous tab.
+ */
+ public void handlePrevCode() {
+ int prev = currentIndex - 1;
+ if (prev < 0) prev = codeCount-1;
+ setCurrentCode(prev);
+ }
+
+
+ /**
+ * Move to the next tab.
+ */
+ public void handleNextCode() {
+ setCurrentCode((currentIndex + 1) % codeCount);
+ }
+
+
+ /**
+ * Sets the modified value for the code in the frontmost tab.
+ */
+ public void setModified(boolean state) {
+ //System.out.println("setting modified to " + state);
+ //new Exception().printStackTrace();
+ current.setModified(state);
+ calcModified();
+ }
+
+
+ protected void calcModified() {
+ modified = false;
+ for (int i = 0; i < codeCount; i++) {
+ if (code[i].isModified()) {
+ modified = true;
+ break;
+ }
+ }
+ editor.header.repaint();
+
+ if (Base.isMacOS()) {
+ // http://developer.apple.com/qa/qa2001/qa1146.html
+ Object modifiedParam = modified ? Boolean.TRUE : Boolean.FALSE;
+ editor.getRootPane().putClientProperty("windowModified", modifiedParam);
+ }
+ }
+
+
+ public boolean isModified() {
+ return modified;
+ }
+
+
+ /**
+ * Save all code in the current sketch.
+ */
+ public boolean save() throws IOException {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ // first get the contents of the editor text area
+ if (current.isModified()) {
+ current.setProgram(editor.getText());
+ }
+
+ // don't do anything if not actually modified
+ //if (!modified) return false;
+
+ if (isReadOnly()) {
+ // if the files are read-only, need to first do a "save as".
+ Base.showMessage("Sketch is read-only",
+ "Some files are marked \"read-only\", so you'll\n" +
+ "need to re-save this sketch to another location.");
+ // if the user cancels, give up on the save()
+ if (!saveAs()) return false;
+ }
+
+ for (int i = 0; i < codeCount; i++) {
+ if (code[i].isModified()) code[i].save();
+ }
+ calcModified();
+ return true;
+ }
+
+
+ /**
+ * Handles 'Save As' for a sketch.
+ *
+ * This basically just duplicates the current sketch folder to
+ * a new location, and then calls 'Save'. (needs to take the current
+ * state of the open files and save them to the new folder..
+ * but not save over the old versions for the old sketch..)
+ *
+ * Also removes the previously-generated .class and .jar files,
+ * because they can cause trouble.
+ */
+ protected boolean saveAs() throws IOException {
+ String newParentDir = null;
+ String newName = null;
+
+ /*
+ JFileChooser fc = new JFileChooser();
+ fc.setDialogTitle("Save sketch folder as...");
+ if (isReadOnly() || isUntitled()) {
+ // default to the sketchbook folder
+ fc.setCurrentDirectory(new File(Preferences.get("sketchbook.path")));
+ } else {
+ // default to the parent folder of where this was
+ fc.setCurrentDirectory(folder.getParentFile());
+ }
+ // can't do this, will try to save into itself by default
+ //fc.setSelectedFile(folder);
+ int result = fc.showSaveDialog(editor);
+ if (result == JFileChooser.APPROVE_OPTION) {
+ File selection = fc.getSelectedFile();
+ newParentDir = selection.getParent();
+ newName = selection.getName();
+ }
+ */
+
+ // get new name for folder
+ FileDialog fd = new FileDialog(editor,
+ "Save sketch folder as...",
+ FileDialog.SAVE);
+ if (isReadOnly() || isUntitled()) {
+ // default to the sketchbook folder
+ fd.setDirectory(Preferences.get("sketchbook.path"));
+ } else {
+ // default to the parent folder of where this was
+ fd.setDirectory(folder.getParent());
+ }
+ String oldName = folder.getName();
+ fd.setFile(oldName);
+
+ fd.setVisible(true);
+ newParentDir = fd.getDirectory();
+ newName = fd.getFile();
+
+ // user canceled selection
+ if (newName == null) return false;
+ newName = Sketch.checkName(newName);
+
+ File newFolder = new File(newParentDir, newName);
+// String newPath = newFolder.getAbsolutePath();
+// String oldPath = folder.getAbsolutePath();
+
+// if (newPath.equals(oldPath)) {
+// return false; // Can't save a sketch over itself
+// }
+
+ // make sure there doesn't exist a tab with that name already
+ // but ignore this situation for the first tab, since it's probably being
+ // resaved (with the same name) to another location/folder.
+ for (int i = 1; i < codeCount; i++) {
+ if (newName.equals(code[i].getPrettyName())) {
+ Base.showMessage("Nope",
+ "You can't save the sketch as \"" + newName + "\"\n" +
+ "because the sketch already has a tab with that name.");
+ return false;
+ }
+ }
+
+ // check if the paths are identical
+ if (newFolder.equals(folder)) {
+ // just use "save" here instead, because the user will have received a
+ // message (from the operating system) about "do you want to replace?"
+ return save();
+ }
+
+ // check to see if the user is trying to save this sketch inside itself
+ try {
+ String newPath = newFolder.getCanonicalPath() + File.separator;
+ String oldPath = folder.getCanonicalPath() + File.separator;
+
+ if (newPath.indexOf(oldPath) == 0) {
+ Base.showWarning("How very Borges of you",
+ "You cannot save the sketch into a folder\n" +
+ "inside itself. This would go on forever.", null);
+ return false;
+ }
+ } catch (IOException e) { }
+
+ // if the new folder already exists, then need to remove
+ // its contents before copying everything over
+ // (user will have already been warned)
+ if (newFolder.exists()) {
+ Base.removeDir(newFolder);
+ }
+ // in fact, you can't do this on windows because the file dialog
+ // will instead put you inside the folder, but it happens on osx a lot.
+
+ // now make a fresh copy of the folder
+ newFolder.mkdirs();
+
+ // grab the contents of the current tab before saving
+ // first get the contents of the editor text area
+ if (current.isModified()) {
+ current.setProgram(editor.getText());
+ }
+
+ // save the other tabs to their new location
+ for (int i = 1; i < codeCount; i++) {
+ File newFile = new File(newFolder, code[i].getFileName());
+ code[i].saveAs(newFile);
+ }
+
+ // re-copy the data folder (this may take a while.. add progress bar?)
+ if (dataFolder.exists()) {
+ File newDataFolder = new File(newFolder, "data");
+ Base.copyDir(dataFolder, newDataFolder);
+ }
+
+ // re-copy the code folder
+ if (codeFolder.exists()) {
+ File newCodeFolder = new File(newFolder, "code");
+ Base.copyDir(codeFolder, newCodeFolder);
+ }
+
+ // copy custom applet.html file if one exists
+ // http://dev.processing.org/bugs/show_bug.cgi?id=485
+ File customHtml = new File(folder, "applet.html");
+ if (customHtml.exists()) {
+ File newHtml = new File(newFolder, "applet.html");
+ Base.copyFile(customHtml, newHtml);
+ }
+
+ // save the main tab with its new name
+ File newFile = new File(newFolder, newName + ".pde");
+ code[0].saveAs(newFile);
+
+ editor.handleOpenUnchecked(newFile.getPath(),
+ currentIndex,
+ editor.getSelectionStart(),
+ editor.getSelectionStop(),
+ editor.getScrollPosition());
+
+ // Name changed, rebuild the sketch menus
+ //editor.sketchbook.rebuildMenusAsync();
+ editor.base.rebuildSketchbookMenus();
+
+ // Make sure that it's not an untitled sketch
+ setUntitled(false);
+
+ // let Editor know that the save was successful
+ return true;
+ }
+
+
+ /**
+ * Prompt the user for a new file to the sketch, then call the
+ * other addFile() function to actually add it.
+ */
+ public void handleAddFile() {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ // if read-only, give an error
+ if (isReadOnly()) {
+ // if the files are read-only, need to first do a "save as".
+ Base.showMessage("Sketch is Read-Only",
+ "Some files are marked \"read-only\", so you'll\n" +
+ "need to re-save the sketch in another location,\n" +
+ "and try again.");
+ return;
+ }
+
+ // get a dialog, select a file to add to the sketch
+ String prompt =
+ "Select an image or other data file to copy to your sketch";
+ //FileDialog fd = new FileDialog(new Frame(), prompt, FileDialog.LOAD);
+ FileDialog fd = new FileDialog(editor, prompt, FileDialog.LOAD);
+ fd.setVisible(true);
+
+ String directory = fd.getDirectory();
+ String filename = fd.getFile();
+ if (filename == null) return;
+
+ // copy the file into the folder. if people would rather
+ // it move instead of copy, they can do it by hand
+ File sourceFile = new File(directory, filename);
+
+ // now do the work of adding the file
+ boolean result = addFile(sourceFile);
+
+ if (result) {
+ editor.statusNotice("One file added to the sketch.");
+ }
+ }
+
+
+ /**
+ * Add a file to the sketch.
+ *
+ * .pde or .java files will be added to the sketch folder.
+ * .jar, .class, .dll, .jnilib, and .so files will all
+ * be added to the "code" folder.
+ * All other files will be added to the "data" folder.
+ *
+ * If they don't exist already, the "code" or "data" folder
+ * will be created.
+ *
+ * @return true if successful.
+ */
+ public boolean addFile(File sourceFile) {
+ String filename = sourceFile.getName();
+ File destFile = null;
+ String codeExtension = null;
+ boolean replacement = false;
+
+ // if the file appears to be code related, drop it
+ // into the code folder, instead of the data folder
+ if (filename.toLowerCase().endsWith(".o") ||
+ filename.toLowerCase().endsWith(".a") ||
+ filename.toLowerCase().endsWith(".so")) {
+
+ //if (!codeFolder.exists()) codeFolder.mkdirs();
+ prepareCodeFolder();
+ destFile = new File(codeFolder, filename);
+
+ } else {
+ for (String extension : getExtensions()) {
+ String lower = filename.toLowerCase();
+ if (lower.endsWith("." + extension)) {
+ destFile = new File(this.folder, filename);
+ codeExtension = extension;
+ }
+ }
+ if (codeExtension == null) {
+ prepareDataFolder();
+ destFile = new File(dataFolder, filename);
+ }
+ }
+
+ // check whether this file already exists
+ if (destFile.exists()) {
+ Object[] options = { "OK", "Cancel" };
+ String prompt = "Replace the existing version of " + filename + "?";
+ int result = JOptionPane.showOptionDialog(editor,
+ prompt,
+ "Replace",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+ if (result == JOptionPane.YES_OPTION) {
+ replacement = true;
+ } else {
+ return false;
+ }
+ }
+
+ // If it's a replacement, delete the old file first,
+ // otherwise case changes will not be preserved.
+ // http://dev.processing.org/bugs/show_bug.cgi?id=969
+ if (replacement) {
+ boolean muchSuccess = destFile.delete();
+ if (!muchSuccess) {
+ Base.showWarning("Error adding file",
+ "Could not delete the existing '" +
+ filename + "' file.", null);
+ return false;
+ }
+ }
+
+ // make sure they aren't the same file
+ if ((codeExtension == null) && sourceFile.equals(destFile)) {
+ Base.showWarning("You can't fool me",
+ "This file has already been copied to the\n" +
+ "location from which where you're trying to add it.\n" +
+ "I ain't not doin nuthin'.", null);
+ return false;
+ }
+
+ // in case the user is "adding" the code in an attempt
+ // to update the sketch's tabs
+ if (!sourceFile.equals(destFile)) {
+ try {
+ Base.copyFile(sourceFile, destFile);
+
+ } catch (IOException e) {
+ Base.showWarning("Error adding file",
+ "Could not add '" + filename + "' to the sketch.", e);
+ return false;
+ }
+ }
+
+ if (codeExtension != null) {
+ SketchCode newCode = new SketchCode(destFile, codeExtension);
+
+ if (replacement) {
+ replaceCode(newCode);
+
+ } else {
+ insertCode(newCode);
+ sortCode();
+ }
+ setCurrentCode(filename);
+ editor.header.repaint();
+ if (editor.untitled) { // TODO probably not necessary? problematic?
+ // Mark the new code as modified so that the sketch is saved
+ current.setModified(true);
+ }
+
+ } else {
+ if (editor.untitled) { // TODO probably not necessary? problematic?
+ // If a file has been added, mark the main code as modified so
+ // that the sketch is properly saved.
+ code[0].setModified(true);
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Add import statements to the current tab for all of packages inside
+ * the specified jar file.
+ */
+ public void importLibrary(String jarPath) {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ String list[] = Compiler.headerListFromIncludePath(jarPath);
+
+ // import statements into the main sketch file (code[0])
+ // if the current code is a .java file, insert into current
+ //if (current.flavor == PDE) {
+ if (hasDefaultExtension(current)) {
+ setCurrentCode(0);
+ }
+ // could also scan the text in the file to see if each import
+ // statement is already in there, but if the user has the import
+ // commented out, then this will be a problem.
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < list.length; i++) {
+ buffer.append("#include <");
+ buffer.append(list[i]);
+ buffer.append(">\n");
+ }
+ buffer.append('\n');
+ buffer.append(editor.getText());
+ editor.setText(buffer.toString());
+ editor.setSelection(0, 0); // scroll to start
+ setModified(true);
+ }
+
+
+ /**
+ * Change what file is currently being edited. Changes the current tab index.
+ *
+ *
store the String for the text of the current file.
+ *
retrieve the String for the text of the new file.
+ *
change the text that's visible in the text area
+ *
+ */
+ public void setCurrentCode(int which) {
+ // if current is null, then this is the first setCurrent(0)
+ if ((currentIndex == which) && (current != null)) {
+ return;
+ }
+
+ // get the text currently being edited
+ if (current != null) {
+ current.setState(editor.getText(),
+ editor.getSelectionStart(),
+ editor.getSelectionStop(),
+ editor.getScrollPosition());
+ }
+
+ current = code[which];
+ currentIndex = which;
+
+ editor.setCode(current);
+ editor.header.rebuild();
+ }
+
+
+ /**
+ * Internal helper function to set the current tab based on a name.
+ * @param findName the file name (not pretty name) to be shown
+ */
+ protected void setCurrentCode(String findName) {
+ for (int i = 0; i < codeCount; i++) {
+ if (findName.equals(code[i].getFileName()) ||
+ findName.equals(code[i].getPrettyName())) {
+ setCurrentCode(i);
+ return;
+ }
+ }
+ }
+
+
+ /**
+ * Cleanup temporary files used during a build/run.
+ */
+ protected void cleanup() {
+ // if the java runtime is holding onto any files in the build dir, we
+ // won't be able to delete them, so we need to force a gc here
+ System.gc();
+
+ // note that we can't remove the builddir itself, otherwise
+ // the next time we start up, internal runs using Runner won't
+ // work because the build dir won't exist at startup, so the classloader
+ // will ignore the fact that that dir is in the CLASSPATH in run.sh
+ Base.removeDescendants(tempBuildFolder);
+ }
+
+
+ /**
+ * Preprocess, Compile, and Run the current code.
+ *
+ * There are three main parts to this process:
+ *
+ * (0. if not java, then use another 'engine'.. i.e. python)
+ *
+ * 1. do the p5 language preprocessing
+ * this creates a working .java file in a specific location
+ * better yet, just takes a chunk of java code and returns a
+ * new/better string editor can take care of saving this to a
+ * file location
+ *
+ * 2. compile the code from that location
+ * catching errors along the way
+ * placing it in a ready classpath, or .. ?
+ *
+ * 3. run the code
+ * needs to communicate location for window
+ * and maybe setup presentation space as well
+ * run externally if a code folder exists,
+ * or if more than one file is in the project
+ *
+ * X. afterwards, some of these steps need a cleanup function
+ *
+ */
+ protected String compile(Target target) throws RunnerException {
+ String name;
+
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ current.setProgram(editor.getText());
+
+ // TODO record history here
+ //current.history.record(program, SketchHistory.RUN);
+
+ // if an external editor is being used, need to grab the
+ // latest version of the code from the file.
+ if (Preferences.getBoolean("editor.external")) {
+ // history gets screwed by the open..
+ //String historySaved = history.lastRecorded;
+ //handleOpen(sketch);
+ //history.lastRecorded = historySaved;
+
+ // set current to null so that the tab gets updated
+ // http://dev.processing.org/bugs/show_bug.cgi?id=515
+ current = null;
+ // nuke previous files and settings, just get things loaded
+ load();
+ }
+
+ // in case there were any boogers left behind
+ // do this here instead of after exiting, since the exit
+ // can happen so many different ways.. and this will be
+ // better connected to the dataFolder stuff below.
+ cleanup();
+
+ // handle preprocessing the main file's code
+ name = build(tempBuildFolder.getAbsolutePath(), target);
+ size(tempBuildFolder.getAbsolutePath(), name);
+
+ return name;
+ }
+
+
+ /**
+ * Build all the code for this sketch.
+ *
+ * In an advanced program, the returned class name could be different,
+ * which is why the className is set based on the return value.
+ * A compilation error will burp up a RunnerException.
+ *
+ * Setting purty to 'true' will cause exception line numbers to be incorrect.
+ * Unless you know the code compiles, you should first run the preprocessor
+ * with purty set to false to make sure there are no errors, then once
+ * successful, re-export with purty set to true.
+ *
+ * @param buildPath Location to copy all the .java files
+ * @return null if compilation failed, main class name if not
+ */
+ public String preprocess(String buildPath, Target target) throws RunnerException {
+ // make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ String[] codeFolderPackages = null;
+ classPath = buildPath;
+
+// // figure out the contents of the code folder to see if there
+// // are files that need to be added to the imports
+// if (codeFolder.exists()) {
+// libraryPath = codeFolder.getAbsolutePath();
+//
+// // get a list of .jar files in the "code" folder
+// // (class files in subfolders should also be picked up)
+// String codeFolderClassPath =
+// Compiler.contentsToClassPath(codeFolder);
+// // append the jar files in the code folder to the class path
+// classPath += File.pathSeparator + codeFolderClassPath;
+// // get list of packages found in those jars
+// codeFolderPackages =
+// Compiler.packageListFromClassPath(codeFolderClassPath);
+//
+// } else {
+// libraryPath = "";
+// }
+
+ // 1. concatenate all .pde files to the 'main' pde
+ // store line number for starting point of each code bit
+
+ // Unfortunately, the header has to be written on a single line, because
+ // there's no way to determine how long it will be until the code has
+ // already been preprocessed. The header will vary in length based on
+ // the programming mode (STATIC, ACTIVE, or JAVA), which is determined
+ // by the preprocessor. So the preprocOffset for the primary class remains
+ // zero, even though it'd be nice to have a legitimate offset, and be able
+ // to remove the 'pretty' boolean for preproc.write().
+
+ StringBuffer bigCode = new StringBuffer();
+ int bigCount = 0;
+ for (SketchCode sc : code) {
+ if (sc.isExtension("pde")) {
+ sc.setPreprocOffset(bigCount);
+ bigCode.append(sc.getProgram());
+ bigCode.append('\n');
+ bigCount += sc.getLineCount();
+// if (sc != code[0]) {
+// sc.setPreprocName(null); // don't compile me
+// }
+ }
+ }
+
+ /*
+ String program = code[0].getProgram();
+ StringBuffer bigCode = new StringBuffer(program);
+ int bigCount = code[0].getLineCount();
+ bigCode.append('\n');
+
+ for (int i = 1; i < codeCount; i++) {
+ if (code[i].isExtension("pde")) {
+ code[i].setPreprocOffset(bigCount);
+ bigCode.append(code[i].getProgram());
+ bigCode.append('\n');
+ bigCount += code[i].getLineCount();
+ code[i].setPreprocName(null); // don't compile me
+ }
+ }
+ */
+
+ // Note that the headerOffset isn't applied until compile and run, because
+ // it only applies to the code after it's been written to the .java file.
+ int headerOffset = 0;
+ PdePreprocessor preprocessor = new PdePreprocessor();
+
+ // 2. run preproc on that code using the sugg class name
+ // to create a single .java file and write to buildpath
+
+ String primaryClassName = null;
+
+ try {
+ // if (i != 0) preproc will fail if a pde file is not
+ // java mode, since that's required
+ String className = preprocessor.write(bigCode.toString(),
+ buildPath,
+ name,
+ codeFolderPackages,
+ target);
+ headerOffset = preprocessor.headerCount + preprocessor.prototypeCount;
+
+ if (className == null) {
+ throw new RunnerException("Could not find main class");
+ // this situation might be perfectly fine,
+ // (i.e. if the file is empty)
+ //System.out.println("No class found in " + code[i].name);
+ //System.out.println("(any code in that file will be ignored)");
+ //System.out.println();
+
+// } else {
+// code[0].setPreprocName(className + ".java");
+ }
+
+ // store this for the compiler and the runtime
+ primaryClassName = className + ".cpp";
+
+ } catch (FileNotFoundException fnfe) {
+ fnfe.printStackTrace();
+ String msg = "Build folder disappeared or could not be written";
+ throw new RunnerException(msg);
+ } catch (RunnerException pe) {
+ // RunnerExceptions are caught here and re-thrown, so that they don't
+ // get lost in the more general "Exception" handler below.
+ throw pe;
+
+ } catch (Exception ex) {
+ // TODO better method for handling this?
+ System.err.println("Uncaught exception type:" + ex.getClass());
+ ex.printStackTrace();
+ throw new RunnerException(ex.toString());
+ }
+
+ // grab the imports from the code just preproc'd
+
+ importedLibraries = new ArrayList();
+
+ for (String item : preprocessor.getExtraImports()) {
+ File libFolder = (File) Base.importToLibraryTable.get(item);
+
+ if (libFolder != null && !importedLibraries.contains(libFolder)) {
+ importedLibraries.add(libFolder);
+ classPath += Compiler.contentsToClassPath(libFolder);
+ libraryPath += File.pathSeparator + libFolder.getAbsolutePath();
+ }
+ }
+
+ // 3. then loop over the code[] and save each .java file
+
+ for (SketchCode sc : code) {
+ if (sc.isExtension("c") || sc.isExtension("cpp") || sc.isExtension("h")) {
+ // no pre-processing services necessary for java files
+ // just write the the contents of 'program' to a .java file
+ // into the build directory. uses byte stream and reader/writer
+ // shtuff so that unicode bunk is properly handled
+ String filename = sc.getFileName(); //code[i].name + ".java";
+ try {
+ Base.saveFile(sc.getProgram(), new File(buildPath, filename));
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RunnerException("Problem moving " + filename +
+ " to the build folder");
+ }
+// sc.setPreprocName(filename);
+
+ } else if (sc.isExtension("pde")) {
+ // The compiler and runner will need this to have a proper offset
+ sc.addPreprocOffset(headerOffset);
+ }
+ }
+ return primaryClassName;
+ }
+
+
+ /**
+ * Preprocess and compile all the code for this sketch.
+ *
+ * In an advanced program, the returned class name could be different,
+ * which is why the className is set based on the return value.
+ * A compilation error will burp up a RunnerException.
+ *
+ * @return null if compilation failed, main class name if not
+ */
+ public String build(String buildPath, Target target) throws RunnerException {
+ // run the preprocessor
+ String primaryClassName = preprocess(buildPath, target);
+
+ // compile the program. errors will happen as a RunnerException
+ // that will bubble up to whomever called build().
+ Compiler compiler = new Compiler();
+ if (compiler.compile(this, buildPath, primaryClassName, target)) {
+ return primaryClassName;
+ }
+ return null;
+ }
+
+
+ protected boolean exportApplet(Target target) throws Exception {
+ return exportApplet(new File(folder, "applet").getAbsolutePath(), target);
+ }
+
+
+ /**
+ * Handle export to applet.
+ */
+ public boolean exportApplet(String appletPath, Target target)
+ throws RunnerException, IOException {
+
+ // Make sure the user didn't hide the sketch folder
+ ensureExistence();
+
+ current.setProgram(editor.getText());
+
+ // Reload the code when an external editor is being used
+ if (Preferences.getBoolean("editor.external")) {
+ current = null;
+ // nuke previous files and settings
+ load();
+ }
+
+ File appletFolder = new File(appletPath);
+ // Nuke the old applet folder because it can cause trouble
+ if (Preferences.getBoolean("export.delete_target_folder")) {
+ Base.removeDir(appletFolder);
+ }
+ // Create a fresh applet folder (needed before preproc is run below)
+ appletFolder.mkdirs();
+
+ // build the sketch
+ String foundName = build(appletFolder.getPath(), target);
+ // (already reported) error during export, exit this function
+ if (foundName == null) return false;
+
+// // If name != exportSketchName, then that's weirdness
+// // BUG unfortunately, that can also be a bug in the preproc :(
+// if (!name.equals(foundName)) {
+// Base.showWarning("Error during export",
+// "Sketch name is " + name + " but the sketch\n" +
+// "name in the code was " + foundName, null);
+// return false;
+// }
+
+ size(appletFolder.getPath(), foundName);
+ upload(appletFolder.getPath(), foundName);
+
+ return true;
+ }
+
+
+ protected void size(String buildPath, String suggestedClassName)
+ throws RunnerException {
+ long size = 0;
+ long maxsize = Preferences.getInteger("boards." + Preferences.get("board") + ".upload.maximum_size");
+ Sizer sizer = new Sizer(buildPath, suggestedClassName);
+ try {
+ size = sizer.computeSize();
+ System.out.println("Binary sketch size: " + size + " bytes (of a " +
+ maxsize + " byte maximum)");
+ } catch (RunnerException e) {
+ System.err.println("Couldn't determine program size: " + e.getMessage());
+ }
+
+ if (size > maxsize)
+ throw new RunnerException(
+ "Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.");
+ }
+
+
+ protected String upload(String buildPath, String suggestedClassName)
+ throws RunnerException {
+
+ Uploader uploader;
+
+ // download the program
+ //
+ uploader = new AvrdudeUploader();
+ boolean success = uploader.uploadUsingPreferences(buildPath,
+ suggestedClassName);
+
+ return success ? suggestedClassName : null;
+ }
+
+ /**
+ * Replace all commented portions of a given String as spaces.
+ * Utility function used here and in the preprocessor.
+ */
+ static public String scrubComments(String what) {
+ char p[] = what.toCharArray();
+
+ int index = 0;
+ while (index < p.length) {
+ // for any double slash comments, ignore until the end of the line
+ if ((p[index] == '/') &&
+ (index < p.length - 1) &&
+ (p[index+1] == '/')) {
+ p[index++] = ' ';
+ p[index++] = ' ';
+ while ((index < p.length) &&
+ (p[index] != '\n')) {
+ p[index++] = ' ';
+ }
+
+ // check to see if this is the start of a new multiline comment.
+ // if it is, then make sure it's actually terminated somewhere.
+ } else if ((p[index] == '/') &&
+ (index < p.length - 1) &&
+ (p[index+1] == '*')) {
+ p[index++] = ' ';
+ p[index++] = ' ';
+ boolean endOfRainbow = false;
+ while (index < p.length - 1) {
+ if ((p[index] == '*') && (p[index+1] == '/')) {
+ p[index++] = ' ';
+ p[index++] = ' ';
+ endOfRainbow = true;
+ break;
+
+ } else {
+ index++;
+ }
+ }
+ if (!endOfRainbow) {
+ throw new RuntimeException("Missing the */ from the end of a " +
+ "/* comment */");
+ }
+ } else { // any old character, move along
+ index++;
+ }
+ }
+ return new String(p);
+ }
+
+
+ public boolean exportApplicationPrompt() throws IOException, RunnerException {
+ return false;
+ }
+
+
+ /**
+ * Export to application via GUI.
+ */
+ protected boolean exportApplication() throws IOException, RunnerException {
+ return false;
+ }
+
+
+ /**
+ * Export to application without GUI.
+ */
+ public boolean exportApplication(String destPath,
+ int exportPlatform) throws IOException, RunnerException {
+ return false;
+ }
+
+
+ protected void addManifest(ZipOutputStream zos) throws IOException {
+ ZipEntry entry = new ZipEntry("META-INF/MANIFEST.MF");
+ zos.putNextEntry(entry);
+
+ String contents =
+ "Manifest-Version: 1.0\n" +
+ "Created-By: Processing " + Base.VERSION_NAME + "\n" +
+ "Main-Class: " + name + "\n"; // TODO not package friendly
+ zos.write(contents.getBytes());
+ zos.closeEntry();
+ }
+
+
+ /**
+ * Read from a file with a bunch of attribute/value pairs
+ * that are separated by = and ignore comments with #.
+ */
+ protected Hashtable readSettings(File inputFile) {
+ Hashtable outgoing = new Hashtable();
+ if (!inputFile.exists()) return outgoing; // return empty hash
+
+ String lines[] = PApplet.loadStrings(inputFile);
+ for (int i = 0; i < lines.length; i++) {
+ int hash = lines[i].indexOf('#');
+ String line = (hash == -1) ?
+ lines[i].trim() : lines[i].substring(0, hash).trim();
+ if (line.length() == 0) continue;
+
+ int equals = line.indexOf('=');
+ if (equals == -1) {
+ System.err.println("ignoring illegal line in " + inputFile);
+ System.err.println(" " + line);
+ continue;
+ }
+ String attr = line.substring(0, equals).trim();
+ String valu = line.substring(equals + 1).trim();
+ outgoing.put(attr, valu);
+ }
+ return outgoing;
+ }
+
+
+ /**
+ * Slurps up .class files from a colon (or semicolon on windows)
+ * separated list of paths and adds them to a ZipOutputStream.
+ */
+ protected void packClassPathIntoZipFile(String path,
+ ZipOutputStream zos,
+ Hashtable zipFileContents)
+ throws IOException {
+ String[] pieces = PApplet.split(path, File.pathSeparatorChar);
+
+ for (int i = 0; i < pieces.length; i++) {
+ if (pieces[i].length() == 0) continue;
+
+ // is it a jar file or directory?
+ if (pieces[i].toLowerCase().endsWith(".jar") ||
+ pieces[i].toLowerCase().endsWith(".zip")) {
+ try {
+ ZipFile file = new ZipFile(pieces[i]);
+ Enumeration entries = file.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+ if (entry.isDirectory()) {
+ // actually 'continue's for all dir entries
+
+ } else {
+ String entryName = entry.getName();
+ // ignore contents of the META-INF folders
+ if (entryName.indexOf("META-INF") == 0) continue;
+
+ // don't allow duplicate entries
+ if (zipFileContents.get(entryName) != null) continue;
+ zipFileContents.put(entryName, new Object());
+
+ ZipEntry entree = new ZipEntry(entryName);
+
+ zos.putNextEntry(entree);
+ byte buffer[] = new byte[(int) entry.getSize()];
+ InputStream is = file.getInputStream(entry);
+
+ int offset = 0;
+ int remaining = buffer.length;
+ while (remaining > 0) {
+ int count = is.read(buffer, offset, remaining);
+ offset += count;
+ remaining -= count;
+ }
+
+ zos.write(buffer);
+ zos.flush();
+ zos.closeEntry();
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Error in file " + pieces[i]);
+ e.printStackTrace();
+ }
+ } else { // not a .jar or .zip, prolly a directory
+ File dir = new File(pieces[i]);
+ // but must be a dir, since it's one of several paths
+ // just need to check if it exists
+ if (dir.exists()) {
+ packClassPathIntoZipFileRecursive(dir, null, zos);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Continue the process of magical exporting. This function
+ * can be called recursively to walk through folders looking
+ * for more goodies that will be added to the ZipOutputStream.
+ */
+ static protected void packClassPathIntoZipFileRecursive(File dir,
+ String sofar,
+ ZipOutputStream zos)
+ throws IOException {
+ String files[] = dir.list();
+ for (int i = 0; i < files.length; i++) {
+ // ignore . .. and .DS_Store
+ if (files[i].charAt(0) == '.') continue;
+
+ File sub = new File(dir, files[i]);
+ String nowfar = (sofar == null) ?
+ files[i] : (sofar + "/" + files[i]);
+
+ if (sub.isDirectory()) {
+ packClassPathIntoZipFileRecursive(sub, nowfar, zos);
+
+ } else {
+ // don't add .jar and .zip files, since they only work
+ // inside the root, and they're unpacked
+ if (!files[i].toLowerCase().endsWith(".jar") &&
+ !files[i].toLowerCase().endsWith(".zip") &&
+ files[i].charAt(0) != '.') {
+ ZipEntry entry = new ZipEntry(nowfar);
+ zos.putNextEntry(entry);
+ zos.write(Base.loadBytesRaw(sub));
+ zos.closeEntry();
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Make sure the sketch hasn't been moved or deleted by some
+ * nefarious user. If they did, try to re-create it and save.
+ * Only checks to see if the main folder is still around,
+ * but not its contents.
+ */
+ protected void ensureExistence() {
+ if (folder.exists()) return;
+
+ Base.showWarning("Sketch Disappeared",
+ "The sketch folder has disappeared.\n " +
+ "Will attempt to re-save in the same location,\n" +
+ "but anything besides the code will be lost.", null);
+ try {
+ folder.mkdirs();
+ modified = true;
+
+ for (int i = 0; i < codeCount; i++) {
+ code[i].save(); // this will force a save
+ }
+ calcModified();
+
+ } catch (Exception e) {
+ Base.showWarning("Could not re-save sketch",
+ "Could not properly re-save the sketch. " +
+ "You may be in trouble at this point,\n" +
+ "and it might be time to copy and paste " +
+ "your code to another text editor.", e);
+ }
+ }
+
+
+ /**
+ * Returns true if this is a read-only sketch. Used for the
+ * examples directory, or when sketches are loaded from read-only
+ * volumes or folders without appropriate permissions.
+ */
+ public boolean isReadOnly() {
+ String apath = folder.getAbsolutePath();
+ if (apath.startsWith(Base.getExamplesPath()) ||
+ apath.startsWith(Base.getLibrariesPath()) ||
+ apath.startsWith(Base.getSketchbookLibrariesPath())) {
+ return true;
+
+ // canWrite() doesn't work on directories
+ //} else if (!folder.canWrite()) {
+ } else {
+ // check to see if each modified code file can be written to
+ for (int i = 0; i < codeCount; i++) {
+ if (code[i].isModified() &&
+ code[i].fileReadOnly() &&
+ code[i].fileExists()) {
+ //System.err.println("found a read-only file " + code[i].file);
+ return true;
+ }
+ }
+ //return true;
+ }
+ return false;
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+ // Breaking out extension types in order to clean up the code, and make it
+ // easier for other environments (like Arduino) to incorporate changes.
+
+
+ /**
+ * True if the specified extension should be hidden when shown on a tab.
+ * For Processing, this is true for .pde files. (Broken out for subclasses.)
+ */
+ public boolean hideExtension(String what) {
+ return what.equals(getDefaultExtension());
+ }
+
+
+ /**
+ * True if the specified code has the default file extension.
+ */
+ public boolean hasDefaultExtension(SketchCode code) {
+ return code.getExtension().equals(getDefaultExtension());
+ }
+
+
+ /**
+ * True if the specified extension is the default file extension.
+ */
+ public boolean isDefaultExtension(String what) {
+ return what.equals(getDefaultExtension());
+ }
+
+
+ /**
+ * Check this extension (no dots, please) against the list of valid
+ * extensions.
+ */
+ public boolean validExtension(String what) {
+ String[] ext = getExtensions();
+ for (int i = 0; i < ext.length; i++) {
+ if (ext[i].equals(what)) return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns the default extension for this editor setup.
+ */
+ public String getDefaultExtension() {
+ return "pde";
+ }
+
+
+ /**
+ * Returns a String[] array of proper extensions.
+ */
+ public String[] getExtensions() {
+ return new String[] { "pde", "c", "cpp", "h" };
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+ // Additional accessors added in 0136 because of package work.
+ // These will also be helpful for tool developers.
+
+
+ /**
+ * Returns the name of this sketch. (The pretty name of the main tab.)
+ */
+ public String getName() {
+ return name;
+ }
+
+
+ /**
+ * Returns a file object for the primary .pde of this sketch.
+ */
+ public File getPrimaryFile() {
+ return primaryFile;
+ }
+
+
+ /**
+ * Returns path to the main .pde file for this sketch.
+ */
+ public String getMainFilePath() {
+ return primaryFile.getAbsolutePath();
+ //return code[0].file.getAbsolutePath();
+ }
+
+
+ /**
+ * Returns the sketch folder.
+ */
+ public File getFolder() {
+ return folder;
+ }
+
+
+ /**
+ * Returns the location of the sketch's data folder. (It may not exist yet.)
+ */
+ public File getDataFolder() {
+ return dataFolder;
+ }
+
+
+ /**
+ * Create the data folder if it does not exist already. As a convenience,
+ * it also returns the data folder, since it's likely about to be used.
+ */
+ public File prepareDataFolder() {
+ if (!dataFolder.exists()) {
+ dataFolder.mkdirs();
+ }
+ return dataFolder;
+ }
+
+
+ /**
+ * Returns the location of the sketch's code folder. (It may not exist yet.)
+ */
+ public File getCodeFolder() {
+ return codeFolder;
+ }
+
+
+ /**
+ * Create the code folder if it does not exist already. As a convenience,
+ * it also returns the code folder, since it's likely about to be used.
+ */
+ public File prepareCodeFolder() {
+ if (!codeFolder.exists()) {
+ codeFolder.mkdirs();
+ }
+ return codeFolder;
+ }
+
+
+ public ArrayList getImportedLibraries() {
+ return importedLibraries;
+ }
+
+
+ public String getClassPath() {
+ return classPath;
+ }
+
+
+ public String getLibraryPath() {
+ return libraryPath;
+ }
+
+
+ public SketchCode[] getCode() {
+ return code;
+ }
+
+
+ public int getCodeCount() {
+ return codeCount;
+ }
+
+
+ public SketchCode getCode(int index) {
+ return code[index];
+ }
+
+
+ public int getCodeIndex(SketchCode who) {
+ for (int i = 0; i < codeCount; i++) {
+ if (who == code[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ public SketchCode getCurrentCode() {
+ return current;
+ }
+
+
+ public void setUntitled(boolean u) {
+ editor.untitled = u;
+ }
+
+
+ public boolean isUntitled() {
+ return editor.untitled;
+ }
+
+
+ public String getAppletClassName2() {
+ return appletClassName;
+ }
+
+
+ // .................................................................
+
+
+ /**
+ * Convert to sanitized name and alert the user
+ * if changes were made.
+ */
+ static public String checkName(String origName) {
+ String newName = sanitizeName(origName);
+
+ if (!newName.equals(origName)) {
+ String msg =
+ "The sketch name had to be modified. Sketch names can only consist\n" +
+ "of ASCII characters and numbers (but cannot start with a number).\n" +
+ "They should also be less less than 64 characters long.";
+ System.out.println(msg);
+ }
+ return newName;
+ }
+
+
+ /**
+ * Return true if the name is valid for a Processing sketch.
+ */
+ static public boolean isSanitaryName(String name) {
+ return sanitizeName(name).equals(name);
+ }
+
+
+ /**
+ * Produce a sanitized name that fits our standards for likely to work.
+ *
+ * Java classes have a wider range of names that are technically allowed
+ * (supposedly any Unicode name) than what we support. The reason for
+ * going more narrow is to avoid situations with text encodings and
+ * converting during the process of moving files between operating
+ * systems, i.e. uploading from a Windows machine to a Linux server,
+ * or reading a FAT32 partition in OS X and using a thumb drive.
+ *
+ * This helper function replaces everything but A-Z, a-z, and 0-9 with
+ * underscores. Also disallows starting the sketch name with a digit.
+ */
+ static public String sanitizeName(String origName) {
+ char c[] = origName.toCharArray();
+ StringBuffer buffer = new StringBuffer();
+
+ // can't lead with a digit, so start with an underscore
+ if ((c[0] >= '0') && (c[0] <= '9')) {
+ buffer.append('_');
+ }
+ for (int i = 0; i < c.length; i++) {
+ if (((c[i] >= '0') && (c[i] <= '9')) ||
+ ((c[i] >= 'a') && (c[i] <= 'z')) ||
+ ((c[i] >= 'A') && (c[i] <= 'Z'))) {
+ buffer.append(c[i]);
+
+ } else {
+ buffer.append('_');
+ }
+ }
+ // let's not be ridiculous about the length of filenames.
+ // in fact, Mac OS 9 can handle 255 chars, though it can't really
+ // deal with filenames longer than 31 chars in the Finder.
+ // but limiting to that for sketches would mean setting the
+ // upper-bound on the character limit here to 25 characters
+ // (to handle the base name + ".class")
+ if (buffer.length() > 63) {
+ buffer.setLength(63);
+ }
+ return buffer.toString();
+ }
+}
diff --git a/app/src/processing/app/SketchCode.java b/app/src/processing/app/SketchCode.java
new file mode 100644
index 000000000..f7dae32bb
--- /dev/null
+++ b/app/src/processing/app/SketchCode.java
@@ -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);
+ }
+}
diff --git a/app/src/processing/app/Theme.java b/app/src/processing/app/Theme.java
new file mode 100644
index 000000000..b62f18828
--- /dev/null
+++ b/app/src/processing/app/Theme.java
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/app/UpdateCheck.java b/app/src/processing/app/UpdateCheck.java
old mode 100755
new mode 100644
similarity index 64%
rename from app/UpdateCheck.java
rename to app/src/processing/app/UpdateCheck.java
index 490867f54..28043eca4
--- a/app/UpdateCheck.java
+++ b/app/src/processing/app/UpdateCheck.java
@@ -1,142 +1,134 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2005 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.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-import javax.swing.text.*;
-import javax.swing.undo.*;
-
-import com.apple.mrj.*;
-import com.ice.jni.registry.*;
-
-//import processing.core.*;
-
-
-/**
- * Threaded class to check for updates in the background.
- *
- * 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.
- *
- * 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 {
- Editor editor;
- String downloadURL = "http://arduino.berlios.de/latest.txt";
-
- static final long ONE_DAY = 24 * 60 * 60 * 1000;
-
-
- public UpdateCheck(Editor editor) {
- this.editor = editor;
- 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));
- }
-
- String info = id + "\t" +
- Base.VERSION+ "\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");
-
- try {
- int latest = readInt(downloadURL + "?" + URLEncoder.encode(info, "UTF-8"));
-
- 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 (latest > Base.VERSION) {
- Object[] options = { "Yes", "No" };
- int result = JOptionPane.showOptionDialog(editor,
- prompt,
- "Update",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE,
- null,
- options,
- options[0]);
-
- if (result == JOptionPane.YES_OPTION) {
- Base.openURL("http://processing.org/download/");
-
- //} else if (result == JOptionPane.NO_OPTION) {
- }
- }
- } 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());
- }
-}
+/* -*- 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.
+ *
+ * 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.
+ *
+ * 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());
+ }
+}
diff --git a/app/src/processing/app/WebServer.java b/app/src/processing/app/WebServer.java
new file mode 100644
index 000000000..01f6cc39e
--- /dev/null
+++ b/app/src/processing/app/WebServer.java
@@ -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 this 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 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 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("
\n");
+ ps.println("Parent Directory \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(""+list[i]+"/ ");
+ } else {
+ ps.println(""+list[i]+"
" + (new Date()) + "");
+ }
+
+}
+
+
+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;
+}
diff --git a/app/AvrdudeUploader.java b/app/src/processing/app/debug/AvrdudeUploader.java
similarity index 93%
rename from app/AvrdudeUploader.java
rename to app/src/processing/app/debug/AvrdudeUploader.java
index e52e638b7..65726facc 100755
--- a/app/AvrdudeUploader.java
+++ b/app/src/processing/app/debug/AvrdudeUploader.java
@@ -24,7 +24,12 @@
$Id$
*/
-package processing.app;
+package processing.app.debug;
+
+import processing.app.Base;
+import processing.app.Preferences;
+import processing.app.Serial;
+
import java.io.*;
import java.util.*;
import java.util.zip.*;
@@ -121,7 +126,7 @@ public class AvrdudeUploader extends Uploader {
} catch (InterruptedException e) {}
List bootloader = new ArrayList();
- bootloader.add("-Uflash:w:" + "hardware" + File.separator + "bootloaders" + File.separator +
+ bootloader.add("-Uflash:w:" + Base.getHardwarePath() + File.separator + "bootloaders" + File.separator +
Preferences.get("boards." + Preferences.get("board") + ".bootloader.path") +
File.separator + Preferences.get("boards." + Preferences.get("board") + ".bootloader.file") + ":i");
bootloader.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.lock_bits") + ":m");
@@ -140,16 +145,12 @@ public class AvrdudeUploader extends Uploader {
commandDownloader.add("avrdude");
// Point avrdude at its config file since it's in a non-standard location.
- if(Base.isMacOS()) {
- commandDownloader.add("-C" + "hardware/tools/avr/etc/avrdude.conf");
- }
- else if(Base.isWindows()) {
- String userdir = System.getProperty("user.dir") + File.separator;
- commandDownloader.add("-C" + userdir + "hardware/tools/avr/etc/avrdude.conf");
- } else {
+ if (Base.isLinux()) {
// ???: is it better to have Linux users install avrdude themselves, in
// a way that it can find its own configuration file?
- commandDownloader.add("-C" + "hardware/tools/avrdude.conf");
+ commandDownloader.add("-C" + Base.getHardwarePath() + "/tools/avrdude.conf");
+ } else {
+ commandDownloader.add("-C" + Base.getHardwarePath() + "/tools/avr/etc/avrdude.conf");
}
if (Preferences.getBoolean("upload.verbose")) {
diff --git a/app/src/processing/app/debug/Compiler.java b/app/src/processing/app/debug/Compiler.java
new file mode 100644
index 000000000..eae1910df
--- /dev/null
+++ b/app/src/processing/app/debug/Compiler.java
@@ -0,0 +1,692 @@
+/* -*- 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.Preferences;
+import processing.app.Sketch;
+import processing.app.SketchCode;
+import processing.core.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+
+public class Compiler implements MessageConsumer {
+ static final String BUGS_URL =
+ "https://developer.berlios.de/bugs/?group_id=3590";
+ static final String SUPER_BADNESS =
+ "Compiler error, please submit this code to " + BUGS_URL;
+
+ Sketch sketch;
+ String buildPath;
+ String primaryClassName;
+
+ RunnerException exception;
+
+ public Compiler() { }
+
+ /**
+ * Compile with avr-gcc.
+ *
+ * @param sketch Sketch object to be compiled.
+ * @param buildPath Where the temporary files live and will be built from.
+ * @param primaryClassName the name of the combined sketch file w/ extension
+ * @param target the target (core) to build against
+ * @return true if successful.
+ * @throws RunnerException Only if there's a problem. Only then.
+ */
+ public boolean compile(Sketch sketch,
+ String buildPath,
+ String primaryClassName,
+ Target target) throws RunnerException {
+ this.sketch = sketch;
+ this.buildPath = buildPath;
+ this.primaryClassName = primaryClassName;
+
+ // the pms object isn't used for anything but storage
+ MessageStream pms = new MessageStream(this);
+
+ String avrBasePath = Base.getAvrBasePath();
+
+ List objectFiles = new ArrayList();
+
+ List includePaths = new ArrayList();
+ includePaths.add(target.getPath());
+
+ String runtimeLibraryName = buildPath + File.separator + "core.a";
+
+ // 1. compile the target (core), outputting .o files to and
+ // then collecting them into the core.a library file.
+
+ List targetObjectFiles =
+ compileFiles(avrBasePath, buildPath, includePaths,
+ findFilesInPath(target.getPath(), "c", true),
+ findFilesInPath(target.getPath(), "cpp", true));
+
+ List baseCommandAR = new ArrayList(Arrays.asList(new String[] {
+ avrBasePath + "avr-ar",
+ "rcs",
+ runtimeLibraryName
+ }));
+
+ for(File file : targetObjectFiles) {
+ List commandAR = new ArrayList(baseCommandAR);
+ commandAR.add(file.getAbsolutePath());
+ execAsynchronously(commandAR);
+ }
+
+ // 2. compile the libraries, outputting .o files to: //
+
+ // use library directories as include paths for all libraries
+ for (File file : sketch.getImportedLibraries()) {
+ includePaths.add(file.getPath());
+ }
+
+ for (File libraryFolder : sketch.getImportedLibraries()) {
+ File outputFolder = new File(buildPath, libraryFolder.getName());
+ createFolder(outputFolder);
+ // this library can use includes in its utility/ folder
+ includePaths.add(libraryFolder.getPath() + File.separator + "utility");
+ objectFiles.addAll(
+ compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths,
+ findFilesInFolder(libraryFolder, "c", false),
+ findFilesInFolder(libraryFolder, "cpp", false)));
+ outputFolder = new File(outputFolder, "utility");
+ createFolder(outputFolder);
+ objectFiles.addAll(
+ compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths,
+ findFilesInFolder(new File(libraryFolder, "utility"), "c", false),
+ findFilesInFolder(new File(libraryFolder, "utility"), "cpp", false)));
+ // other libraries should not see this library's utility/ folder
+ includePaths.remove(includePaths.size() - 1);
+ }
+
+ // 3. compile the sketch (already in the buildPath)
+
+ objectFiles.addAll(
+ compileFiles(avrBasePath, buildPath, includePaths,
+ findFilesInPath(buildPath, "c", false),
+ findFilesInPath(buildPath, "cpp", false)));
+
+ // 4. link it all together into the .elf file
+
+ List baseCommandLinker = new ArrayList(Arrays.asList(new String[] {
+ avrBasePath + "avr-gcc",
+ "-Os",
+ "-Wl,--gc-sections",
+ "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
+ "-o",
+ buildPath + File.separator + primaryClassName + ".elf"
+ }));
+
+ for (File file : objectFiles) {
+ baseCommandLinker.add(file.getAbsolutePath());
+ }
+
+ baseCommandLinker.add(runtimeLibraryName);
+ baseCommandLinker.add("-L" + buildPath);
+ baseCommandLinker.add("-lm");
+
+ execAsynchronously(baseCommandLinker);
+
+ List baseCommandObjcopy = new ArrayList(Arrays.asList(new String[] {
+ avrBasePath + "avr-objcopy",
+ "-O",
+ "-R",
+ }));
+
+ List commandObjcopy;
+
+ // 5. extract EEPROM data (from EEMEM directive) to .eep file.
+ commandObjcopy = new ArrayList(baseCommandObjcopy);
+ commandObjcopy.add(2, "ihex");
+ commandObjcopy.set(3, "-j");
+ commandObjcopy.add(".eeprom");
+ commandObjcopy.add("--set-section-flags=.eeprom=alloc,load");
+ commandObjcopy.add("--no-change-warnings");
+ commandObjcopy.add("--change-section-lma");
+ commandObjcopy.add(".eeprom=0");
+ commandObjcopy.add(buildPath + File.separator + primaryClassName + ".elf");
+ commandObjcopy.add(buildPath + File.separator + primaryClassName + ".eep");
+ execAsynchronously(commandObjcopy);
+
+ // 6. build the .hex file
+ commandObjcopy = new ArrayList(baseCommandObjcopy);
+ commandObjcopy.add(2, "ihex");
+ commandObjcopy.add(".eeprom"); // remove eeprom data
+ commandObjcopy.add(buildPath + File.separator + primaryClassName + ".elf");
+ commandObjcopy.add(buildPath + File.separator + primaryClassName + ".hex");
+ execAsynchronously(commandObjcopy);
+
+ return true;
+ }
+
+
+ private List compileFiles(String avrBasePath,
+ String buildPath, List includePaths,
+ List cSources, List cppSources)
+ throws RunnerException {
+
+ List objectPaths = new ArrayList();
+
+ for (File file : cSources) {
+ String objectPath = buildPath + File.separator + file.getName() + ".o";
+ objectPaths.add(new File(objectPath));
+ execAsynchronously(getCommandCompilerC(avrBasePath, includePaths,
+ file.getAbsolutePath(),
+ objectPath));
+ }
+
+ for (File file : cppSources) {
+ String objectPath = buildPath + File.separator + file.getName() + ".o";
+ objectPaths.add(new File(objectPath));
+ execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths,
+ file.getAbsolutePath(),
+ objectPath));
+ }
+
+ return objectPaths;
+ }
+
+
+ boolean firstErrorFound;
+ boolean secondErrorFound;
+
+ /**
+ * Either succeeds or throws a RunnerException fit for public consumption.
+ */
+ private void execAsynchronously(List commandList) throws RunnerException {
+ String[] command = new String[commandList.size()];
+ commandList.toArray(command);
+ int result = 0;
+
+ if (Preferences.getBoolean("build.verbose")) {
+ for(int j = 0; j < command.length; j++) {
+ System.out.print(command[j] + " ");
+ }
+ System.out.println();
+ }
+
+ firstErrorFound = false; // haven't found any errors yet
+ secondErrorFound = false;
+
+ Process process;
+
+ try {
+ process = Runtime.getRuntime().exec(command);
+ } catch (IOException e) {
+ RunnerException re = new RunnerException(e.getMessage());
+ re.hideStackTrace();
+ throw re;
+ }
+
+ MessageSiphon in = new MessageSiphon(process.getInputStream(), this);
+ MessageSiphon err = new MessageSiphon(process.getErrorStream(), this);
+
+ // wait for the process to finish. if interrupted
+ // before waitFor returns, continue waiting
+ boolean compiling = true;
+ while (compiling) {
+ try {
+ if (in.thread != null)
+ in.thread.join();
+ if (err.thread != null)
+ err.thread.join();
+ result = process.waitFor();
+ //System.out.println("result is " + result);
+ compiling = false;
+ } catch (InterruptedException ignored) { }
+ }
+
+ // an error was queued up by message(), barf this back to compile(),
+ // which will barf it back to Editor. if you're having trouble
+ // discerning the imagery, consider how cows regurgitate their food
+ // to digest it, and the fact that they have five stomaches.
+ //
+ //System.out.println("throwing up " + exception);
+ if (exception != null) { throw exception; }
+
+ if (result > 1) {
+ // a failure in the tool (e.g. unable to locate a sub-executable)
+ System.err.println(command[0] + " returned " + result);
+ }
+
+ if (result != 0) {
+ RunnerException re = new RunnerException("Error compiling.");
+ re.hideStackTrace();
+ throw re;
+ }
+ }
+
+
+ /**
+ * Part of the MessageConsumer interface, this is called
+ * whenever a piece (usually a line) of error message is spewed
+ * out from the compiler. The errors are parsed for their contents
+ * and line number, which is then reported back to Editor.
+ */
+ public void message(String s) {
+ // This receives messages as full lines, so a newline needs
+ // to be added as they're printed to the console.
+ //System.err.print(s);
+
+ // ignore cautions
+ if (s.indexOf("warning") != -1) return;
+
+ // ignore this line; the real error is on the next one
+ if (s.indexOf("In file included from") != -1) return;
+
+ // jikes always uses a forward slash character as its separator,
+ // so replace any platform-specific separator characters before
+ // attemping to compare
+ //
+ //String buildPathSubst = buildPath.replace(File.separatorChar, '/') + "/";
+ String buildPathSubst = buildPath.replace(File.separatorChar,File.separatorChar) + File.separatorChar;
+
+ String partialTempPath = null;
+ int partialStartIndex = -1; //s.indexOf(partialTempPath);
+ int fileIndex = -1; // use this to build a better exception
+
+ // check the main sketch file first.
+ partialTempPath = buildPathSubst + primaryClassName;
+ partialStartIndex = s.indexOf(partialTempPath);
+
+ if (partialStartIndex != -1) {
+ fileIndex = 0;
+ } else {
+ // wasn't there, check the other (non-pde) files in the sketch.
+ // iterate through the project files to see who's causing the trouble
+ for (int i = 0; i < sketch.getCodeCount(); i++) {
+ if (sketch.getCode(i).isExtension("pde")) continue;
+
+ partialTempPath = buildPathSubst + sketch.getCode(i).getFileName();
+ //System.out.println(partialTempPath);
+ partialStartIndex = s.indexOf(partialTempPath);
+ if (partialStartIndex != -1) {
+ fileIndex = i;
+ //System.out.println("fileIndex is " + fileIndex);
+ break;
+ }
+ }
+ //+ className + ".java";
+ }
+
+ // if the partial temp path appears in the error message...
+ //
+ //int partialStartIndex = s.indexOf(partialTempPath);
+ if (partialStartIndex != -1) {
+
+ // skip past the path and parse the int after the first colon
+ //
+ String s1 = s.substring(partialStartIndex +
+ partialTempPath.length() + 1);
+ //System.out.println(s1);
+ int colon = s1.indexOf(':');
+
+ if (s1.indexOf("In function") != -1 || colon == -1) {
+ System.err.print(s1);
+ //firstErrorFound = true;
+ return;
+ }
+
+ int lineNumber;
+ try {
+ lineNumber = Integer.parseInt(s1.substring(0, colon));
+ } catch (NumberFormatException e) {
+ System.err.print(s1);
+ return;
+ }
+
+ //System.out.println("pde / line number: " + lineNumber);
+
+ if (fileIndex == 0) { // main class, figure out which tab
+ for (int i = 1; i < sketch.getCodeCount(); i++) {
+ if (sketch.getCode(i).isExtension("pde")) {
+ //System.out.println("preprocOffset "+ sketch.getCode(i).getPreprocOffset());
+ if (sketch.getCode(i).getPreprocOffset() < lineNumber) {
+ fileIndex = i;
+ //System.out.println("i'm thinkin file " + i);
+ }
+ }
+ }
+ // XXX: DAM: if the lineNumber is less than sketch.getCode(0).getPreprocOffset()
+ // we shouldn't subtract anything from it, as the error is above the
+ // location where the function prototypes and #include "WProgram.h"
+ // were inserted.
+ lineNumber -= sketch.getCode(fileIndex).getPreprocOffset();
+ }
+
+ //String s2 = s1.substring(colon + 2);
+ int err = s1.indexOf(":");
+ if (err != -1) {
+
+ // if the first error has already been found, then this must be
+ // (at least) the second error found
+ if (firstErrorFound) {
+ secondErrorFound = true;
+ return;
+ }
+
+ // if executing at this point, this is *at least* the first error
+ firstErrorFound = true;
+
+ err += ":".length();
+ String description = s1.substring(err);
+ description = description.trim();
+ System.err.print(description);
+
+ //System.out.println("description = " + description);
+ //System.out.println("creating exception " + exception);
+ exception = new RunnerException(description, fileIndex, lineNumber-1, -1, false);
+
+ // NOTE!! major change here, this exception will be queued
+ // here to be thrown by the compile() function
+ //editor.error(exception);
+
+ } else {
+ System.err.println("i suck: " + s);
+ }
+
+ } else {
+ // this isn't the start of an error line, so don't attempt to parse
+ // a line number out of it.
+
+ // if the second error hasn't been discovered yet, these lines
+ // are probably associated with the first error message,
+ // which is already in the status bar, and are likely to be
+ // of interest to the user, so spit them to the console.
+ //
+ if (!secondErrorFound) {
+ System.err.println(s);
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ static private List getCommandCompilerC(String avrBasePath, List includePaths,
+ String sourceName, String objectName) {
+ List baseCommandCompiler = new ArrayList(Arrays.asList(new String[] {
+ avrBasePath + "avr-gcc",
+ "-c", // compile, don't link
+ "-g", // include debugging info (so errors include line numbers)
+ "-Os", // optimize for size
+ "-w", // surpress all warnings
+ "-ffunction-sections", // place each function in its own section
+ "-fdata-sections",
+ "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
+ "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
+ }));
+
+ for (int i = 0; i < includePaths.size(); i++) {
+ baseCommandCompiler.add("-I" + (String) includePaths.get(i));
+ }
+
+ baseCommandCompiler.add(sourceName);
+ baseCommandCompiler.add("-o"+ objectName);
+
+ return baseCommandCompiler;
+ }
+
+
+ static private List getCommandCompilerCPP(String avrBasePath,
+ List includePaths, String sourceName, String objectName) {
+ List baseCommandCompilerCPP = new ArrayList(Arrays.asList(new String[] {
+ avrBasePath + "avr-g++",
+ "-c", // compile, don't link
+ "-g", // include debugging info (so errors include line numbers)
+ "-Os", // optimize for size
+ "-w", // surpress all warnings
+ "-fno-exceptions",
+ "-ffunction-sections", // place each function in its own section
+ "-fdata-sections",
+ "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
+ "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
+ }));
+
+ for (int i = 0; i < includePaths.size(); i++) {
+ baseCommandCompilerCPP.add("-I" + (String) includePaths.get(i));
+ }
+
+ baseCommandCompilerCPP.add(sourceName);
+ baseCommandCompilerCPP.add("-o"+ objectName);
+
+ return baseCommandCompilerCPP;
+ }
+
+
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ static private void createFolder(File folder) throws RunnerException {
+ if (folder.isDirectory()) return;
+ if (!folder.mkdir())
+ throw new RunnerException("Couldn't create: " + folder);
+ }
+
+ /**
+ * Given a folder, return a list of the header files in that folder (but
+ * not the header files in its sub-folders, as those should be included from
+ * within the header files at the top-level).
+ */
+ static public String[] headerListFromIncludePath(String path) {
+ FilenameFilter onlyHFiles = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".h");
+ }
+ };
+
+ return (new File(path)).list(onlyHFiles);
+ }
+
+ static public ArrayList findFilesInPath(String path, String extension,
+ boolean recurse) {
+ return findFilesInFolder(new File(path), extension, recurse);
+ }
+
+ static public ArrayList findFilesInFolder(File folder, String extension,
+ boolean recurse) {
+ ArrayList files = new ArrayList();
+
+ if (folder.listFiles() == null) return files;
+
+ for (File file : folder.listFiles()) {
+ if (file.getName().equals(".") || file.getName().equals("..")) continue;
+
+ if (file.getName().endsWith("." + extension))
+ files.add(file);
+
+ if (recurse && file.isDirectory()) {
+ files.addAll(findFilesInFolder(file, extension, true));
+ }
+ }
+
+ return files;
+ }
+
+ /**
+ * 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;
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/processing/app/debug/EventThread.java b/app/src/processing/app/debug/EventThread.java
new file mode 100644
index 000000000..918600f1f
--- /dev/null
+++ b/app/src/processing/app/debug/EventThread.java
@@ -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 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 0) {
+ String pieces[] = PApplet.split(options, ' ');
+ for (int i = 0; i < pieces.length; i++) {
+ String p = pieces[i].trim();
+ if (p.length() > 0) {
+ params.add(p);
+ }
+ }
+ }
+
+// params.add("-Djava.ext.dirs=nuffing");
+
+ if (Preferences.getBoolean("run.options.memory")) {
+ params.add("-Xms" + Preferences.get("run.options.memory.initial") + "m");
+ params.add("-Xmx" + Preferences.get("run.options.memory.maximum") + "m");
+ }
+
+ if (Base.isMacOS()) {
+ params.add("-Xdock:name=" + appletClassName);
+// params.add("-Dcom.apple.mrj.application.apple.menu.about.name=" +
+// sketch.getMainClassName());
+ }
+ // sketch.libraryPath might be ""
+ // librariesClassPath will always have sep char prepended
+ params.add("-Djava.library.path=" +
+ sketch.getLibraryPath() +
+ File.pathSeparator +
+ System.getProperty("java.library.path"));
+
+ params.add("-cp");
+ params.add(sketch.getClassPath());
+// params.add(sketch.getClassPath() +
+// File.pathSeparator +
+// Base.librariesClassPath);
+
+ //PApplet.println(PApplet.split(sketch.classPath, ':'));
+
+ String outgoing[] = new String[params.size()];
+ params.toArray(outgoing);
+
+ //PApplet.println(outgoing);
+// PApplet.println(PApplet.split(outgoing[0], ":"));
+// PApplet.println();
+// PApplet.println("class path");
+// PApplet.println(PApplet.split(outgoing[2], ":"));
+
+ return outgoing;
+ //return (String[]) params.toArray();
+
+// System.out.println("sketch class path");
+// PApplet.println(PApplet.split(sketch.classPath, ';'));
+// System.out.println();
+// System.out.println("libraries class path");
+// PApplet.println(PApplet.split(Base.librariesClassPath, ';'));
+// System.out.println();
+ }
+
+
+ protected String[] getSketchParams() {
+ ArrayList params = new ArrayList();
+
+ params.add("processing.core.PApplet");
+
+ // If there was a saved location (this guy has been run more than once)
+ // then the location will be set to the last position of the sketch window.
+ // This will be passed to the PApplet runner using something like
+ // --location=30,20
+ // Otherwise, the editor location will be passed, and the applet will
+ // figure out where to place itself based on the editor location.
+ // --editor-location=150,20
+ if (editor != null) { // if running processing-cmd, don't do placement
+ Point windowLocation = editor.getSketchLocation();
+ if (windowLocation != null) {
+ params.add(PApplet.ARGS_LOCATION + "=" +
+ windowLocation.x + "," + windowLocation.y);
+ } else {
+ Point editorLocation = editor.getLocation();
+ params.add(PApplet.ARGS_EDITOR_LOCATION + "=" +
+ editorLocation.x + "," + editorLocation.y);
+ }
+ params.add(PApplet.ARGS_EXTERNAL);
+ }
+
+ params.add(PApplet.ARGS_DISPLAY + "=" +
+ Preferences.get("run.display"));
+ params.add(PApplet.ARGS_SKETCH_FOLDER + "=" +
+ sketch.getFolder().getAbsolutePath());
+
+ if (presenting) {
+ params.add(PApplet.ARGS_PRESENT);
+ if (Preferences.getBoolean("run.present.exclusive")) {
+ params.add(PApplet.ARGS_EXCLUSIVE);
+ }
+ params.add(PApplet.ARGS_STOP_COLOR + "=" +
+ Preferences.get("run.present.stop.color"));
+ params.add(PApplet.ARGS_BGCOLOR + "=" +
+ Preferences.get("run.present.bgcolor"));
+ }
+
+ params.add(appletClassName);
+
+// String outgoing[] = new String[params.size()];
+// params.toArray(outgoing);
+// return outgoing;
+ return (String[]) params.toArray(new String[0]);
+ }
+
+
+ /*
+ protected VirtualMachine launchVirtualMachine_sun(String[] vmParams, String[] classParams) {
+ //vm = launchTarget(sb.toString());
+ LaunchingConnector connector =
+ findLaunchingConnector("com.sun.jdi.CommandLineLaunch");
+ //Map arguments = connectorArguments(connector, mainArgs);
+
+ PApplet.println(connector); // gets the defaults
+
+ Map arguments = connector.defaultArguments();
+ //System.out.println(arguments);
+
+// for (Iterator itr = arguments.keySet().iterator(); itr.hasNext(); ) {
+// Connector.Argument argument =
+// (Connector.Argument) arguments.get(itr.next());
+// System.out.println(argument);
+// }
+
+ //connector.transport().
+
+ Connector.Argument mainArg =
+ (Connector.Argument)arguments.get("main");
+ if (mainArg == null) {
+ throw new Error("Bad launching connector");
+ }
+ String mainArgs = "";
+ //mainArgs = addArgument(mainArgs, className);
+ if (classParams != null) {
+ for (int i = 0; i < classParams.length; i++) {
+ mainArgs = addArgument(mainArgs, classParams[i], ' ');
+ }
+ }
+ mainArg.setValue(mainArgs);
+
+ //System.out.println("main args are: ");
+ //System.out.println(mainArgs);
+
+// if (watchFields) {
+// // We need a VM that supports watchpoints
+// Connector.Argument optionArg =
+// (Connector.Argument)arguments.get("options");
+// if (optionArg == null) {
+// throw new Error("Bad launching connector");
+// }
+// optionArg.setValue("-classic");
+// }
+ String optionArgs = "";
+ for (int i = 0; i < vmParams.length; i++) {
+ optionArgs = addArgument(optionArgs, vmParams[i], ' ');
+ }
+ // prevent any incorrect transport address b.s. from being added
+ // -Xrunjdwp:transport=dt_socket,address=cincinnati118.ipcorporate.com:55422,suspend=y
+ //optionArgs = addArgument(optionArgs, "-agentlib:jdwp=transport=dt_socket,address=localhost:12345,suspend=y", ' ');
+ //optionArgs += " -Xrunjdwp:transport=dt_socket,address=localhost:55422,suspend=y";
+ //optionArgs = optionArgs + " -agentlib:jdwp=transport=dt_socket";
+ //optionArgs = addArgument(optionArgs, "-Xrunjdwp:transport=dt_socket,address=localhost:55422,suspend=y", ' ');
+
+ //optionArgs = addArgument(optionArgs, "address=127.0.0.1:54321", ' ');
+ //optionArgs = addArgument(optionArgs, "localAddress", ' ');
+
+ Connector.Argument optionArg =
+ (Connector.Argument)arguments.get("options");
+ optionArg.setValue(optionArgs);
+
+// Connector.Argument addressArg =
+// (Connector.Argument)arguments.get("address");
+ //arguments.put("raw.address", new Connector.Argument("blah"));
+ //PApplet.println("it's gonna be " + addressArg);
+
+ //arguments.put("address", "localhost");
+
+// Connector.Argument addressArg =
+// (Connector.Argument)arguments.get("address");
+// addressArg.setValue("localhost");
+
+// System.out.println("option args are: ");
+// System.out.println(arguments.get("options"));
+
+ System.out.println("args are " + arguments);
+
+ // com.sun.tools.jdi.SunCommandLineLauncher
+
+ // http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html#sunlaunch
+ try {
+ return connector.launch(arguments);
+ } catch (IOException exc) {
+ throw new Error("Unable to launch target VM: " + exc);
+ } catch (IllegalConnectorArgumentsException exc) {
+ throw new Error("Internal error: " + exc);
+ } catch (VMStartException exc) {
+ exc.printStackTrace();
+ System.err.println();
+ System.err.println("Could not run the sketch.");
+ System.err.println("Make sure that you haven't set the maximum available memory too high.");
+ System.err.println("For more information, read revisions.txt and Help -> Troubleshooting.");
+ //System.err.println("Target VM failed to initialize:");
+ //System.err.println("msg is " + exc.getMessage());
+ //exc.printStackTrace();
+ //throw new Error("Target VM failed to initialize: " +
+ //exc.getMessage());
+ //throw new Error(exc.getMessage());
+ //throw new RunnerException(exc.getMessage());
+ //editor.error(exc);
+ editor.error("Could not run the sketch.");
+ return null;
+ }
+ }
+ */
+
+
+ protected VirtualMachine launchVirtualMachine(String[] vmParams,
+ String[] classParams) {
+ //vm = launchTarget(sb.toString());
+ LaunchingConnector connector =
+ findLaunchingConnector("com.sun.jdi.RawCommandLineLaunch");
+ //PApplet.println(connector); // gets the defaults
+
+ //Map arguments = connectorArguments(connector, mainArgs);
+ Map arguments = connector.defaultArguments();
+
+ Connector.Argument commandArg =
+ (Connector.Argument)arguments.get("command");
+ // Using localhost instead of 127.0.0.1 sometimes causes a
+ // "Transport Error 202" error message when trying to run.
+ // http://dev.processing.org/bugs/show_bug.cgi?id=895
+ String addr = "127.0.0.1:" + (8000 + (int) (Math.random() * 1000));
+ //String addr = "localhost:" + (8000 + (int) (Math.random() * 1000));
+ //String addr = "" + (8000 + (int) (Math.random() * 1000));
+
+ String commandArgs = Base.isWindows() ?
+ "java -Xrunjdwp:transport=dt_shmem,address=" + addr + ",suspend=y " :
+ "java -Xrunjdwp:transport=dt_socket,address=" + addr + ",suspend=y ";
+ //String commandArgs = "java -agentlib:jdwp=transport=dt_socket,address=" + addr + ",suspend=y ";
+ //String commandArgs = "java -agentlib:jdwp=transport=dt_socket,address=" + addr + ",server=n,suspend=y ";
+ for (int i = 0; i < vmParams.length; i++) {
+ commandArgs = addArgument(commandArgs, vmParams[i], ' ');
+ }
+ if (classParams != null) {
+ for (int i = 0; i < classParams.length; i++) {
+ commandArgs = addArgument(commandArgs, classParams[i], ' ');
+ }
+ }
+ commandArg.setValue(commandArgs);
+
+ Connector.Argument addressArg =
+ (Connector.Argument)arguments.get("address");
+ addressArg.setValue(addr);
+
+ //PApplet.println(connector); // prints the current
+ //com.sun.tools.jdi.AbstractLauncher al;
+ //com.sun.tools.jdi.RawCommandLineLauncher rcll;
+
+ //System.out.println(PApplet.javaVersion);
+ // http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html#sunlaunch
+ try {
+ return connector.launch(arguments);
+ } catch (IOException exc) {
+ throw new Error("Unable to launch target VM: " + exc);
+ } catch (IllegalConnectorArgumentsException exc) {
+ throw new Error("Internal error: " + exc);
+ } catch (VMStartException exc) {
+ Process p = exc.process();
+ //System.out.println(p);
+ String[] errorStrings = PApplet.loadStrings(p.getErrorStream());
+ /*String[] inputStrings =*/ PApplet.loadStrings(p.getInputStream());
+
+ if (errorStrings != null && errorStrings.length > 1) {
+ if (errorStrings[0].indexOf("Invalid maximum heap size") != -1) {
+ Base.showWarning("Way Too High",
+ "Please lower the value for \u201Cmaximum available memory\u201D in the\n" +
+ "Preferences window. For more information, read Help \u2192 Troubleshooting.",
+ exc);
+ } else {
+ PApplet.println(errorStrings);
+ System.err.println("Using startup command:");
+ PApplet.println(arguments);
+ }
+ } else {
+ exc.printStackTrace();
+ System.err.println("Could not run the sketch (Target VM failed to initialize).");
+ if (Preferences.getBoolean("run.options.memory")) {
+ // Only mention this if they've even altered the memory setup
+ System.err.println("Make sure that you haven't set the maximum available memory too high.");
+ }
+ System.err.println("For more information, read revisions.txt and Help \u2192 Troubleshooting.");
+ }
+ if (editor != null) {
+ listener.statusError("Could not run the sketch.");
+ }
+ return null;
+ }
+ }
+
+
+ private static boolean hasWhitespace(String string) {
+ int length = string.length();
+ for (int i = 0; i < length; i++) {
+ if (Character.isWhitespace(string.charAt(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private static String addArgument(String string, String argument, char sep) {
+ if (hasWhitespace(argument) || argument.indexOf(',') != -1) {
+ // Quotes were stripped out for this argument, add 'em back.
+ StringBuffer buffer = new StringBuffer(string);
+ buffer.append('"');
+ for (int i = 0; i < argument.length(); i++) {
+ char c = argument.charAt(i);
+ if (c == '"') {
+ buffer.append('\\');
+ }
+ buffer.append(c);
+ }
+ buffer.append('\"');
+ buffer.append(sep);
+ return buffer.toString();
+ } else {
+ return string + argument + String.valueOf(sep);
+ }
+ }
+
+
+ /**
+ * Generate the trace.
+ * Enable events, start thread to display events,
+ * start threads to forward remote error and output streams,
+ * resume the remote VM, wait for the final event, and shutdown.
+ */
+ void generateTrace(PrintWriter writer) {
+ vm.setDebugTraceMode(debugTraceMode);
+
+ EventThread eventThread = null;
+ //if (writer != null) {
+ eventThread = new EventThread(this, vm, excludes, writer);
+ eventThread.setEventRequests(watchFields);
+ eventThread.start();
+ //}
+
+ //redirectOutput();
+
+ Process process = vm.process();
+
+// processInput = new SystemOutSiphon(process.getInputStream());
+// processError = new MessageSiphon(process.getErrorStream(), this);
+
+ // Copy target's output and error to our output and error.
+// errThread = new StreamRedirectThread("error reader",
+// process.getErrorStream(),
+// System.err);
+ MessageSiphon ms = new MessageSiphon(process.getErrorStream(), this);
+ errThread = ms.thread;
+
+ outThread = new StreamRedirectThread("output reader",
+ process.getInputStream(),
+ System.out);
+
+ errThread.start();
+ outThread.start();
+
+ vm.resume();
+ //System.out.println("done with resume");
+
+ // Shutdown begins when event thread terminates
+ try {
+ if (eventThread != null) eventThread.join();
+ // Bug #852 tracked to this next line in the code.
+ // http://dev.processing.org/bugs/show_bug.cgi?id=852
+ errThread.join(); // Make sure output is forwarded
+ outThread.join(); // before we exit
+ //System.out.println("out of it");
+
+ // At this point, disable the run button.
+ // This happens when the sketch is exited by hitting ESC,
+ // or the user manually closes the sketch window.
+ // TODO this should be handled better, should it not?
+ if (editor != null) {
+ editor.internalRunnerClosed();
+ }
+
+ } catch (InterruptedException exc) {
+ // we don't interrupt
+ }
+ //System.out.println("and leaving");
+ if (writer != null) writer.close();
+ }
+
+
+ /**
+ * Find a com.sun.jdi.CommandLineLaunch connector
+ */
+ LaunchingConnector findLaunchingConnector(String connectorName) {
+ //VirtualMachineManager mgr = Bootstrap.virtualMachineManager();
+
+ // Get the default connector.
+ // Not useful here since they all need different args.
+// System.out.println(Bootstrap.virtualMachineManager().defaultConnector());
+// return Bootstrap.virtualMachineManager().defaultConnector();
+
+ List connectors = Bootstrap.virtualMachineManager().allConnectors();
+
+ // code to list available connectors
+// Iterator iter2 = connectors.iterator();
+// while (iter2.hasNext()) {
+// Connector connector = (Connector)iter2.next();
+// System.out.println("connector name is " + connector.name());
+// }
+
+ Iterator iter = connectors.iterator();
+ while (iter.hasNext()) {
+ Connector connector = (Connector)iter.next();
+ if (connector.name().equals(connectorName)) {
+ return (LaunchingConnector)connector;
+ }
+ }
+ throw new Error("No launching connector");
+ }
+
+
+ public void exception(ExceptionEvent event) {
+ ObjectReference or = event.exception();
+ ReferenceType rt = or.referenceType();
+ String exceptionName = rt.name();
+ //Field messageField = Throwable.class.getField("detailMessage");
+ Field messageField = rt.fieldByName("detailMessage");
+// System.out.println("field " + messageField);
+ Value messageValue = or.getValue(messageField);
+// System.out.println("mess val " + messageValue);
+
+ int last = exceptionName.lastIndexOf('.');
+ String message = exceptionName.substring(last + 1);
+ if (messageValue != null) {
+ String messageStr = messageValue.toString();
+ if (messageStr.startsWith("\"")) {
+ messageStr = messageStr.substring(1, messageStr.length() - 1);
+ }
+ message += ": " + messageStr;
+ }
+// System.out.println("mess type " + messageValue.type());
+ //StringReference messageReference = (StringReference) messageValue.type();
+
+// System.out.println(or.referenceType().fields());
+// if (name.startsWith("java.lang.")) {
+// name = name.substring(10);
+ if (exceptionName.equals("java.lang.OutOfMemoryError")) {
+ listener.statusError("OutOfMemoryError: You may need to increase the memory setting in Preferences.");
+ System.err.println("An OutOfMemoryError means that your code is either using up too much memory");
+ System.err.println("because of a bug (e.g. creating an array that's too large, or unintentionally");
+ System.err.println("loading thousands of images), or that your sketch may need more memory to run.");
+ System.err.println("If your sketch uses a lot of memory (for instance if it loads a lot of data files)");
+ System.err.println("you can increase the memory available to your sketch using the Preferences window.");
+
+ } else if (exceptionName.equals("java.lang.StackOverflowError")) {
+ listener.statusError("StackOverflowError: This sketch is attempting too much recursion.");
+ System.err.println("A StackOverflowError means that you have a bug that's causing a function");
+ System.err.println("to be called recursively (it's calling itself and going in circles),");
+ System.err.println("or you're intentionally calling a recursive function too much,");
+ System.err.println("and your code should be rewritten in a more efficient manner.");
+
+ } else if (exceptionName.equals("java.lang.UnsupportedClassVersionError")) {
+ listener.statusError("UnsupportedClassVersionError: A library is using code compiled with an unsupported version of Java.");
+ System.err.println("This version of Processing only supports libraries and JAR files compiled for Java 1.5.");
+ System.err.println("A library used by this sketch was compiled for Java 1.6 or later, ");
+ System.err.println("and needs to be recompiled to be compatible with Java 1.5.");
+
+ } else if (exceptionName.equals("java.lang.NoSuchMethodError") || exceptionName.equals("java.lang.NoSuchFieldError")) {
+ listener.statusError(exceptionName.substring(10) + ": You're probably using a library that's incompatible with this version of Processing.");
+
+ } else if (message.equals("ClassNotFoundException: quicktime.std.StdQTException")) {
+ listener.statusError("Could not find QuickTime, please reinstall QuickTime 7 or later.");
+
+ } else {
+ reportException(message, event.thread());
+ }
+ editor.internalRunnerClosed();
+ }
+
+
+ // This may be called more than one time per error in the VM,
+ // presumably because exceptions might be wrapped inside others,
+ // and this will fire for both.
+ protected void reportException(String message, ThreadReference thread) {
+ try {
+ int codeIndex = -1;
+ int lineNumber = -1;
+
+ // Any of the thread.blah() methods can throw an AbsentInformationEx
+ // if that bit of data is missing. If so, just write out the error
+ // message to the console.
+ List frames = thread.frames();
+ for (StackFrame frame : frames) {
+ //System.out.println("frame: " + frame);
+ Location location = frame.location();
+ String filename = null;
+ filename = location.sourceName();
+ lineNumber = location.lineNumber();
+
+ String appletJavaFile = appletClassName + ".java";
+ SketchCode errorCode = null;
+ if (filename.equals(appletJavaFile)) {
+ for (SketchCode code : sketch.getCode()) {
+ if (code.isExtension("pde")) {
+ if (lineNumber >= code.getPreprocOffset()) {
+ errorCode = code;
+ }
+ }
+ }
+ } else {
+ for (SketchCode code : sketch.getCode()) {
+ if (code.isExtension("java")) {
+ if (filename.equals(code.getFileName())) {
+ errorCode = code;
+ }
+ }
+ }
+ }
+ codeIndex = sketch.getCodeIndex(errorCode);
+
+ if (codeIndex != -1) {
+ //System.out.println("got line num " + lineNumber);
+ // in case this was a tab that got embedded into the main .java
+ lineNumber -= sketch.getCode(codeIndex).getPreprocOffset();
+
+ // lineNumber is 1-indexed, but editor wants zero-indexed
+ lineNumber--;
+
+ // getMessage() will be what's shown in the editor
+ exception = new RunnerException(message, codeIndex, lineNumber, -1);
+ exception.hideStackTrace();
+ listener.statusError(exception);
+ return;
+ }
+ }
+ } catch (AbsentInformationException e) {
+ //e.printStackTrace(); // not useful
+ exception = new RunnerException(message);
+ exception.hideStackTrace();
+ listener.statusError(exception);
+
+ } catch (IncompatibleThreadStateException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void close() {
+ // TODO make sure stop() has already been called to exit the sketch
+
+ // TODO actually kill off the vm here
+ if (vm != null) {
+ try {
+ vm.exit(0);
+
+ } catch (com.sun.jdi.VMDisconnectedException vmde) {
+ // if the vm has disconnected on its own, ignore message
+ //System.out.println("harmless disconnect " + vmde.getMessage());
+ // TODO shouldn't need to do this, need to do more cleanup
+ }
+ vm = null;
+ }
+
+ //if (window != null) window.hide();
+// if (window != null) {
+// //System.err.println("disposing window");
+// window.dispose();
+// window = null;
+// }
+
+ /*
+ if (process != null) {
+ try {
+ process.destroy();
+ } catch (Exception e) {
+ //System.err.println("(ignored) error while destroying");
+ //e.printStackTrace();
+ }
+ process = null;
+ }
+ */
+ }
+
+
+ // made synchronized for rev 87
+ // attempted to remove synchronized for 0136 to fix bug #775 (no luck tho)
+ // http://dev.processing.org/bugs/show_bug.cgi?id=775
+ synchronized public void message(String s) {
+ //System.out.println("M" + s.length() + ":" + s.trim()); // + "MMM" + s.length());
+
+ // this eats the CRLFs on the lines.. oops.. do it later
+ //if (s.trim().length() == 0) return;
+
+ // this is PApplet sending a message (via System.out.println)
+ // that signals that the applet has been quit.
+ if (s.indexOf(PApplet.EXTERNAL_STOP) == 0) {
+ //System.out.println("external: quit");
+ editor.internalCloseRunner();
+ return;
+ }
+
+ // this is the PApplet sending us a message that the applet
+ // is being moved to a new window location
+ if (s.indexOf(PApplet.EXTERNAL_MOVE) == 0) {
+ String nums = s.substring(s.indexOf(' ') + 1).trim();
+ int space = nums.indexOf(' ');
+ int left = Integer.parseInt(nums.substring(0, space));
+ int top = Integer.parseInt(nums.substring(space + 1));
+ editor.setSketchLocation(new Point(left, top));
+ //System.out.println("external: move to " + left + " " + top);
+ return;
+ }
+
+ // Removed while doing cleaning for 0145,
+ // it seems that this is never actually printed out.
+ /*
+ // this is PApplet sending a message saying "i'm about to spew
+ // a stack trace because an error occurred during PApplet.run()"
+ if (s.indexOf(PApplet.LEECH_WAKEUP) == 0) {
+ // newMessage being set to 'true' means that the next time
+ // message() is called, expect the first line of the actual
+ // error message & stack trace to be sent from the applet.
+ newMessage = true;
+ return; // this line ignored
+ }
+ */
+
+ // these are used for debugging, in case there are concerns
+ // that some errors aren't coming through properly
+ /*
+ if (s.length() > 2) {
+ System.err.println(newMessage);
+ System.err.println("message " + s.length() + ":" + s);
+ }
+ */
+ // always shove out the mesage, since it might not fall under
+ // the same setup as we're expecting
+ System.err.print(s);
+ //System.err.println("[" + s.length() + "] " + s);
+ System.err.flush();
+
+// // exit here because otherwise the exception name
+// // may be titled with a blank string
+// if (s.trim().length() == 0) return;
+//
+// // annoying, because it seems as though the terminators
+// // aren't being sent properly
+// //System.err.println(s);
+//
+// //if (newMessage && s.length() > 2) {
+// if (newMessage) {
+// exception = new RunnerException(s); // type of java ex
+// exception.hideStackTrace();
+// //System.out.println("setting ex type to " + s);
+// newMessage = false;
+// foundMessageSource = false;
+// messageLineCount = 0;
+//
+// } else {
+// messageLineCount++;
+//
+// /*
+//java.lang.NullPointerException
+// at javatest.(javatest.java:5)
+// at Temporary_2425_1153.draw(Temporary_2425_1153.java:11)
+// at PApplet.nextFrame(PApplet.java:481)
+// at PApplet.run(PApplet.java:428)
+// at java.lang.Thread.run(Unknown Source)
+// */
+//
+// if (!foundMessageSource) {
+// // " at javatest.(javatest.java:5)"
+// // -> "javatest.(javatest.java:5)"
+// int atIndex = s.indexOf("at ");
+// if (atIndex == -1) {
+// //System.err.println(s); // stop double-printing exceptions
+// return;
+// }
+// s = s.substring(atIndex + 3);
+//
+// // added for 0124 to improve error handling
+// // not highlighting lines if it's in the p5 code
+// if (s.startsWith("processing.")) return;
+// // no highlight if it's java.lang.whatever
+// if (s.startsWith("java.")) return;
+//
+// // "javatest.(javatest.java:5)"
+// // -> "javatest." and "(javatest.java:5)"
+// int startParen = s.indexOf('(');
+// // at javatest.(javatest.java:5)
+// //String pkgClassFxn = null;
+// //String fileLine = null;
+// int codeIndex = -1;
+// int lineNumber = -1;
+//
+// if (startParen == -1) {
+// //pkgClassFxn = s;
+//
+// } else {
+// //pkgClassFxn = s.substring(0, startParen);
+//
+// // "(javatest.java:5)"
+// String fileAndLine = s.substring(startParen + 1);
+// int stopParen = fileAndLine.indexOf(')');
+// //fileAndLine = fileAndLine.substring(0, fileAndLine.length() - 1);
+// fileAndLine = fileAndLine.substring(0, stopParen);
+// //System.out.println("file 'n line " + fileAndLine);
+//
+// //if (!fileAndLine.equals("Unknown Source")) {
+// // "javatest.java:5"
+// int colonIndex = fileAndLine.indexOf(':');
+// if (colonIndex != -1) {
+// String filename = fileAndLine.substring(0, colonIndex);
+// // "javatest.java" and "5"
+// //System.out.println("filename = " + filename);
+// //System.out.println("pre0 = " + sketch.code[0].preprocName);
+// //for (int i = 0; i < sketch.codeCount; i++) {
+// //System.out.println(i + " " + sketch.code[i].lineOffset + " " +
+// // sketch.code[i].preprocName);
+// //}
+// lineNumber =
+// Integer.parseInt(fileAndLine.substring(colonIndex + 1)) - 1;
+//
+// for (int i = 0; i < sketch.getCodeCount(); i++) {
+// SketchCode code = sketch.getCode(i);
+// //System.out.println(code.preprocName + " " + lineNumber + " " +
+// // code.preprocOffset);
+// if (((code.preprocName == null) &&
+// (lineNumber >= code.preprocOffset)) ||
+// ((code.preprocName != null) &&
+// code.preprocName.equals(filename))) {
+// codeIndex = i;
+// //System.out.println("got codeindex " + codeIndex);
+// //break;
+// //} else if (
+// }
+// }
+//
+// if (codeIndex != -1) {
+// //System.out.println("got line num " + lineNumber);
+// // in case this was a tab that got embedded into the main .java
+// lineNumber -= sketch.getCode(codeIndex).preprocOffset;
+//
+// // this may have a paren on the end, if so need to strip
+// // down to just the digits
+// /*
+// int lastNumberIndex = colonIndex + 1;
+// while ((lastNumberIndex < fileAndLine.length()) &&
+// Character.isDigit(fileAndLine.charAt(lastNumberIndex))) {
+// lastNumberIndex++;
+// }
+// */
+//
+// // lineNumber is 1-indexed, but editor wants zero-indexed
+// // getMessage() will be what's shown in the editor
+// exception =
+// new RunnerException(exception.getMessage(),
+// codeIndex, lineNumber, -1);
+// exception.hideStackTrace();
+// foundMessageSource = true;
+// }
+// }
+// }
+// editor.error(exception);
+//
+// /*
+// int index = s.indexOf(className + ".java");
+// if (index != -1) {
+// int len = (className + ".java").length();
+// String lineNumberStr = s.substring(index + len + 1);
+// index = lineNumberStr.indexOf(')');
+// lineNumberStr = lineNumberStr.substring(0, index);
+// try {
+// exception.line = Integer.parseInt(lineNumberStr) - 1; //2;
+// } catch (NumberFormatException e) { }
+// //e.printStackTrace(); // a recursive error waiting to happen?
+// // if nfe occurs, who cares, still send the error on up
+// editor.error(exception);
+// */
+//
+// /*
+// // WARNING THESE ARE DISABLED!!
+// } else if ((index = s.indexOf(className + ".class")) != -1) {
+// // code to check for:
+// // at Temporary_484_3845.loop(Compiled Code)
+// // would also probably get:
+// // at Temporary_484_3845.loop
+// // which (i believe) is used by the mac and/or jview
+// String functionStr = s.substring(index +
+// (className + ".class").length() + 1);
+// index = functionStr.indexOf('(');
+// if (index != -1) {
+// functionStr = functionStr.substring(0, index);
+// }
+// exception = new RunnerException(//"inside \"" + functionStr + "()\": " +
+// exception.getMessage() +
+// " inside " + functionStr + "() " +
+// "[add Compiler.disable() to setup()]");
+// editor.error(exception);
+// // this will fall through in tihs example:
+// // at Temporary_4636_9696.pootie(Compiled Code)
+// // at Temporary_4636_9696.loop(Temporary_4636_9696.java:24)
+// // because pootie() (re)sets the exception title
+// // and throws it, but then the line number gets set
+// // because of the line that comes after
+// */
+//
+// } else if (messageLineCount > 10) { // 5 -> 10 for 0088
+// // this means the class name may not be mentioned
+// // in the stack trace.. this is just a general purpose
+// // error, but needs to make it through anyway.
+// // so if five lines have gone past, might as well signal
+// messageLineCount = -100;
+// exception = new RunnerException(exception.getMessage());
+// exception.hideStackTrace();
+// editor.error(exception);
+//
+// } else {
+// //System.err.print(s);
+// }
+// //System.out.println("got it " + s);
+// }
+ }
+
+
+ //////////////////////////////////////////////////////////////
+
+
+ /**
+ * Siphons from an InputStream of System.out (from a Process)
+ * and sends it to the real System.out.
+ */
+ class SystemOutSiphon implements Runnable {
+ InputStream input;
+ Thread thread;
+
+ public SystemOutSiphon(InputStream input) {
+ this.input = input;
+
+ thread = new Thread(this);
+ // unless this is set to min, it seems to hork the app
+ // since it's in charge of stuffing the editor console with strings
+ // maybe it's time to get rid of/fix that friggin console
+ // ...disabled for 0075, with 0074's fix for code folder hanging
+ // this only seems to make the console unresponsive
+ //thread.setPriority(Thread.MIN_PRIORITY);
+ thread.start();
+ }
+
+ public void run() {
+ byte boofer[] = new byte[256];
+
+ while (Thread.currentThread() == thread) {
+ try {
+ // can't use a buffered reader here because incremental
+ // print statements are interesting too.. causes some
+ // disparity with how System.err gets spewed, oh well.
+ int count = input.read(boofer, 0, boofer.length);
+ if (count == -1) {
+ thread = null;
+
+ } else {
+ System.out.print(new String(boofer, 0, count));
+ //System.out.flush();
+ }
+
+ } catch (IOException e) {
+ // this is prolly because the app was quit & the stream broken
+ //e.printStackTrace(System.out);
+ //e.printStackTrace();
+ thread = null;
+
+ } catch (Exception e) {
+ //System.out.println("SystemOutSiphon: i just died in your arms tonight");
+ // on mac os x, this will spew a "Bad File Descriptor" ex
+ // each time an external app is shut down.
+ //e.printStackTrace();
+ thread = null;
+ //System.out.println("");
+ }
+ //System.out.println("SystemOutSiphon: out");
+ //thread = null;
+ }
+ }
+ }
+}
diff --git a/app/src/processing/app/debug/RunnerException.java b/app/src/processing/app/debug/RunnerException.java
new file mode 100644
index 000000000..0b4e59154
--- /dev/null
+++ b/app/src/processing/app/debug/RunnerException.java
@@ -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.
+ *
+ * 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();
+ }
+ }
+}
diff --git a/app/src/processing/app/debug/RunnerListener.java b/app/src/processing/app/debug/RunnerListener.java
new file mode 100644
index 000000000..1728d7972
--- /dev/null
+++ b/app/src/processing/app/debug/RunnerListener.java
@@ -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);
+}
\ No newline at end of file
diff --git a/app/Sizer.java b/app/src/processing/app/debug/Sizer.java
similarity index 89%
rename from app/Sizer.java
rename to app/src/processing/app/debug/Sizer.java
index 818237424..d67728a3c 100644
--- a/app/Sizer.java
+++ b/app/src/processing/app/debug/Sizer.java
@@ -23,7 +23,10 @@
$Id$
*/
-package processing.app;
+package processing.app.debug;
+
+import processing.app.Base;
+
import java.io.*;
import java.util.*;
@@ -39,17 +42,7 @@ public class Sizer implements MessageConsumer {
}
public long computeSize() throws RunnerException {
- String userdir = System.getProperty("user.dir") + File.separator;
- String avrBasePath;
- if(Base.isMacOS()) {
- avrBasePath = new String("hardware/tools/avr/bin/");
- }
- else if(Base.isLinux()) {
- avrBasePath = new String("");
- }
- else {
- avrBasePath = new String(userdir + "hardware/tools/avr/bin/");
- }
+ String avrBasePath = Base.getAvrBasePath();
String commandSize[] = new String[] {
avrBasePath + "avr-size",
" "
diff --git a/app/src/processing/app/debug/StreamRedirectThread.java b/app/src/processing/app/debug/StreamRedirectThread.java
new file mode 100644
index 000000000..795e8c199
--- /dev/null
+++ b/app/src/processing/app/debug/StreamRedirectThread.java
@@ -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);
+ }
+ }
+}
diff --git a/app/Target.java b/app/src/processing/app/debug/Target.java
similarity index 96%
rename from app/Target.java
rename to app/src/processing/app/debug/Target.java
index 083f49414..1c76ec167 100644
--- a/app/Target.java
+++ b/app/src/processing/app/debug/Target.java
@@ -21,10 +21,10 @@
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- $Id$
+ $Id: Target.java 85 2006-01-12 23:24:12Z mellis $
*/
-package processing.app;
+package processing.app.debug;
import java.io.*;
import java.util.*;
diff --git a/app/Uploader.java b/app/src/processing/app/debug/Uploader.java
similarity index 95%
rename from app/Uploader.java
rename to app/src/processing/app/debug/Uploader.java
index f71cc26e0..624d58772 100755
--- a/app/Uploader.java
+++ b/app/src/processing/app/debug/Uploader.java
@@ -24,7 +24,12 @@
$Id$
*/
-package processing.app;
+package processing.app.debug;
+
+import processing.app.Base;
+import processing.app.Preferences;
+import processing.app.Serial;
+
import java.io.*;
import java.util.*;
import java.util.zip.*;
@@ -102,14 +107,12 @@ public abstract class Uploader implements MessageConsumer {
commandDownloader.toArray(commandArray);
String avrBasePath;
- if(Base.isMacOS()) {
- avrBasePath = new String("hardware/tools/avr/bin/");
- }
- else if(Base.isLinux()) {
- avrBasePath = new String("hardware/tools/");
+
+ if(Base.isLinux()) {
+ avrBasePath = new String(Base.getHardwarePath() + "/tools/");
}
else {
- avrBasePath = new String(userdir + "hardware/tools/avr/bin/");
+ avrBasePath = new String(Base.getHardwarePath() + "/tools/avr/bin/");
}
commandArray[0] = avrBasePath + commandArray[0];
@@ -136,7 +139,7 @@ public abstract class Uploader implements MessageConsumer {
}
}
if(exception!=null) {
- exception.hideStackTrace = true;
+ exception.hideStackTrace();
throw exception;
}
if(result!=0)
diff --git a/app/src/processing/app/linux/Platform.java b/app/src/processing/app/linux/Platform.java
new file mode 100644
index 000000000..496e926ae
--- /dev/null
+++ b/app/src/processing/app/linux/Platform.java
@@ -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");
+ }
+ }
+}
diff --git a/app/src/processing/app/macosx/Platform.java b/app/src/processing/app/macosx/Platform.java
new file mode 100644
index 000000000..a7180aadc
--- /dev/null
+++ b/app/src/processing/app/macosx/Platform.java
@@ -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(), "Arduino");
+ }
+
+
+ public File getDefaultSketchbookFolder() throws Exception {
+ return new File(getDocumentsFolder(), "Arduino");
+ /*
+ // 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, "Arduino");
+
+ } 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);
+ }
+}
diff --git a/app/src/processing/app/macosx/ThinkDifferent.java b/app/src/processing/app/macosx/ThinkDifferent.java
new file mode 100644
index 000000000..38cb6cb9a
--- /dev/null
+++ b/app/src/processing/app/macosx/ThinkDifferent.java
@@ -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) {
+ }
+}
\ No newline at end of file
diff --git a/app/src/processing/app/preproc/.cvsignore b/app/src/processing/app/preproc/.cvsignore
new file mode 100644
index 000000000..b010c249c
--- /dev/null
+++ b/app/src/processing/app/preproc/.cvsignore
@@ -0,0 +1,9 @@
+*Lexer.java
+*Recognizer.java
+*TokenTypes.java
+*TokenTypes.txt
+*TreeParser.java
+*TreeParserTokenTypes.java
+*TreeParserTokenTypes.txt
+expanded*.g
+
diff --git a/app/preproc/PdePreprocessor.java b/app/src/processing/app/preproc/PdePreprocessor.java
old mode 100755
new mode 100644
similarity index 97%
rename from app/preproc/PdePreprocessor.java
rename to app/src/processing/app/preproc/PdePreprocessor.java
index ff3e00a84..e0ba89681
--- a/app/preproc/PdePreprocessor.java
+++ b/app/src/processing/app/preproc/PdePreprocessor.java
@@ -30,6 +30,7 @@
package processing.app.preproc;
import processing.app.*;
+import processing.app.debug.Target;
import processing.core.*;
import java.io.*;
@@ -55,7 +56,8 @@ public class PdePreprocessor {
// might be at the end instead of .* whcih would make trouble
// other classes using this can lop of the . and anything after
// it to produce a package name consistently.
- public String extraImports[];
+ //public String extraImports[];
+ ArrayList programImports;
static public final int STATIC = 0; // formerly BEGINNER
static public final int ACTIVE = 1; // formerly INTERMEDIATE
@@ -70,7 +72,8 @@ public class PdePreprocessor {
public int prototypeCount = 0;
// stores number of included library headers written
- public int headerCount = 0;
+ // we always write one header: WProgram.h
+ public int headerCount = 1;
/**
* These may change in-between (if the prefs panel adds this option)
@@ -274,7 +277,7 @@ public class PdePreprocessor {
//String mess = "^\\s*(import\\s+\\S+\\s*;)";
//String mess = "^\\s*(import\\s+)(\\S+)(\\s*;)";
String mess = "^\\s*#include\\s+[<\"](\\S+)[\">]";
- java.util.Vector imports = new java.util.Vector();
+ programImports = new ArrayList();
Pattern pattern = null;
try {
@@ -286,12 +289,9 @@ public class PdePreprocessor {
PatternMatcherInput input = new PatternMatcherInput(program);
while (matcher.contains(input, pattern)) {
- imports.add(matcher.getMatch().group(1));
+ programImports.add(matcher.getMatch().group(1));
}
- extraImports = new String[imports.size()];
- imports.copyInto(extraImports);
-
// do this after the program gets re-combobulated
this.programReader = new StringReader(program);
this.buildPath = buildPath;
@@ -363,6 +363,11 @@ public class PdePreprocessor {
}
+ public ArrayList getExtraImports() {
+ return programImports;
+ }
+
+
static String advClassName = "";
/**
diff --git a/app/syntax/CTokenMarker.java b/app/src/processing/app/syntax/CTokenMarker.java
similarity index 99%
rename from app/syntax/CTokenMarker.java
rename to app/src/processing/app/syntax/CTokenMarker.java
index c15183214..1fdb33fe6 100644
--- a/app/syntax/CTokenMarker.java
+++ b/app/src/processing/app/syntax/CTokenMarker.java
@@ -15,7 +15,7 @@ import javax.swing.text.Segment;
* C token marker.
*
* @author Slava Pestov
- * @version $Id$
+ * @version $Id: CTokenMarker.java 1268 2005-04-09 02:30:37Z benfry $
*/
public class CTokenMarker extends TokenMarker
{
diff --git a/app/syntax/DefaultInputHandler.java b/app/src/processing/app/syntax/DefaultInputHandler.java
similarity index 99%
rename from app/syntax/DefaultInputHandler.java
rename to app/src/processing/app/syntax/DefaultInputHandler.java
index 7ae11121b..9814cf252 100644
--- a/app/syntax/DefaultInputHandler.java
+++ b/app/src/processing/app/syntax/DefaultInputHandler.java
@@ -19,7 +19,7 @@ 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$
+ * @version $Id: DefaultInputHandler.java 1438 2005-05-11 08:34:16Z benfry $
*/
public class DefaultInputHandler extends InputHandler
{
diff --git a/app/syntax/InputHandler.java b/app/src/processing/app/syntax/InputHandler.java
similarity index 97%
rename from app/syntax/InputHandler.java
rename to app/src/processing/app/syntax/InputHandler.java
index 6963d2dad..db7260da5 100644
--- a/app/syntax/InputHandler.java
+++ b/app/src/processing/app/syntax/InputHandler.java
@@ -24,8 +24,7 @@ import java.util.*;
* to the implementations of this class to do so.
*
* @author Slava Pestov
- * @version $Id$
- * @see org.gjt.sp.jedit.textarea.DefaultInputHandler
+ * @version $Id: InputHandler.java 4168 2008-08-09 17:24:37Z fry $
*/
public abstract class InputHandler extends KeyAdapter
{
@@ -138,7 +137,7 @@ public abstract class InputHandler extends KeyAdapter
ActionListener _listener = getAction(name);
if(_listener == listener) {
return name;
- }
+ }
}
return null;
}
@@ -408,7 +407,7 @@ public abstract class InputHandler extends KeyAdapter
}
if(textArea.getSelectionStart()
- != textArea.getSelectionEnd())
+ != textArea.getSelectionStop())
{
textArea.setSelectedText("");
}
@@ -438,7 +437,7 @@ public abstract class InputHandler extends KeyAdapter
{
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
- if(start != textArea.getSelectionEnd())
+ if(start != textArea.getSelectionStop())
{
textArea.setSelectedText("");
}
@@ -491,7 +490,7 @@ public abstract class InputHandler extends KeyAdapter
}
if(textArea.getSelectionStart()
- != textArea.getSelectionEnd())
+ != textArea.getSelectionStop())
{
textArea.setSelectedText("");
}
@@ -521,7 +520,7 @@ public abstract class InputHandler extends KeyAdapter
{
JEditTextArea textArea = getTextArea(evt);
int start = textArea.getSelectionStart();
- if(start != textArea.getSelectionEnd())
+ if(start != textArea.getSelectionStop())
{
textArea.setSelectedText("");
}
@@ -575,7 +574,7 @@ public abstract class InputHandler extends KeyAdapter
int caret = textArea.getCaretPosition();
- int lastOfLine = textArea.getLineEndOffset(
+ int lastOfLine = textArea.getLineStopOffset(
textArea.getCaretLine()) - 1;
int lastVisibleLine = textArea.getFirstLine()
+ textArea.getVisibleLines();
@@ -587,7 +586,7 @@ public abstract class InputHandler extends KeyAdapter
else
lastVisibleLine -= (textArea.getElectricScroll() + 1);
- int lastVisible = textArea.getLineEndOffset(lastVisibleLine) - 1;
+ int lastVisible = textArea.getLineStopOffset(lastVisibleLine) - 1;
int lastDocument = textArea.getDocumentLength();
if(caret == lastDocument)
@@ -747,26 +746,26 @@ public abstract class InputHandler extends KeyAdapter
if(caret == textArea.getDocumentLength())
{
if (textArea.getSelectionStart() !=
- textArea.getSelectionEnd()) {
+ textArea.getSelectionStop()) {
// just move to the end of the selection
textArea.select(caret, caret);
} else {
// beep at the user for being annoying
- textArea.getToolkit().beep();
- }
+ textArea.getToolkit().beep();
+ }
} else if (select) {
textArea.select(textArea.getMarkPosition(), caret+1);
} else {
int start = textArea.getSelectionStart();
- int end = textArea.getSelectionEnd();
+ int end = textArea.getSelectionStop();
if (start != end) {
textArea.select(end, end);
} else {
- textArea.setCaretPosition(caret + 1);
- }
- }
+ textArea.setCaretPosition(caret + 1);
+ }
+ }
}
}
@@ -794,7 +793,7 @@ public abstract class InputHandler extends KeyAdapter
} else {
textArea.setCaretPosition(doc);
}
- return;
+ return;
}
int magic = textArea.getMagicCaretPosition();
@@ -924,13 +923,13 @@ public abstract class InputHandler extends KeyAdapter
textArea.select(textArea.getMarkPosition(), caret-1);
} else {
int start = textArea.getSelectionStart();
- int end = textArea.getSelectionEnd();
+ int end = textArea.getSelectionStop();
if (start != end) {
textArea.select(start, start);
} else {
- textArea.setCaretPosition(caret - 1);
- }
- }
+ textArea.setCaretPosition(caret - 1);
+ }
+ }
}
}
diff --git a/app/syntax/JEditTextArea.java b/app/src/processing/app/syntax/JEditTextArea.java
similarity index 95%
rename from app/syntax/JEditTextArea.java
rename to app/src/processing/app/syntax/JEditTextArea.java
index 5b45b4e40..af01ea16c 100644
--- a/app/syntax/JEditTextArea.java
+++ b/app/src/processing/app/syntax/JEditTextArea.java
@@ -1,4 +1,4 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* JEditTextArea.java - jEdit's text component
@@ -20,7 +20,6 @@ import javax.swing.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.*;
-import java.io.*;
import java.util.Enumeration;
import java.util.Vector;
@@ -52,7 +51,7 @@ import java.util.Vector;
* + "}");
*
* @author Slava Pestov
- * @version $Id$
+ * @version $Id: JEditTextArea.java 5343 2008-11-29 17:22:59Z fry $
*/
public class JEditTextArea extends JComponent
{
@@ -116,21 +115,6 @@ public class JEditTextArea extends JComponent
// We don't seem to get the initial focus event?
focusedComponent = this;
- // no more need for reflection, pde requires use of java 1.4
- /*
- if (System.getProperty("java.version").startsWith("1.4")) {
- try {
- Class kWheelHandler =
- Class.forName("processing.app.syntax.WheelHandler");
- java.lang.reflect.Constructor konstructor =
- kWheelHandler.getConstructor(new Class[] { getClass() });
- konstructor.newInstance(new Object[] { this });
- } catch (Exception e) {
- System.err.println(e);
- }
- }
- */
- //new WheelHandler(this);
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
if (!scrollBarsInitialized) return;
@@ -161,24 +145,21 @@ public class JEditTextArea extends JComponent
* Returns if this component can be traversed by pressing
* the Tab key. This returns false.
*/
- public final boolean isManagingFocus()
- {
+ public final boolean isManagingFocus() {
return true;
}
/**
* Returns the object responsible for painting this text area.
*/
- public final TextAreaPainter getPainter()
- {
+ public final TextAreaPainter getPainter() {
return painter;
}
/**
* Returns the input handler.
*/
- public final InputHandler getInputHandler()
- {
+ public final InputHandler getInputHandler() {
return inputHandler;
}
@@ -186,16 +167,14 @@ public class JEditTextArea extends JComponent
* Sets the input handler.
* @param inputHandler The new input handler
*/
- public void setInputHandler(InputHandler inputHandler)
- {
+ public void setInputHandler(InputHandler inputHandler) {
this.inputHandler = inputHandler;
}
/**
* Returns true if the caret is blinking, false otherwise.
*/
- public final boolean isCaretBlinkEnabled()
- {
+ public final boolean isCaretBlinkEnabled() {
return caretBlinks;
}
@@ -203,8 +182,7 @@ public class JEditTextArea extends JComponent
* Toggles caret blinking.
* @param caretBlinks True if the caret should blink, false otherwise
*/
- public void setCaretBlinkEnabled(boolean caretBlinks)
- {
+ public void setCaretBlinkEnabled(boolean caretBlinks) {
this.caretBlinks = caretBlinks;
if(!caretBlinks)
blink = false;
@@ -215,8 +193,7 @@ public class JEditTextArea extends JComponent
/**
* Returns true if the caret is visible, false otherwise.
*/
- public final boolean isCaretVisible()
- {
+ public final boolean isCaretVisible() {
return (!caretBlinks || blink) && caretVisible;
}
@@ -225,8 +202,7 @@ public class JEditTextArea extends JComponent
* @param caretVisible True if the caret should be visible, false
* otherwise
*/
- public void setCaretVisible(boolean caretVisible)
- {
+ public void setCaretVisible(boolean caretVisible) {
this.caretVisible = caretVisible;
blink = true;
@@ -236,23 +212,20 @@ public class JEditTextArea extends JComponent
/**
* Blinks the caret.
*/
- public final void blinkCaret()
- {
- if(caretBlinks)
- {
- blink = !blink;
- painter.invalidateSelectedLines();
- }
- else
+ public final void blinkCaret() {
+ if (caretBlinks) {
+ blink = !blink;
+ painter.invalidateSelectedLines();
+ } else {
blink = true;
+ }
}
/**
* Returns the number of lines from the top and button of the
* text area that are always visible.
*/
- public final int getElectricScroll()
- {
+ public final int getElectricScroll() {
return electricScroll;
}
@@ -262,8 +235,7 @@ public class JEditTextArea extends JComponent
* @param electricScroll The number of lines always visible from
* the top or bottom
*/
- public final void setElectricScroll(int electricScroll)
- {
+ public final void setElectricScroll(int electricScroll) {
this.electricScroll = electricScroll;
}
@@ -282,7 +254,7 @@ public class JEditTextArea extends JComponent
//if (horizontal != null && width != 0) {
if ((horizontal != null) && (painter.getWidth() != 0)) {
- int value = horizontal.getValue();
+ //int value = horizontal.getValue();
//System.out.println("updateScrollBars");
//int width = painter.getWidth();
int lineCount = getLineCount();
@@ -328,12 +300,10 @@ public class JEditTextArea extends JComponent
}
}
-
/**
* Returns the line displayed at the text area's origin.
*/
- public final int getFirstLine()
- {
+ public final int getFirstLine() {
return firstLine;
}
@@ -341,22 +311,20 @@ public class JEditTextArea extends JComponent
* Sets the line displayed at the text area's origin without
* updating the scroll bars.
*/
- public void setFirstLine(int firstLine)
- {
- if(firstLine == this.firstLine)
- return;
- int oldFirstLine = this.firstLine;
+ public void setFirstLine(int firstLine) {
+ if (firstLine == this.firstLine) return;
+
this.firstLine = firstLine;
- if(firstLine != vertical.getValue())
+ if (firstLine != vertical.getValue()) {
updateScrollBars();
+ }
painter.repaint();
}
/**
* Returns the number of lines visible in this text area.
*/
- public final int getVisibleLines()
- {
+ public final int getVisibleLines() {
return visibleLines;
}
@@ -364,13 +332,11 @@ public class JEditTextArea extends JComponent
* Recalculates the number of visible lines. This should not
* be called directly.
*/
- public final void recalculateVisibleLines()
- {
- if(painter == null)
- return;
+ public final void recalculateVisibleLines() {
+ if (painter == null) return;
+
int height = painter.getHeight();
int lineHeight = painter.getFontMetrics().getHeight();
- int oldVisibleLines = visibleLines;
visibleLines = height / lineHeight;
updateScrollBars();
}
@@ -378,8 +344,7 @@ public class JEditTextArea extends JComponent
/**
* Returns the horizontal offset of drawn lines.
*/
- public final int getHorizontalOffset()
- {
+ public final int getHorizontalOffset() {
return horizontalOffset;
}
@@ -408,7 +373,7 @@ public class JEditTextArea extends JComponent
public boolean setOrigin(int firstLine, int horizontalOffset)
{
boolean changed = false;
- int oldFirstLine = this.firstLine;
+ //int oldFirstLine = this.firstLine;
if(horizontalOffset != this.horizontalOffset)
{
@@ -569,7 +534,7 @@ public class JEditTextArea extends JComponent
= tokenMarker.markTokens(lineSegment,line);
}
- Toolkit toolkit = painter.getToolkit();
+ //Toolkit toolkit = painter.getToolkit();
Font defaultFont = painter.getFont();
SyntaxStyle[] styles = painter.getStyles();
@@ -584,7 +549,7 @@ public class JEditTextArea extends JComponent
if(id == Token.NULL)
fm = painter.getFontMetrics();
else
- fm = styles[id].getFontMetrics(defaultFont);
+ fm = styles[id].getFontMetrics(defaultFont, this);
int length = tokens.length;
@@ -668,7 +633,7 @@ public class JEditTextArea extends JComponent
}
int offset = 0;
- Toolkit toolkit = painter.getToolkit();
+ //Toolkit toolkit = painter.getToolkit();
Font defaultFont = painter.getFont();
SyntaxStyle[] styles = painter.getStyles();
@@ -681,7 +646,7 @@ public class JEditTextArea extends JComponent
if(id == Token.NULL)
fm = painter.getFontMetrics();
else
- fm = styles[id].getFontMetrics(defaultFont);
+ fm = styles[id].getFontMetrics(defaultFont, this);
int length = tokens.length;
@@ -842,7 +807,7 @@ public class JEditTextArea extends JComponent
* @return The end offset of the specified line, or -1 if the line is
* invalid.
*/
- public int getLineEndOffset(int line)
+ public int getLineStopOffset(int line)
{
Element lineElement = document.getDefaultRootElement()
.getElement(line);
@@ -883,22 +848,23 @@ public class JEditTextArea extends JComponent
}
}
+
/**
* Sets the entire text of this text area.
*/
public void setText(String text)
{
try {
- document.beginCompoundEdit();
- document.remove(0,document.getLength());
- document.insertString(0,text,null);
+ document.beginCompoundEdit();
+ document.remove(0,document.getLength());
+ document.insertString(0,text,null);
} catch (BadLocationException bl) {
- bl.printStackTrace();
+ bl.printStackTrace();
} finally {
- document.endCompoundEdit();
- }
+ document.endCompoundEdit();
+ }
}
@@ -949,7 +915,7 @@ public class JEditTextArea extends JComponent
public final String getLineText(int lineIndex)
{
int start = getLineStartOffset(lineIndex);
- return getText(start,getLineEndOffset(lineIndex) - start - 1);
+ return getText(start,getLineStopOffset(lineIndex) - start - 1);
}
/**
@@ -960,7 +926,7 @@ public class JEditTextArea extends JComponent
public final void getLineText(int lineIndex, Segment segment)
{
int start = getLineStartOffset(lineIndex);
- getText(start,getLineEndOffset(lineIndex) - start - 1,segment);
+ getText(start,getLineStopOffset(lineIndex) - start - 1,segment);
}
/**
@@ -1016,7 +982,7 @@ public class JEditTextArea extends JComponent
/**
* Returns the selection end offset.
*/
- public final int getSelectionEnd()
+ public final int getSelectionStop()
{
return selectionEnd;
}
@@ -1025,7 +991,7 @@ public class JEditTextArea extends JComponent
* Returns the offset where the selection ends on the specified
* line.
*/
- public int getSelectionEnd(int line)
+ public int getSelectionStop(int line)
{
if(line == selectionEndLine)
return selectionEnd;
@@ -1041,13 +1007,13 @@ public class JEditTextArea extends JComponent
return Math.min(lineEnd,lineStart + end);
}
else
- return getLineEndOffset(line) - 1;
+ return getLineStopOffset(line) - 1;
}
/**
* Returns the selection end line.
*/
- public final int getSelectionEndLine()
+ public final int getSelectionStopLine()
{
return selectionEndLine;
}
@@ -1062,7 +1028,8 @@ public class JEditTextArea extends JComponent
{
select(selectionStart,selectionEnd);
}
-
+
+
public final boolean isSelectionActive()
{
return(selectionStart != selectionEnd);
@@ -1447,7 +1414,7 @@ public class JEditTextArea extends JComponent
// Don't overstrike if we're on the end of
// the line
int caret = getCaretPosition();
- int caretLineEnd = getLineEndOffset(getCaretLine());
+ int caretLineEnd = getLineStopOffset(getCaretLine());
if(caretLineEnd - caret <= str.length())
{
setSelectedText(str);
@@ -1642,11 +1609,12 @@ public class JEditTextArea extends JComponent
switch(evt.getID()) {
case KeyEvent.KEY_TYPED:
- //if ((editorListener != null) && !editorListener.keyTyped(evt)) {
- inputHandler.keyTyped(evt);
+ if ((editorListener == null) || !editorListener.keyTyped(evt)) {
+ inputHandler.keyTyped(evt);
+ }
break;
case KeyEvent.KEY_PRESSED:
- if ((editorListener != null) && !editorListener.keyPressed(evt)) {
+ if ((editorListener == null) || !editorListener.keyPressed(evt)) {
inputHandler.keyPressed(evt);
}
break;
@@ -2201,13 +2169,13 @@ public class JEditTextArea extends JComponent
}
for(int i = offset; i < lineText.length(); i++) {
- ch = lineText.charAt(i);
+ ch = lineText.charAt(i);
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
- wordEnd = i;
- break;
- }
+ wordEnd = i;
+ break;
}
+ }
//}
int lineStart = getLineStartOffset(line);
@@ -2227,7 +2195,7 @@ public class JEditTextArea extends JComponent
private void doTripleClick(MouseEvent evt, int line,
int offset, int dot)
{
- select(getLineStartOffset(line),getLineEndOffset(line)-1);
+ select(getLineStartOffset(line),getLineStopOffset(line)-1);
}
}
diff --git a/app/syntax/KeywordMap.java b/app/src/processing/app/syntax/KeywordMap.java
similarity index 98%
rename from app/syntax/KeywordMap.java
rename to app/src/processing/app/syntax/KeywordMap.java
index d0d834adf..065d92b3f 100644
--- a/app/syntax/KeywordMap.java
+++ b/app/src/processing/app/syntax/KeywordMap.java
@@ -20,7 +20,7 @@ import javax.swing.text.Segment;
* This class is used by CTokenMarker to map keywords to ids.
*
* @author Slava Pestov, Mike Dillon
- * @version $Id$
+ * @version $Id: KeywordMap.java 2050 2006-03-11 00:50:01Z fry $
*/
public class KeywordMap
{
diff --git a/app/src/processing/app/syntax/PdeKeywords.java b/app/src/processing/app/syntax/PdeKeywords.java
new file mode 100644
index 000000000..d363e8c9b
--- /dev/null
+++ b/app/src/processing/app/syntax/PdeKeywords.java
@@ -0,0 +1,127 @@
+/* -*- 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.
+ *
+ * Uses getKeywords() method because that's part of the
+ * TokenMarker classes.
+ *
+ * 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();
+ getKeywords(Base.getLibStream("keywords.txt"));
+ for (File lib : Base.getLibraries()) {
+ File keywords = new File(lib, "keywords.txt");
+ if (keywords.exists()) getKeywords(new FileInputStream(keywords));
+ }
+ } 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 private void getKeywords(InputStream input) throws Exception {
+ 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();
+ }
+
+
+ static public String getReference(String keyword) {
+ return (String) keywordToReference.get(keyword);
+ }
+}
diff --git a/app/syntax/PdeTextAreaDefaults.java b/app/src/processing/app/syntax/PdeTextAreaDefaults.java
similarity index 81%
rename from app/syntax/PdeTextAreaDefaults.java
rename to app/src/processing/app/syntax/PdeTextAreaDefaults.java
index e85dad955..a2dda2b78 100644
--- a/app/syntax/PdeTextAreaDefaults.java
+++ b/app/src/processing/app/syntax/PdeTextAreaDefaults.java
@@ -1,4 +1,4 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
PdeTextAreaDefaults - grabs font/color settings for the editor
@@ -69,8 +69,8 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
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("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);
@@ -133,60 +133,60 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
styles = new SyntaxStyle[Token.ID_COUNT];
// comments
- styles[Token.COMMENT1] = Preferences.getStyle("comment1");
- styles[Token.COMMENT2] = Preferences.getStyle("comment2");
+ styles[Token.COMMENT1] = Theme.getStyle("comment1");
+ styles[Token.COMMENT2] = Theme.getStyle("comment2");
// abstract, final, private
- styles[Token.KEYWORD1] = Preferences.getStyle("keyword1");
+ styles[Token.KEYWORD1] = Theme.getStyle("keyword1");
// beginShape, point, line
- styles[Token.KEYWORD2] = Preferences.getStyle("keyword2");
+ styles[Token.KEYWORD2] = Theme.getStyle("keyword2");
// byte, char, short, color
- styles[Token.KEYWORD3] = Preferences.getStyle("keyword3");
+ styles[Token.KEYWORD3] = Theme.getStyle("keyword3");
// constants: null, true, this, RGB, TWO_PI
- styles[Token.LITERAL1] = Preferences.getStyle("literal1");
+ styles[Token.LITERAL1] = Theme.getStyle("literal1");
// p5 built in variables: mouseX, width, pixels
- styles[Token.LITERAL2] = Preferences.getStyle("literal2");
+ styles[Token.LITERAL2] = Theme.getStyle("literal2");
// ??
- styles[Token.LABEL] = Preferences.getStyle("label");
+ styles[Token.LABEL] = Theme.getStyle("label");
// + - = /
- styles[Token.OPERATOR] = Preferences.getStyle("operator");
+ styles[Token.OPERATOR] = Theme.getStyle("operator");
// area that's not in use by the text (replaced with tildes)
- styles[Token.INVALID] = Preferences.getStyle("invalid");
+ styles[Token.INVALID] = Theme.getStyle("invalid");
// moved from TextAreaPainter
font = Preferences.getFont("editor.font");
- fgcolor = Preferences.getColor("editor.fgcolor");
- bgcolor = Preferences.getColor("editor.bgcolor");
+ fgcolor = Theme.getColor("editor.fgcolor");
+ bgcolor = Theme.getColor("editor.bgcolor");
caretVisible = true;
caretBlinks = Preferences.getBoolean("editor.caret.blink");
- caretColor = Preferences.getColor("editor.caret.color");
+ caretColor = Theme.getColor("editor.caret.color");
- selectionColor = Preferences.getColor("editor.selection.color");
+ selectionColor = Theme.getColor("editor.selection.color");
lineHighlight =
- Preferences.getBoolean("editor.linehighlight");
+ Theme.getBoolean("editor.linehighlight");
lineHighlightColor =
- Preferences.getColor("editor.linehighlight.color");
+ Theme.getColor("editor.linehighlight.color");
bracketHighlight =
- Preferences.getBoolean("editor.brackethighlight");
+ Theme.getBoolean("editor.brackethighlight");
bracketHighlightColor =
- Preferences.getColor("editor.brackethighlight.color");
+ Theme.getColor("editor.brackethighlight.color");
- eolMarkers = Preferences.getBoolean("editor.eolmarkers");
- eolMarkerColor = Preferences.getColor("editor.eolmarkers.color");
+ eolMarkers = Theme.getBoolean("editor.eolmarkers");
+ eolMarkerColor = Theme.getColor("editor.eolmarkers.color");
- paintInvalid = Preferences.getBoolean("editor.invalid");
+ paintInvalid = Theme.getBoolean("editor.invalid");
}
}
diff --git a/app/syntax/SyntaxDocument.java b/app/src/processing/app/syntax/SyntaxDocument.java
similarity index 98%
rename from app/syntax/SyntaxDocument.java
rename to app/src/processing/app/syntax/SyntaxDocument.java
index 25b50d69a..7b07a4269 100644
--- a/app/syntax/SyntaxDocument.java
+++ b/app/src/processing/app/syntax/SyntaxDocument.java
@@ -18,7 +18,7 @@ import javax.swing.undo.UndoableEdit;
* system.
*
* @author Slava Pestov
- * @version $Id$
+ * @version $Id: SyntaxDocument.java 1268 2005-04-09 02:30:37Z benfry $
*/
public class SyntaxDocument extends PlainDocument
{
diff --git a/app/syntax/SyntaxStyle.java b/app/src/processing/app/syntax/SyntaxStyle.java
similarity index 91%
rename from app/syntax/SyntaxStyle.java
rename to app/src/processing/app/syntax/SyntaxStyle.java
index 000b40aef..56323c3cc 100644
--- a/app/syntax/SyntaxStyle.java
+++ b/app/src/processing/app/syntax/SyntaxStyle.java
@@ -10,13 +10,14 @@
package processing.app.syntax;
import java.awt.*;
-import java.util.StringTokenizer;
+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$
+ * @version $Id: SyntaxStyle.java 4824 2008-10-11 23:41:40Z fry $
*/
public class SyntaxStyle
{
@@ -87,7 +88,7 @@ public class SyntaxStyle
/**
* Returns the font metrics for the styled font.
*/
- public FontMetrics getFontMetrics(Font font)
+ public FontMetrics getFontMetrics(Font font, JComponent comp)
{
if(font == null)
throw new NullPointerException("font param must not"
@@ -99,8 +100,8 @@ public class SyntaxStyle
(bold ? Font.BOLD : 0)
| (italic ? Font.ITALIC : 0),
font.getSize());
- fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(
- lastStyledFont);
+ //fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(lastStyledFont);
+ fontMetrics = comp.getFontMetrics(lastStyledFont);
return fontMetrics;
}
diff --git a/app/syntax/SyntaxUtilities.java b/app/src/processing/app/syntax/SyntaxUtilities.java
similarity index 98%
rename from app/syntax/SyntaxUtilities.java
rename to app/src/processing/app/syntax/SyntaxUtilities.java
index 6da021b52..5225d0b73 100644
--- a/app/syntax/SyntaxUtilities.java
+++ b/app/src/processing/app/syntax/SyntaxUtilities.java
@@ -18,7 +18,7 @@ import java.awt.*;
* subsystem.
*
* @author Slava Pestov
- * @version $Id$
+ * @version $Id: SyntaxUtilities.java 1268 2005-04-09 02:30:37Z benfry $
*/
public class SyntaxUtilities
{
diff --git a/app/syntax/TextAreaDefaults.java b/app/src/processing/app/syntax/TextAreaDefaults.java
similarity index 100%
rename from app/syntax/TextAreaDefaults.java
rename to app/src/processing/app/syntax/TextAreaDefaults.java
diff --git a/app/syntax/TextAreaPainter.java b/app/src/processing/app/syntax/TextAreaPainter.java
similarity index 96%
rename from app/syntax/TextAreaPainter.java
rename to app/src/processing/app/syntax/TextAreaPainter.java
index 80487b820..ef205b079 100644
--- a/app/syntax/TextAreaPainter.java
+++ b/app/src/processing/app/syntax/TextAreaPainter.java
@@ -1,4 +1,4 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* TextAreaPainter.java - Paints the text area
@@ -24,7 +24,6 @@ import java.awt.print.*;
* The text area repaint manager. It performs double buffering and paints
* lines of text.
* @author Slava Pestov
- * @version $Id$
*/
public class TextAreaPainter extends JComponent
implements TabExpander, Printable
@@ -82,7 +81,7 @@ implements TabExpander, Printable
/**
* Returns the syntax styles used to paint colorized text. Entry n
* will be used to paint tokens with id = n.
- * @see org.gjt.sp.jedit.syntax.Token
+ * @see processing.app.syntax.Token
*/
public final SyntaxStyle[] getStyles()
{
@@ -93,7 +92,7 @@ implements TabExpander, Printable
* Sets the syntax styles used to paint colorized text. Entry n
* will be used to paint tokens with id = n.
* @param styles The syntax styles
- * @see org.gjt.sp.jedit.syntax.Token
+ * @see processing.app.syntax.Token
*/
public final void setStyles(SyntaxStyle[] styles)
{
@@ -357,13 +356,13 @@ implements TabExpander, Printable
public void setFont(Font font)
{
super.setFont(font);
- fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ fm = super.getFontMetrics(font);
textArea.recalculateVisibleLines();
}
/**
* Repaints the text.
- * @param g The graphics context
+ * @param gfx The graphics context
*/
public void paint(Graphics gfx)
{
@@ -464,7 +463,7 @@ implements TabExpander, Printable
public final void invalidateSelectedLines()
{
invalidateLineRange(textArea.getSelectionStartLine(),
- textArea.getSelectionEndLine());
+ textArea.getSelectionStopLine());
}
/**
@@ -632,19 +631,19 @@ implements TabExpander, Printable
protected void paintHighlight(Graphics gfx, int line, int y)
{
if (!printing) {
- if (line >= textArea.getSelectionStartLine()
- && line <= textArea.getSelectionEndLine())
- paintLineHighlight(gfx,line,y);
+ if (line >= textArea.getSelectionStartLine()
+ && line <= textArea.getSelectionStopLine())
+ paintLineHighlight(gfx,line,y);
- if (highlights != null)
- highlights.paintHighlight(gfx,line,y);
+ if (highlights != null)
+ highlights.paintHighlight(gfx,line,y);
- if (bracketHighlight && line == textArea.getBracketLine())
- paintBracketHighlight(gfx,line,y);
+ if (bracketHighlight && line == textArea.getBracketLine())
+ paintBracketHighlight(gfx,line,y);
- if (line == textArea.getCaretLine())
- paintCaret(gfx,line,y);
- }
+ if (line == textArea.getCaretLine())
+ paintCaret(gfx,line,y);
+ }
}
protected void paintLineHighlight(Graphics gfx, int line, int y)
@@ -653,7 +652,7 @@ implements TabExpander, Printable
y += fm.getLeading() + fm.getMaxDescent();
int selectionStart = textArea.getSelectionStart();
- int selectionEnd = textArea.getSelectionEnd();
+ int selectionEnd = textArea.getSelectionStop();
if (selectionStart == selectionEnd) {
if (lineHighlight) {
@@ -664,7 +663,7 @@ implements TabExpander, Printable
gfx.setColor(selectionColor);
int selectionStartLine = textArea.getSelectionStartLine();
- int selectionEndLine = textArea.getSelectionEndLine();
+ int selectionEndLine = textArea.getSelectionStopLine();
int lineStart = textArea.getLineStartOffset(line);
int x1, x2;
diff --git a/app/syntax/TextUtilities.java b/app/src/processing/app/syntax/TextUtilities.java
similarity index 98%
rename from app/syntax/TextUtilities.java
rename to app/src/processing/app/syntax/TextUtilities.java
index 29db67716..d31f8f3b7 100644
--- a/app/syntax/TextUtilities.java
+++ b/app/src/processing/app/syntax/TextUtilities.java
@@ -14,7 +14,7 @@ import javax.swing.text.*;
/**
* Class with several utility functions used by the text area component.
* @author Slava Pestov
- * @version $Id$
+ * @version $Id: TextUtilities.java 1268 2005-04-09 02:30:37Z benfry $
*/
public class TextUtilities
{
diff --git a/app/syntax/Token.java b/app/src/processing/app/syntax/Token.java
similarity index 98%
rename from app/syntax/Token.java
rename to app/src/processing/app/syntax/Token.java
index 1873d50da..a0f73bebf 100644
--- a/app/syntax/Token.java
+++ b/app/src/processing/app/syntax/Token.java
@@ -17,7 +17,7 @@ package processing.app.syntax;
* token in the text, and a pointer to the next token in the list.
*
* @author Slava Pestov
- * @version $Id$
+ * @version $Id: Token.java 1268 2005-04-09 02:30:37Z benfry $
*/
public class Token
{
diff --git a/app/syntax/TokenMarker.java b/app/src/processing/app/syntax/TokenMarker.java
similarity index 99%
rename from app/syntax/TokenMarker.java
rename to app/src/processing/app/syntax/TokenMarker.java
index 942568ab2..9244556d3 100644
--- a/app/syntax/TokenMarker.java
+++ b/app/src/processing/app/syntax/TokenMarker.java
@@ -10,7 +10,6 @@
package processing.app.syntax;
import javax.swing.text.Segment;
-import java.util.*;
/**
* A token marker that splits lines of text into tokens. Each token carries
@@ -23,9 +22,6 @@ import java.util.*;
* cached.
*
* @author Slava Pestov
- * @version $Id$
- *
- * @see org.gjt.sp.jedit.syntax.Token
*/
public abstract class TokenMarker
{
diff --git a/app/syntax/readme.txt b/app/src/processing/app/syntax/readme.txt
similarity index 100%
rename from app/syntax/readme.txt
rename to app/src/processing/app/syntax/readme.txt
diff --git a/app/tools/Archiver.java b/app/src/processing/app/tools/Archiver.java
similarity index 80%
rename from app/tools/Archiver.java
rename to app/src/processing/app/tools/Archiver.java
index 0c90e5e69..9eb9655ff 100755
--- a/app/tools/Archiver.java
+++ b/app/src/processing/app/tools/Archiver.java
@@ -1,10 +1,10 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- 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-05 Ben Fry and Casey Reas
+ 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
@@ -32,7 +32,7 @@ import java.util.*;
import java.util.zip.*;
-public class Archiver {
+public class Archiver implements Tool {
Editor editor;
// someday these will be settable
@@ -43,7 +43,12 @@ public class Archiver {
SimpleDateFormat dateFormat;
- public Archiver(Editor editor) {
+ public String getMenuTitle() {
+ return "Archive Sketch";
+ }
+
+
+ public void init(Editor editor) {
this.editor = editor;
numberFormat = NumberFormat.getInstance();
@@ -54,11 +59,13 @@ public class Archiver {
}
- public void show() {
+ public void run() {
+ Sketch sketch = editor.getSketch();
+
// first save the sketch so that things don't archive strangely
boolean success = false;
try {
- success = editor.sketch.save();
+ success = sketch.save();
} catch (Exception e) {
e.printStackTrace();
}
@@ -69,7 +76,7 @@ public class Archiver {
return;
}
- File location = editor.sketch.folder;
+ File location = sketch.getFolder();
String name = location.getName();
File parent = new File(location.getParent());
@@ -102,7 +109,7 @@ public class Archiver {
new FileDialog(editor, "Archive sketch as:", FileDialog.SAVE);
fd.setDirectory(parent.getAbsolutePath());
fd.setFile(newbie.getName());
- fd.show();
+ fd.setVisible(true);
String directory = fd.getDirectory();
String filename = fd.getFile();
@@ -111,25 +118,25 @@ public class Archiver {
if (filename != null) {
newbie = new File(directory, filename);
- try {
- //System.out.println(newbie);
- FileOutputStream zipOutputFile = new FileOutputStream(newbie);
- ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
+ try {
+ //System.out.println(newbie);
+ FileOutputStream zipOutputFile = new FileOutputStream(newbie);
+ ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
- // recursively fill the zip file
- buildZip(location, name, zos);
+ // recursively fill the zip file
+ buildZip(location, name, zos);
- // close up the jar file
- zos.flush();
- zos.close();
+ // close up the jar file
+ zos.flush();
+ zos.close();
- editor.message("Created archive " + newbie.getName() + ".");
+ editor.statusNotice("Created archive " + newbie.getName() + ".");
- } catch (IOException e) {
- e.printStackTrace();
- }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
} else {
- editor.message("Archive sketch canceled.");
+ editor.statusNotice("Archive sketch canceled.");
}
}
@@ -157,7 +164,7 @@ public class Archiver {
ZipEntry entry = new ZipEntry(nowfar);
entry.setTime(sub.lastModified());
zos.putNextEntry(entry);
- zos.write(Base.grabFile(sub));
+ zos.write(Base.loadBytesRaw(sub));
zos.closeEntry();
}
}
diff --git a/app/tools/AutoFormat.java b/app/src/processing/app/tools/AutoFormat.java
similarity index 93%
rename from app/tools/AutoFormat.java
rename to app/src/processing/app/tools/AutoFormat.java
index 8d95c1645..2397967c5 100644
--- a/app/tools/AutoFormat.java
+++ b/app/src/processing/app/tools/AutoFormat.java
@@ -1,4 +1,4 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
@@ -24,17 +24,15 @@
package processing.app.tools;
import processing.app.*;
-import processing.core.*;
import java.io.*;
-import java.util.StringTokenizer;
/**
* Alternate handler for dealing with auto format.
* Contributed by Martin Gomez, additional bug fixes by Ben Fry.
*/
-public class AutoFormat {
+public class AutoFormat implements Tool {
Editor editor;
static final int BLOCK_MAXLEN = 1024;
@@ -83,10 +81,14 @@ public class AutoFormat {
//static int outfil; // temporary
- public AutoFormat(Editor editor) {
+ public void init(Editor editor) {
this.editor = editor;
}
+
+ public String getMenuTitle() {
+ return "Auto Format";
+ }
public void comment() throws IOException {
int save_s_flg;
@@ -104,7 +106,7 @@ public class AutoFormat {
}
c = string[j++] = getchr();
}
- String tmpstr = new String(string);
+ //String tmpstr = new String(string);
if (j>1 && string[j-2] == '*') {
done = 1;
jdoc = 0;
@@ -180,7 +182,7 @@ public class AutoFormat {
//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);
+ //String j_string = new String(string);
strOut.append(out_string);
}
@@ -395,7 +397,7 @@ public class AutoFormat {
public int lookup (String keyword)
{
char r;
- int l,kk,k,i;
+ int l,kk; //,k,i;
String j_string = new String(string);
if (j<1) return (0);
@@ -417,8 +419,8 @@ public class AutoFormat {
public int lookup_com (String keyword)
{
- char r;
- int l,kk,k,i;
+ //char r;
+ int l,kk; //,k,i;
String j_string = new String(string);
if (j<1) return (0);
@@ -434,10 +436,11 @@ public class AutoFormat {
}
- public void show() {
+ public void run() {
StringBuffer onechar;
- String originalText = editor.textarea.getText();
+ // 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(" ");
@@ -527,7 +530,7 @@ public class AutoFormat {
{
break;
}
- String j_string = new String(string);
+ //String j_string = new String(string);
e_flg = lookup(w_else);
if(e_flg == 1) gotelse();
@@ -710,7 +713,7 @@ public class AutoFormat {
}
else
{
- int double_colon = 0;
+ //int double_colon = 0;
peek = 1;
}
@@ -878,7 +881,7 @@ public class AutoFormat {
//System.out.println("string len is " + string.length);
//if (EOF == 1) System.out.println(string);
- String j_string = new String(string);
+ //String j_string = new String(string);
} // end while not EOF
@@ -902,7 +905,7 @@ public class AutoFormat {
*/
// save current (rough) selection point
- int selectionEnd = editor.textarea.getSelectionEnd();
+ int selectionEnd = editor.getSelectionStop();
// make sure the caret would be past the end of the text
if (strOut.length() < selectionEnd - 1) {
@@ -913,30 +916,31 @@ public class AutoFormat {
String formattedText = strOut.toString();
if (formattedText.equals(originalText)) {
- editor.message("No changes necessary for Auto Format.");
+ editor.statusNotice("No changes necessary for Auto Format.");
} else if (paren != 0) {
// warn user if there are too many parens in either direction
- editor.error("Auto Format Canceled: Too many " +
- ((paren < 0) ? "right" : "left") +
- " parentheses.");
+ 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.error("Auto Format Canceled: Too many " +
- ((c_level < 0) ? "right" : "left") +
- " curly braces.");
+ } 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 {
+ } else {
// replace with new bootiful text
// selectionEnd hopefully at least in the neighborhood
- editor.setText(formattedText, selectionEnd, selectionEnd);
- editor.sketch.setModified(true);
+ editor.setText(formattedText);
+ editor.setSelection(selectionEnd, selectionEnd);
+ editor.getSketch().setModified(true);
// mark as finished
- editor.message("Auto Format finished.");
- }
+ editor.statusNotice("Auto Format finished.");
+ }
} catch (Exception e) {
- editor.error(e);
+ editor.statusError(e);
}
}
}
diff --git a/app/src/processing/app/tools/ColorSelector.java b/app/src/processing/app/tools/ColorSelector.java
new file mode 100644
index 000000000..d4843d18a
--- /dev/null
+++ b/app/src/processing/app/tools/ColorSelector.java
@@ -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.
+ *
+ * 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
+ }
+ }
+}
diff --git a/app/src/processing/app/tools/CreateFont.java b/app/src/processing/app/tools/CreateFont.java
new file mode 100644
index 000000000..663798985
--- /dev/null
+++ b/app/src/processing/app/tools/CreateFont.java
@@ -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);
+ }
+}
diff --git a/app/src/processing/app/tools/DiscourseFormat.java b/app/src/processing/app/tools/DiscourseFormat.java
new file mode 100644
index 000000000..a9a40d299
--- /dev/null
+++ b/app/src/processing/app/tools/DiscourseFormat.java
@@ -0,0 +1,228 @@
+/* -*- 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
+ *
+ * Original code by owd.
+ * 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.
+ *
+ * Updated for 0122 to simply copy the code directly to the clipboard,
+ * rather than opening a new window.
+ *
+ * Updated for 0144 to only format the selected lines.
+ *
+ * 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;
+ boolean html;
+
+
+ /**
+ * 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, boolean html) {
+ this.editor = editor;
+ this.textarea = editor.getTextArea();
+ this.html = html;
+ }
+
+
+ /**
+ * Format and render sketch code.
+ */
+ public void show() {
+ // [code] tag cancels other tags, using [quote]
+ StringBuffer cf = new StringBuffer(html ? "
\n" : "[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(html ? "\n
" : "\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 " +
+ (html ? "HTML" : "the Arduino forum ") +
+ " 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(html ? "" : "]");
+
+ if (styles[id].isBold())
+ cf.append(html ? "" : "[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(html ? " " : '\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(html ? "" : "[/b]");
+ if (j == (length - 1) && id != Token.NULL)
+ cf.append(html ? "" : "[/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;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/processing/app/tools/FixEncoding.java b/app/src/processing/app/tools/FixEncoding.java
new file mode 100644
index 000000000..ecdfc6df9
--- /dev/null
+++ b/app/src/processing/app/tools/FixEncoding.java
@@ -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();
+ }
+}
\ No newline at end of file
diff --git a/app/src/processing/app/tools/Tool.java b/app/src/processing/app/tools/Tool.java
new file mode 100644
index 000000000..7278452e0
--- /dev/null
+++ b/app/src/processing/app/tools/Tool.java
@@ -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();
+}
+
diff --git a/app/src/processing/app/tools/format/src/AutoFormat.java b/app/src/processing/app/tools/format/src/AutoFormat.java
new file mode 100644
index 000000000..e047e9371
--- /dev/null
+++ b/app/src/processing/app/tools/format/src/AutoFormat.java
@@ -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
+ * Jalopy. 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);
+ }
+ }
+}
diff --git a/app/src/processing/app/tools/format/tool/jalopy.jar b/app/src/processing/app/tools/format/tool/jalopy.jar
new file mode 100644
index 000000000..fe51ce230
Binary files /dev/null and b/app/src/processing/app/tools/format/tool/jalopy.jar differ
diff --git a/app/src/processing/app/tools/format/tool/log4j.jar b/app/src/processing/app/tools/format/tool/log4j.jar
new file mode 100644
index 000000000..493a3ccc1
Binary files /dev/null and b/app/src/processing/app/tools/format/tool/log4j.jar differ
diff --git a/app/src/processing/app/windows/Advapi32.java b/app/src/processing/app/windows/Advapi32.java
new file mode 100644
index 000000000..0534d6b21
--- /dev/null
+++ b/app/src/processing/app/windows/Advapi32.java
@@ -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;
+ }
+}
+
+
diff --git a/app/src/processing/app/windows/Options.java b/app/src/processing/app/windows/Options.java
new file mode 100644
index 000000000..f5cff2888
--- /dev/null
+++ b/app/src/processing/app/windows/Options.java
@@ -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 UNICODE_OPTIONS = new HashMap() {
+ {
+ put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
+ put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
+ }
+ };
+}
diff --git a/app/src/processing/app/windows/Platform.java b/app/src/processing/app/windows/Platform.java
new file mode 100644
index 000000000..cdc685ecf
--- /dev/null
+++ b/app/src/processing/app/windows/Platform.java
@@ -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, "Arduino");
+ 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, "Arduino");
+ }
+
+
+ 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 + "\"");
+ }
+}
diff --git a/app/src/processing/app/windows/Registry.java b/app/src/processing/app/windows/Registry.java
new file mode 100644
index 000000000..71fa5eebe
--- /dev/null
+++ b/app/src/processing/app/windows/Registry.java
@@ -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 rootKeyMap = new HashMap();
+
+ 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 subKeys = new TreeSet();
+
+ 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 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 values = new TreeMap(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);
+ }
+}
diff --git a/app/src/processing/app/windows/WINBASE.java b/app/src/processing/app/windows/WINBASE.java
new file mode 100644
index 000000000..c4807cc90
--- /dev/null
+++ b/app/src/processing/app/windows/WINBASE.java
@@ -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;
+ }
+}
diff --git a/app/src/processing/app/windows/WINERROR.java b/app/src/processing/app/windows/WINERROR.java
new file mode 100644
index 000000000..3e1146e93
--- /dev/null
+++ b/app/src/processing/app/windows/WINERROR.java
@@ -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;
+}
diff --git a/app/src/processing/app/windows/WINNT.java b/app/src/processing/app/windows/WINNT.java
new file mode 100644
index 000000000..89aa36168
--- /dev/null
+++ b/app/src/processing/app/windows/WINNT.java
@@ -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
+
+}
diff --git a/app/src/processing/app/windows/WINREG.java b/app/src/processing/app/windows/WINREG.java
new file mode 100644
index 000000000..988f7ef36
--- /dev/null
+++ b/app/src/processing/app/windows/WINREG.java
@@ -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;
+}
diff --git a/app/syntax/PdeKeywords.java b/app/syntax/PdeKeywords.java
deleted file mode 100644
index 8dec16b6c..000000000
--- a/app/syntax/PdeKeywords.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- mode: jde; 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.
- *
- * Uses getKeywords() method because that's part of the
- * TokenMarker classes.
- *
- * 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.getStream("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;
-
- // don't bother if line begins with hash
- if(0 < line.length()){
- if('#' == line.charAt(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 Arduino.", e);
- System.exit(1);
- }
- }
- return keywordColoring;
- }
-
-
- static public String getReference(String keyword) {
- return (String) keywordToReference.get(keyword);
- }
-
- static public KeywordMap getKeywordColoring() {
- return keywordColoring;
- }
-}
diff --git a/app/tools/DiscourseFormat.java b/app/tools/DiscourseFormat.java
deleted file mode 100644
index 240cf56b3..000000000
--- a/app/tools/DiscourseFormat.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2005-06 Ignacio Manuel González Moreta
- 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 java.awt.*;
-import java.awt.datatransfer.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.text.Segment;
-
-import processing.app.*;
-import processing.app.syntax.*;
-import processing.core.PApplet;
-
-/**
- * Format for Discourse Tool
- *
- * Original code by owd.
- * Revised and updated for revision 0108 by Ben Fry (10 March 2006).
- * This code will later be removed but is included with release 0108+
- * while features for the "Tools" menu are in testing.
- *
- * Updated for 0122 to simply copy the code directly to the clipboard,
- * rather than opening a new window.
- *
- * 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 {
-
- //static final String WINDOW_TITLE = "Format for Discourse by owd";
-
- // p5 icon for the window
- //static Image icon;
-
- Editor editor;
- //JEditTextArea textarea;
-
- // JTextArea of the actual Editor
- JEditTextArea parent;
-
- //JFrame frame;
-
- boolean html;
-
- /**
- * 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, boolean html) {
- this.editor = editor;
- this.parent = editor.textarea;
- this.html = html;
-
- /*
- textarea = new JEditTextArea(new PdeTextAreaDefaults());
- textarea.setRightClickPopup(new DiscourseTextAreaPopup());
- textarea.setTokenMarker(new PdeKeywords());
- textarea.setHorizontalOffset(6);
-
- textarea.setEditable(false);
-
- // Create and set up the window.
- frame = new JFrame(WINDOW_TITLE);
- frame.setSize(500, 500);
-
- // set the window icon
- try {
- icon = Base.getImage("icon.gif", frame);
- frame.setIconImage(icon);
- } catch (Exception e) { } // fail silently, no big whup
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-
- Container pain = frame.getContentPane();
- pain.setLayout(new BorderLayout());
- pain.add(textarea, BorderLayout.CENTER);
-
- frame.setResizable(true);
-
- frame.pack();
- frame.setLocation(100, 100);
- //frame.setVisible(true);
- */
- }
-
-
- public void show() {
- // Format and render sketchcode
-
- // [code] tag cancels other tags, using [quote]
- StringBuffer cf = new StringBuffer(html ? "
\n" : "[quote] \n");
-
- // Line by line
- for (int i = 0; i < parent.getLineCount(); i++) {
- cf.append(formatCode(i));
- }
-
- cf.append(html ? "
" : "[/quote]");
-
- /*
- // Send the text to the textarea
- textarea.setText(cf.toString());
- textarea.select(0, 0);
-
- frame.show();
- */
-
- 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.message((html ? "HTML" : "Forum") + "-formatted code has " +
- "been copied to the clipboard.");
- }
-
-
- // A terrible headache...
- public String formatCode(int line) {
- StringBuffer cf = new StringBuffer();
-
- // Segment
- Segment lineSegment = new Segment();
-
- TextAreaPainter painter = parent.getPainter();
- TokenMarker tokenMarker = parent.getTokenMarker();
-
- // Use painter's cached info for speed
- FontMetrics fm = painter.getFontMetrics();
-
- // get line text from parent textarea
- parent.getLineText(line, lineSegment);
-
- char[] segmentArray = lineSegment.array;
- int limit = lineSegment.getEndIndex();
- int segmentOffset = lineSegment.offset;
- int segmentCount = lineSegment.count;
- int width = 0; //parent.getHorizontalOffset();
-
- int x = 0; //parent.getHorizontalOffset();
-
- // 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); //concat(character(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.currentLineIndex = line;
- painter.setCurrentLineTokens(tokenMarker.markTokens(lineSegment, line));
- tokens = painter.getCurrentLineTokens();
- }
-
- int offset = 0;
- Toolkit toolkit = painter.getToolkit();
- Font defaultFont = painter.getFont();
- SyntaxStyle[] styles = painter.getStyles();
-
- for (;;) {
- byte id = tokens.id;
- if (id == Token.END) {
- if (segmentOffset + offset < limit) {
- cf.append(segmentArray[segmentOffset + offset]);
- } else {
- cf.append('\n');
- }
- return cf.toString();
- }
- if (id == Token.NULL) {
- fm = painter.getFontMetrics();
- } else {
- // Place open tags []
- //cf.append("[color=" + color() + "]");
- cf.append(html ? "" : "]");
-
- if (styles[id].isBold())
- cf.append(html ? "" : "[b]");
-
- fm = styles[id].getFontMetrics(defaultFont);
- }
- int length = tokens.length;
-
- for (int j = 0; j < length; j++) {
- char c = segmentArray[segmentOffset + offset + j];
- cf.append(c);
- // Place close tags [/]
- if (j == (length - 1) && id != Token.NULL && styles[id].isBold())
- cf.append(html ? "" : "[/b]");
- if (j == (length - 1) && id != Token.NULL)
- cf.append(html ? "" : "[/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;
- }
- }
- return cf.toString();
- }
-
-
- /**
- * Returns the discourse popup menu. Another features can be added: format
- * selected text with a determinated tag (I'm thinking about [url]selected
- * text[/url])
- */
- /*
- class DiscourseTextAreaPopup extends JPopupMenu {
- JMenuItem copyItem;
-
- public DiscourseTextAreaPopup() {
- JMenuItem item;
-
- copyItem = new JMenuItem("Copy");
- copyItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.copy();
- }
- });
- this.add(copyItem);
-
- item = new JMenuItem("Select All");
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- textarea.selectAll();
- }
- });
- this.add(item);
- }
-
- // if no text is selected, disable copy menu item
- public void show(Component component, int x, int y) {
- if (textarea.isSelectionActive()) {
- copyItem.setEnabled(true);
-
- } else {
- copyItem.setEnabled(false);
- }
- super.show(component, x, y);
- }
- }
- */
-
-
- /*
- // A false listener (use the mouse)
- public class DiscourseListener {
-
- public DiscourseListener(JEditTextArea thisTextarea) {
- // I'm a... I know this gives peoblems, but all this code
- // is a funny hacking experiment
- thisTextarea.editorListener = parent.editorListener;
- }
-
- public boolean keyPressed(KeyEvent event) {
- System.out.println("Is your mouse lone some tonight...");
- return false;
- }
- }
- */
-}
\ No newline at end of file
diff --git a/app/tools/ExportFolder.java b/app/tools/ExportFolder.java
deleted file mode 100755
index 25ca32145..000000000
--- a/app/tools/ExportFolder.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- ExportFolder - tool to export all sketches within a certain folder
- 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.tools;
-
-import processing.app.*;
-
-import java.io.*;
-import java.text.*;
-import java.util.*;
-import java.util.zip.*;
-
-import javax.swing.*;
-
-
-public class ExportFolder {
- Editor editor;
- static JFileChooser fc;
-
-
- public ExportFolder(Editor editor) {
- this.editor = editor;
-
- if (fc == null) {
- fc = new JFileChooser();
- fc.setSelectedFile(new File(Sketchbook.getSketchbookPath()));
- fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
- }
- }
-
-
- public void show() {
- if (fc.showOpenDialog(new JDialog()) != JFileChooser.APPROVE_OPTION) {
- return;
- }
-
- File folder = fc.getSelectedFile();
- // export everything under this folder
-
- Vector sketches = new Vector();
- try {
- addSketches(sketches, folder);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- boolean success = true;
- int counter = 0;
-
- try {
- // iterate through the list
- Enumeration en = sketches.elements();
- while (en.hasMoreElements()) {
- editor.message("Exporting sketch " + (++counter) +
- " of " + sketches.size());
- String path = (String) en.nextElement();
- editor.handleOpen(path);
- // success may not be that useful, usually an ex is thrown
- success = editor.sketch.exportApplet(new Target(
- System.getProperty("user.dir") + File.separator + "hardware" +
- File.separator + "cores",
- Preferences.get("boards." + Preferences.get("board") + ".build.core")));
- if (!success) break;
- //System.out.println("success was " + success);
- }
- } catch (Exception e) {
- editor.error(e);
- success = false;
- //e.printStackTrace();
- }
-
- if (success) {
- editor.message("Done exporting.");
- } // else the error message will be visible
- }
-
-
- protected void addSketches(Vector sketches, File folder) throws IOException {
-
- // skip .DS_Store files, etc
- if (!folder.isDirectory()) return; // false;
-
- System.out.println(folder.getAbsolutePath());
-
- String list[] = folder.list();
- // if a bad folder or something like that, this might come back null
- if (list == null) return; // false;
-
- for (int i = 0; i < list.length; i++) {
- if (list[i].charAt(0) == '.') continue;
-
- File subfolder = new File(folder, list[i]);
- File entry = new File(subfolder, list[i] + ".pde");
- // if a .pde file of the same prefix as the folder exists..
- if (entry.exists()) {
- sketches.add(entry.getAbsolutePath());
-
- } else if (subfolder.isDirectory()) { // only follow if a dir
- addSketches(sketches, subfolder);
- }
- }
- }
-}
diff --git a/build/auto-build/arduino-rsync-checkout b/build/auto-build/arduino-rsync-checkout
deleted file mode 100755
index d6469729b..000000000
--- a/build/auto-build/arduino-rsync-checkout
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-# update from the Berlios SVN repository
-
-# the source dir where this script is
-SCRIPT_DIR=`echo $0 | sed 's|\(.*\)/.*$|\1|'`
-. $SCRIPT_DIR/auto-build-common
-
-# the name of this script
-SCRIPT=`echo $0| sed 's|.*/\(.*\)|\1|g'`
-LOGFILE=/home/arduino/logs/${DATE}_${TIME}_-_${SCRIPT}_-_${SYSTEM}.txt
-
-touch $LOGFILE
-
-for dir in /home/arduino/rsync/*; do
- dirname=`echo $dir | sed 's|.*/\(.*\)|\1|'`
- echo $dirname ---------------------------- >> ${LOGFILE}
- cd $dir
- svn up >> ${LOGFILE}
-done
diff --git a/build/auto-build/arduino-trunk-auto-build b/build/auto-build/arduino-trunk-auto-build
deleted file mode 100755
index 24b2fd0e5..000000000
--- a/build/auto-build/arduino-trunk-auto-build
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/bin/sh
-# this script is the first attempt to have an automated updater and builder
-
-# the source dir where this script is
-SCRIPT_DIR=`echo $0 | sed 's|\(.*\)/.*$|\1|'`
-. $SCRIPT_DIR/auto-build-common
-
-# the name of this script
-SCRIPT=`echo $0| sed 's|.*/\(.*\)|\1|g'`
-
-BUILD_DIR=.
-case $SYSTEM in
- linux)
- BUILD_DIR=linux
- echo "Configuring to use $BUILD_DIR on GNU/Linux"
- ;;
- darwin)
- BUILD_DIR=macosx
- echo "Configuring to use $BUILD_DIR on Darwin/Mac OS X"
- ;;
- mingw*)
- BUILD_DIR=windows
- echo "Configuring to use $BUILD_DIR on MinGW/Windows"
- ;;
- cygwin*)
- BUILD_DIR=windows
- echo "Configuring to use $BUILD_DIR on Cygwin/Windows"
- ;;
- *)
- echo "ERROR: Platform $SYSTEM not supported!"
- exit
- ;;
-esac
-
-
-# convert into absolute path
-cd `echo $0 | sed 's|\(.*\)/.*$|\1|'`/../..
-auto_build_root_dir=`pwd`
-echo "root: $auto_build_root_dir"
-
-# let rsync handle the cleanup with --delete
-case $SYSTEM in
- mingw*)
- /c/cygwin/bin/sh --login -c \
- "rsync -a --delete rsync://128.238.56.50/arduino/arduino-trunk/ ${auto_build_root_dir}/"
- ;;
- *)
- rsync -a --delete rsync://128.238.56.50/arduino/arduino-trunk/ ${auto_build_root_dir}/
- ;;
-esac
-
-cd "${auto_build_root_dir}/build/$BUILD_DIR"
-./dist.sh
-
-upload_build ()
-{
- platform_folder=$1
- build_folder=$2
- archive_format=$3
-
- archive="${auto_build_root_dir}/build/${platform_folder}/${build_folder}/arduino*.${archive_format}"
-
- echo "upload specs $1 $2 $3"
- echo "Uploading $archive"
- upload_filename=`ls -1 ${archive} | sed "s|.*/\(.*\)\.${archive_format}|\1-${HOSTNAME}.${archive_format}|"`
- case $SYSTEM in
- mingw*)
- if [ -e ${archive} ]; then
- /c/cygwin/bin/sh --login -c \
- "rsync -a ${archive} rsync://128.238.56.50/arduinoupload/${DATE}/${upload_filename}" && \
- md5sum ${archive} > ${archive}.md5 && \
- /c/cygwin/bin/sh --login -c \
- "rsync -a ${archive}.md5 rsync://128.238.56.50/arduinoupload/${DATE}/${upload_filename}.md5" && \
- echo SUCCESS
- fi
- ;;
- *)
- if [ -e ${archive} ]; then
- rsync -a ${archive} rsync://128.238.56.50/arduinoupload/${DATE}/${upload_filename} && \
- md5sum ${archive} > ${archive}.md5 && \
- rsync -a ${archive}.md5 rsync://128.238.56.50/arduinoupload/${DATE}/${upload_filename}.md5 && \
- echo SUCCESS
- fi
- ;;
- esac
-}
-
-
-case $SYSTEM in
- linux)
- upload_build linux . tgz
- ;;
- darwin)
- upload_build macosx . zip
- ;;
- mingw*)
- upload_build windows . zip
- ;;
- cygwin*)
- upload_build windows . zip
- ;;
-esac
-
diff --git a/build/auto-build/auto-build-common b/build/auto-build/auto-build-common
deleted file mode 100644
index 73134d51f..000000000
--- a/build/auto-build/auto-build-common
+++ /dev/null
@@ -1,29 +0,0 @@
-# these are common variables for the auto-build scripts
-
-HOSTNAME=`hostname | sed 's|\([a-zA-Z0-9-]\)\..*|\1|' | sed 'y|ABCDEFGHIJKLMNOPQRSTUVWXYZ|abcdefghijklmnopqrstuvwxyz|'`
-SYSTEM=`uname -s | sed 'y|ABCDEFGHIJKLMNOPQRSTUVWXYZ|abcdefghijklmnopqrstuvwxyz|'`
-DATE=`date +%Y-%m-%d`
-TIME=`date +%H.%M.%S`
-
-## the following creates a spam-bot that sends emails to an address that has not asked for it
-## because of the spam-problem, i (jmz) have disabled it
-# recipient of any emails set from the scripts
-#RECIPIENT=pd-cvs@iem.at
-
-
-## if you want to send emails about the success of your build,
-## please create a file "auto-build-common.local" in this directory
-## and set the "RECIPIENT" address to some valid email-address
-#
-## please do NOT check your auto-build-common.local into the CVS
-#
-## another possibility is to set the "RECIPIENT" environmental variable before running
-## the autobuilder
-
-if [ -e ${SCRIPT_DIR}/auto-build-common.local ]; then
- . ${SCRIPT_DIR}/auto-build-common.local
-else
- echo "Could not find local configuration in \"${SCRIPT_DIR}/auto-build-common.local\""
- echo "Skipping... (see ${SCRIPT_DIR}/auto-build-common for instructions)"
- echo
-fi
diff --git a/build/auto-build/run-auto-builds b/build/auto-build/run-auto-builds
deleted file mode 100755
index 3f50a9769..000000000
--- a/build/auto-build/run-auto-builds
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-
-cd /
-
-# On Mac OS X, there are some handy things in Fink, but don't override the
-# built-in tools
-PATH="${PATH}:/sw/bin:/sw/sbin"
-export PATH
-
-# the source dir where this script is
-SCRIPT_DIR=`echo $0 | sed 's|\(.*\)/.*$|\1|'`
-. $SCRIPT_DIR/auto-build-common
-
-# the name of this script
-SCRIPT=`echo $0| sed 's|.*/\(.*\)|\1|g'`
-
-run_build_script ()
-{
- distro=$1
-
- LOGFILE=/home/arduino/logs/${DATE}_${TIME}_${SYSTEM}_${HOSTNAME}_${distro}_${SCRIPT}.txt
- touch ${LOGFILE}
-
- sh /home/arduino/auto-build/${distro}/build/auto-build/${distro}-auto-build >> $LOGFILE 2>&1
-
- case $SYSTEM in
- mingw*)
- /c/cygwin/bin/sh --login -c \
- "rsync -a ${LOGFILE} rsync://128.238.56.50/arduinoupload/${DATE}/logs/"
- ;;
- *)
- rsync -a ${LOGFILE} rsync://128.238.56.50/arduinoupload/${DATE}/logs/
- ;;
- esac
-
-# send status report if something failed
- completion_test=`tail -1 ${LOGFILE}`
- if [ "x${completion_test}" != "xSUCCESS" ]; then
- if [ "x${RECIPIENT}" != "x" ]; then
- SUBJECT="autobuild: $distro $HOSTNAME $DATE $TIME"
- tail -20 ${LOGFILE} | mail -s "${SUBJECT}" ${RECIPIENT}
- fi
- fi
-}
-
-for dir in /home/arduino/auto-build/*; do
- dirname=`echo $dir | sed 's|.*/\(.*\)|\1|'`
- test -e $dir/build/auto-build/${dirname}-auto-build && \
- run_build_script $dirname
-done
diff --git a/build/cmd/dist.sh b/build/cmd/dist.sh
new file mode 100755
index 000000000..38d295365
--- /dev/null
+++ b/build/cmd/dist.sh
@@ -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.
diff --git a/build/cmd/dist/processing b/build/cmd/dist/processing
new file mode 100644
index 000000000..8f6944154
--- /dev/null
+++ b/build/cmd/dist/processing
@@ -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"
diff --git a/build/create_reference.pl b/build/create_reference.pl
index d49b6b610..f3270cec4 100644
--- a/build/create_reference.pl
+++ b/build/create_reference.pl
@@ -12,7 +12,7 @@ use warnings;
my $verbose = 1;
my $CURL_OPTIONS = '--silent --show-error';
-my $ARDUINO = 'http://www.arduino.cc/en'; # base url for arduino site
+my $ARDUINO = 'http://arduino.cc/en'; # base url for arduino site
my %downloaded = (); # keep track of the pages we download
@@ -28,6 +28,7 @@ my $wire = create_page('Wire.html', "$ARDUINO/Reference/Wire");
my $servo = create_page('Servo.html', "$ARDUINO/Reference/Servo");
my $lcd = create_page('LiquidCrystal.html', "$ARDUINO/Reference/LiquidCrystal");
my $ethernet = create_page('Ethernet.html', "$ARDUINO/Reference/Ethernet");
+my $serial = create_page('Serial.html', "$ARDUINO/Reference/Serial");
create_linked_pages($guide, qr!$ARDUINO/Guide/(\w+)!, 'Guide_%%.html');
create_linked_pages($softser, qr!$ARDUINO/Reference/(SoftwareSerial\w+)!, '%%.html');
@@ -39,10 +40,10 @@ create_linked_pages($lcd, qr!$ARDUINO/Reference/(LiquidCrystal\w+)!, '%%.
create_linked_pages($ethernet, qr!$ARDUINO/Reference/(Ethernet\w+)!, '%%.html');
create_linked_pages($ethernet, qr!$ARDUINO/Reference/(Server\w+)!, '%%.html');
create_linked_pages($ethernet, qr!$ARDUINO/Reference/(Client\w+)!, '%%.html');
+create_linked_pages($serial, qr!$ARDUINO/Serial/(\w+)!, 'Serial_%%.html');
my $index = create_page('index.html', "$ARDUINO/Reference/HomePage");
-create_linked_pages($index, qr!$ARDUINO/Serial/(\w+)!, 'Serial_%%.html');
create_linked_pages($index, qr!$ARDUINO/Reference/(\w+)!, '%%.html');
my $ext = create_page('Extended.html', "$ARDUINO/Reference/Extended");
diff --git a/build/howto.txt b/build/howto.txt
index 49c7a8842..d2103b03c 100755
--- a/build/howto.txt
+++ b/build/howto.txt
@@ -1,98 +1,167 @@
-HOW TO BUILD ARDUINO ON YOUR FAVORITE PLATFORM
-
-
-////////////////////////////////////////////////////////////////////
-
-//// 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:
-
-+ svn - used for version control
-
-+ make, gcc-mingw, and g++ - used to build arduino.exe
- (this will also pull in gcc-core)
-
-+ perl - use this version, activestate or other distros have trouble
-
-+ unzip, zip - for dealing with archives
-
-+ included in the defaults, but make sure:
- coreutils (or textutils), gzip, tar
-
-+ not required but useful:
- openssh - command line ssh client
- nano - handy/simple text editor
-
-** 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 and subversion.
-
-1c. On Linux, you need the Sun Java SDK, avr-gcc, make, and subversion.
-
-
-2. GRAB THE CODE FROM BERLIOS
-
-* this grabs the code as an anonymous user.
-
-# grab the code, it'll take a while
-svn co svn://svn.berlios.de/arduino/trunk arduino
-# (maybe even a long while for you dialup and international folks)
-
-
-3. BUILD IT
+HOW TO BUILD PROCESSING ON YOUR FAVORITE PLATFORM
-3a. On the Mac, use the Xcode project to build the Arduino software.
- Set the active target to App to run Arduino, or to Distribute to
- create a .zip file.
+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
-3b. On Windows or Linux, use the command line.
-
-# on Windows
-cd /path/to/arduino/build/windows
-
-# or if you're on linux
-cd /path/to/arduino/build/linux
-
-# 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
-
-
-4a. Each time you want to update to latest version from svn:
-
-cd /path/to/arduino
-svn update
-
-
-4b. If new folders have been added, or you're gettin odd errors, use:
-
-# remove the work directory
-rm -rf work
-
-$Id$
+
+////////////////////////////////////////////////////////////////////
+
+//// 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
diff --git a/build/javadoc/core/allclasses-frame.html b/build/javadoc/core/allclasses-frame.html
new file mode 100644
index 000000000..ae3faeefb
--- /dev/null
+++ b/build/javadoc/core/allclasses-frame.html
@@ -0,0 +1,87 @@
+
+
+
+
+
+All Classes
+
+
+
+
+
+
+
+
+
+
+All Classes
+
+
+
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+Overview
+
+
+
+The Overview 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.
+
+Package
+
+
+
+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:
+
Interfaces (italic)
Classes
Enums
Exceptions
Errors
Annotation Types
+
+
+Class/Interface
+
+
+
+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:
+
Class inheritance diagram
Direct Subclasses
All Known Subinterfaces
All Known Implementing Classes
Class/interface declaration
Class/interface description
+
+
Nested Class Summary
Field Summary
Constructor Summary
Method Summary
+
+
Field Detail
Constructor Detail
Method Detail
+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.
+
+
+Annotation Type
+
+
+
+Each annotation type has its own separate page with the following sections:
+
Annotation Type declaration
Annotation Type description
Required Element Summary
Optional Element Summary
Element Detail
+
+
+
+Enum
+
+
+
+Each enum has its own separate page with the following sections:
+
Enum declaration
Enum description
Enum Constant Summary
Enum Constant Detail
+
+
+Tree (Class Hierarchy)
+
+There is a Class Hierarchy 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 java.lang.Object. The interfaces do not inherit from java.lang.Object.
+
When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
+
+
+Deprecated API
+
+The Deprecated API 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.
+
+Index
+
+The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
+
+Prev/Next
+These links take you to the next or previous class, interface, package, or related page.
+Frames/No Frames
+These links show and hide the HTML frames. All pages are available with or without frames.
+
+
+Serialized Form
+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.
+
Create a .vlw font on the fly from either a font name that's
+ installed on the system, or from a .ttf or .otf that's inside
+ the data folder of this sketch.
+
Preferred method of creating new PImage objects, ensures that a
+ reference to the parent PApplet is included, which makes save() work
+ without needing an absolute path.
+
Called by the browser or applet viewer to inform this applet
+ that it is being reclaimed and that it should destroy
+ any resources that it has allocated.
+
Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
+ 'keyCode', and 'keyEvent' variables to no longer work;
+ key events will no longer be queued until the end of draw();
+ and the keyPressed(), keyReleased() and keyTyped() methods
+ will no longer be called.
+
If you override this or any function that takes a "MouseEvent e"
+ without calling its super.mouseXxxx() then mouseX, mouseY,
+ mousePressed, and mouseEvent will no longer be set.
+
number format signed (or space)
+ Formats a number but leaves a blank space in the front
+ when it's positive so that it can be properly aligned with
+ numbers that have a negative sign in front of them.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
Sets the text rendering/placement to be either SCREEN (direct
+ to the screen, exact coordinates, only use the font's original size)
+ or MODEL (the default, where text is manipulated by translate() and
+ can have a textSize).
+
remove(java.lang.Object object,
+ java.lang.reflect.Method method)
+
+
+ Removes first object/method pair matched (and only the first,
+ must be called multiple times if object is registered multiple times).
Removes first object/method pair matched (and only the first,
+ must be called multiple times if object is registered multiple times).
+ Does not shrink array afterwards, silently returns if method not found.
+
public static class PApplet.RendererChangeException
extends java.lang.RuntimeException
+
+
+
+Exception thrown when size() is called the first time.
+
+ This is used internally so that setup() is forced to run twice
+ when the renderer is changed. This is the only way for us to handle
+ invoking the new renderer while also in the midst of rendering.
+
+Base class for all sketches that use processing.core.
+
+ Note that you should not use AWT or Swing components inside a Processing
+ applet. The surface is made to automatically update itself, and will cause
+ problems with redraw of components drawn above it. If you'd like to
+ integrate other Java components, see below.
+
+ As of release 0145, Processing uses active mode rendering in all cases.
+ All animation tasks happen on the "Processing Animation Thread". The
+ setup() and draw() methods are handled by that thread, and events (like
+ mouse movement and key presses, which are fired by the event dispatch
+ thread or EDT) are queued to be (safely) handled at the end of draw().
+ For code that needs to run on the EDT, use SwingUtilities.invokeLater().
+ When doing so, be careful to synchronize between that code (since
+ invokeLater() will make your code run from the EDT) and the Processing
+ animation thread. Use of a callback function or the registerXxx() methods
+ in PApplet can help ensure that your code doesn't do something naughty.
+
+ As of release 0136 of Processing, we have discontinued support for versions
+ of Java prior to 1.5. We don't have enough people to support it, and for a
+ project of our size, we should be focusing on the future, rather than
+ working around legacy Java code. In addition, Java 1.5 gives us access to
+ better timing facilities which will improve the steadiness of animation.
+
+ This class extends Applet instead of JApplet because 1) historically,
+ we supported Java 1.1, which does not include Swing (without an
+ additional, sizable, download), and 2) Swing is a bloated piece of crap.
+ A Processing applet is a heavyweight AWT component, and can be used the
+ same as any other AWT component, with or without Swing.
+
+ Similarly, Processing runs in a Frame and not a JFrame. However, there's
+ nothing to prevent you from embedding a PApplet into a JFrame, it's just
+ that the base version uses a regular AWT frame because there's simply
+ no need for swing in that context. If people want to use Swing, they can
+ embed themselves as they wish.
+
+ It is possible to use PApplet, along with core.jar in other projects.
+ In addition to enabling you to use Java 1.5+ features with your sketch,
+ this also allows you to embed a Processing drawing area into another Java
+ application. This means you can use standard GUI controls with a Processing
+ sketch. Because AWT and Swing GUI components cannot be used on top of a
+ PApplet, you can instead embed the PApplet inside another GUI the way you
+ would any other Component.
+
+ It is also possible to resize the Processing window by including
+ frame.setResizable(true) inside your setup() method.
+ Note that the Java method frame.setSize() will not work unless
+ you first set the frame to be resizable.
+
+ Because the default animation thread will run at 60 frames per second,
+ an embedded PApplet can make the parent sluggish. You can use frameRate()
+ to make it update less often, or you can use noLoop() and loop() to disable
+ and then re-enable looping. If you want to only update the sketch
+ intermittently, use noLoop() inside setup(), and redraw() whenever
+ the screen needs to be updated once (or loop() to re-enable the animation
+ thread). The following example embeds a sketch and also uses the noLoop()
+ and redraw() methods. You need not use noLoop() and redraw() when embedding
+ if you want your application to animate continuously.
+
+ public class ExampleFrame extends Frame {
+
+ public ExampleFrame() {
+ super("Embedded PApplet");
+
+ setLayout(new BorderLayout());
+ PApplet embed = new Embedded();
+ add(embed, BorderLayout.CENTER);
+
+ // important to call this whenever embedding a PApplet.
+ // It ensures that the animation thread is started and
+ // that other internal variables are properly set.
+ embed.init();
+ }
+ }
+
+ public class Embedded extends PApplet {
+
+ public void setup() {
+ // original setup code here ...
+ size(400, 400);
+
+ // prevent thread from starving everything else
+ noLoop();
+ }
+
+ public void draw() {
+ // drawing code goes here
+ }
+
+ public void mousePressed() {
+ // do something based on mouse movement
+
+ // update the screen (run draw once)
+ redraw();
+ }
+ }
+
+
+
Processing on multiple displays
+
I was asked about Processing with multiple displays, and for lack of a
+ better place to document it, things will go here.
+
You can address both screens by making a window the width of both,
+ and the height of the maximum of both screens. In this case, do not use
+ present mode, because that's exclusive to one screen. Basically it'll
+ give you a PApplet that spans both screens. If using one half to control
+ and the other half for graphics, you'd just have to put the 'live' stuff
+ on one half of the canvas, the control stuff on the other. This works
+ better in windows because on the mac we can't get rid of the menu bar
+ unless it's running in present mode.
+
For more control, you need to write straight java code that uses p5.
+ You can create two windows, that are shown on two separate screens,
+ that have their own PApplet. this is just one of the tradeoffs of one of
+ the things that we don't support in p5 from within the environment
+ itself (we must draw the line somewhere), because of how messy it would
+ get to start talking about multiple screens. It's also not that tough to
+ do by hand w/ some Java code.
arraycopy(java.lang.Object src,
+ int srcPosition,
+ java.lang.Object dst,
+ int dstPosition,
+ int length)
+
+
+ Deprecated.Use arrayCopy() instead.
+
+
+
+static void
+
arrayCopy(java.lang.Object src,
+ int srcPosition,
+ java.lang.Object dst,
+ int dstPosition,
+ int length)
+
+
+ Calls System.arraycopy(), included here so that we can
+ avoid people needing to learn about the System object
+ before they can just copy an array.
beginRaw(java.lang.String renderer,
+ java.lang.String filename)
+
+
+ Begin recording raw shape data to a renderer of the specified type,
+ using the width and height of the main drawing surface.
+
+
+
+ void
+
beginRecord(PGraphics recorder)
+
+
+ Begin recording (echoing) commands to the specified PGraphics object.
beginRecord(java.lang.String renderer,
+ java.lang.String filename)
+
+
+ Begin recording to a new renderer of the specified type, using the width
+ and height of the main drawing surface.
createFont(java.lang.String name,
+ float size,
+ boolean smooth,
+ char[] charset)
+
+
+ Create a .vlw font on the fly from either a font name that's
+ installed on the system, or from a .ttf or .otf that's inside
+ the data folder of this sketch.
createGraphics(int iwidth,
+ int iheight,
+ java.lang.String irenderer,
+ java.lang.String ipath)
+
+
+ Create an offscreen graphics surface for drawing, in this case
+ for a renderer that writes to a file (such as PDF or DXF).
createImage(int wide,
+ int high,
+ int format)
+
+
+ Preferred method of creating new PImage objects, ensures that a
+ reference to the parent PApplet is included, which makes save() work
+ without needing an absolute path.
createOutput(java.lang.String filename)
+
+
+ Similar to createInput() (formerly openStream), this creates a Java
+ OutputStream for a given filename or path.
delay(int napTime)
+
+
+ The delay() function causes the program to halt for a specified time.
+
+
+
+ void
+
destroy()
+
+
+ Called by the browser or applet viewer to inform this applet
+ that it is being reclaimed and that it should destroy
+ any resources that it has allocated.
+
+
+
+ void
+
die(java.lang.String what)
+
+
+ Function for an applet/application to kill itself and
+ display an error.
+
+
+
+ void
+
die(java.lang.String what,
+ java.lang.Exception e)
+
+
+ Same as above but with an exception.
join(java.lang.String[] str,
+ char separator)
+
+
+ Join an array of Strings together as a single String,
+ separated by the whatever's passed in for the separator.
+
+
+
+static java.lang.String
+
join(java.lang.String[] str,
+ java.lang.String separator)
+
+
+ Join an array of Strings together as a single String,
+ separated by the whatever's passed in for the separator.
+
+
+
+ void
+
keyPressed()
+
+
+ Called each time a single key on the keyboard is pressed.
+
+
+
+ void
+
keyPressed(java.awt.event.KeyEvent e)
+
+
+ Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
+ 'keyCode', and 'keyEvent' variables to no longer work;
+ key events will no longer be queued until the end of draw();
+ and the keyPressed(), keyReleased() and keyTyped() methods
+ will no longer be called.
loadImage(java.lang.String filename,
+ java.lang.String extension)
+
+
+ Identical to loadImage, but allows you to specify the type of
+ image by its extension.
+
+
+
+ void
+
loadPixels()
+
+
+ Override the g.pixels[] function to set the pixels[] array
+ that's part of the PApplet object.
main(java.lang.String[] args)
+
+
+ main() method for running this class from the command line.
+
+
+
+static float
+
map(float value,
+ float istart,
+ float istop,
+ float ostart,
+ float ostop)
+
+
+ Convenience function to map a variable from one coordinate space
+ to another.
match(java.lang.String what,
+ java.lang.String regexp)
+
+
+ Match a string with a regular expression, and returns the match as an
+ array.
+
+
+
+static java.lang.String[][]
+
matchAll(java.lang.String what,
+ java.lang.String regexp)
+
+
+ Identical to match(), except that it returns an array of all matches in
+ the specified String, rather than just the first.
+
+
+
+static float
+
max(float[] list)
+
+
+ Find the maximum value in an array.
mousePressed()
+
+
+ Mouse has been pressed, and should be considered "down"
+ until mouseReleased() is called.
+
+
+
+ void
+
mousePressed(java.awt.event.MouseEvent e)
+
+
+ If you override this or any function that takes a "MouseEvent e"
+ without calling its super.mouseXxxx() then mouseX, mouseY,
+ mousePressed, and mouseEvent will no longer be set.
+
+
+
+ void
+
mouseReleased()
+
+
+ Mouse button has been released.
nfp(int num,
+ int digits)
+
+
+ number format positive (or plus)
+ Formats a number, always placing a - or + sign
+ in the front when it's negative or positive.
+
+
+
+static java.lang.String[]
+
nfs(float[] num,
+ int left,
+ int right)
+
+
+ Number formatter that takes into account whether the number
+ has a sign (positive, negative, etc) in front of it.
nfs(int num,
+ int digits)
+
+
+ number format signed (or space)
+ Formats a number but leaves a blank space in the front
+ when it's positive so that it can be properly aligned with
+ numbers that have a negative sign in front of them.
+
+
+
+ void
+
noCursor()
+
+
+ Hide the cursor by creating a transparent image
+ and using it as a custom cursor.
parseInt(java.lang.String what)
+
+
+ Parse a String into an int value.
+
+
+
+static int[]
+
parseInt(java.lang.String[] what)
+
+
+ Make an array of int elements from an array of String objects.
+
+
+
+static int[]
+
parseInt(java.lang.String[] what,
+ int missing)
+
+
+ Make an array of int elements from an array of String objects.
+
+
+
+static int
+
parseInt(java.lang.String what,
+ int otherwise)
+
+
+ Parse a String to an int, and provide an alternate value that
+ should be used when the number is invalid.
save(java.lang.String filename)
+
+
+ Intercepts any relative paths to make them absolute (relative
+ to the sketch folder) before passing to save() in PImage.
+
+
+
+static void
+
saveBytes(java.io.File file,
+ byte[] buffer)
+
+
+ Saves bytes to a specific File location specified by the user.
+
+
+
+static void
+
saveBytes(java.io.OutputStream output,
+ byte[] buffer)
+
+
+ Spews a buffer of bytes to an OutputStream.
+
+
+
+ void
+
saveBytes(java.lang.String filename,
+ byte[] buffer)
+
+
+ Saves bytes to a file to inside the sketch folder.
+
+
+
+ java.io.File
+
saveFile(java.lang.String where)
+
+
+ Identical to savePath(), but returns a File object.
+
+
+
+ void
+
saveFrame()
+
+
+ Grab an image of what's currently in the drawing area and save it
+ as a .tif or .tga file.
+
+
+
+ void
+
saveFrame(java.lang.String what)
+
+
+ Save the current frame as a .tif or .tga image.
+
+
+
+ java.lang.String
+
savePath(java.lang.String where)
+
+
+ Returns a path inside the applet folder to save to.
saveStream(java.io.File targetFile,
+ java.lang.String sourceLocation)
+
+
+ Identical to the other saveStream(), but writes to a File
+ object, for greater control over the file location.
+
+
+
+ void
+
saveStream(java.lang.String targetFilename,
+ java.lang.String sourceLocation)
+
+
+ Save the contents of a stream to a file in the sketch folder.
size(int iwidth,
+ int iheight,
+ java.lang.String irenderer,
+ java.lang.String ipath)
+
+
+ Creates a new PGraphics object and sets it to the specified size.
split(java.lang.String what,
+ char delim)
+
+
+ Split a string into pieces along a specific character.
+
+
+
+static java.lang.String[]
+
split(java.lang.String what,
+ java.lang.String delim)
+
+
+ Split a String on a specific delimiter.
+
+
+
+static java.lang.String[]
+
splitTokens(java.lang.String what)
+
+
+ Split the provided String at wherever whitespace occurs.
+
+
+
+static java.lang.String[]
+
splitTokens(java.lang.String what,
+ java.lang.String delim)
+
+
+ Splits a string into pieces, using any of the chars in the
+ String 'delim' as separator characters.
+public static final java.lang.String javaVersionName
+
+
Full name of the Java version (i.e. 1.5.0_11).
+ Prior to 0125, this was only the first three digits.
+
+
+
+
+
+
+
+javaVersion
+
+public static final float javaVersion
+
+
Version of Java that's in use, whether 1.1 or 1.3 or whatever,
+ stored as a float.
+
+ Note that because this is stored as a float, the values may
+ not be exactly 1.3 or 1.4. Instead, make sure you're
+ comparing against 1.3f or 1.4f, which will have the same amount
+ of error (i.e. 1.40000001). This could just be a double, but
+ since Processing only uses floats, it's safer for this to be a float
+ because there's no good way to specify a double with the preproc.
+
+
+
+
+
+
+
+platform
+
+public static int platform
+
+
Current platform in use, one of the
+ PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
+
+
+
+
+
+
+
+MENU_SHORTCUT
+
+public static final int MENU_SHORTCUT
+
+
Modifier flags for the shortcut key used to trigger menus.
+ (Cmd on Mac OS X, Ctrl on Linux and Windows)
+
The PGraphics renderer associated with this PApplet
+
+
+
+
+
+
+
+frame
+
+public java.awt.Frame frame
+
+
The frame containing this applet (if any)
+
+
+
+
+
+
+
+screen
+
+public java.awt.Dimension screen
+
+
The screen size when the applet was started.
+
+ Access this via screen.width and screen.height. To make an applet
+ run at full screen, use size(screen.width, screen.height).
+
+ If you have multiple displays, this will be the size of the main
+ display. Running full screen across multiple displays isn't
+ particularly supported, and requires more monkeying with the values.
+ This probably can't/won't be fixed until/unless I get a dual head
+ system.
+
+ Note that this won't update if you change the resolution
+ of your screen once the the applet is running.
+
+ This variable is not static, because future releases need to be better
+ at handling multiple displays.
+
Minimum dimensions for the window holding an applet.
+ This varies between platforms, Mac OS X 10.3 can do any height
+ but requires at least 128 pixels width. Windows XP has another
+ set of limitations. And for all I know, Linux probably lets you
+ make windows with negative sizes.
+
true if no size() command has been executed. This is used to wait until
+ a size has been set before placing in the window and showing it.
+
+
+
+
+
+
+
+pixels
+
+public int[] pixels
+
+
Pixel buffer from this applet's PGraphics.
+
+ When used with OpenGL or Java2D, this value will
+ be null until loadPixels() has been called.
+
+
+
+
+
+
+
+width
+
+public int width
+
+
width of this applet's associated PGraphics
+
+
+
+
+
+
+
+height
+
+public int height
+
+
height of this applet's associated PGraphics
+
+
+
+
+
+
+
+mouseX
+
+public int mouseX
+
+
current x position of the mouse
+
+
+
+
+
+
+
+mouseY
+
+public int mouseY
+
+
current y position of the mouse
+
+
+
+
+
+
+
+pmouseX
+
+public int pmouseX
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+
+pmouseY
+
+public int pmouseY
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+
+firstMouse
+
+public boolean firstMouse
+
+
Used to set pmouseX/Y to mouseX/Y the first time mouseX/Y are used,
+ otherwise pmouseX/Y are always zero, causing a nasty jump.
+
+ Just using (frameCount == 0) won't work since mouseXxxxx()
+ may not be called until a couple frames into things.
+
+
+
+
+
+
+
+mouseButton
+
+public int mouseButton
+
+
Last mouse button pressed, one of LEFT, CENTER, or RIGHT.
+
+ If running on Mac OS, a ctrl-click will be interpreted as
+ the righthand mouse button (unlike Java, which reports it as
+ the left mouse).
+
+
+
+
+
+
+
+mousePressed
+
+public boolean mousePressed
+
+
+
+
+
+
+
+mouseEvent
+
+public java.awt.event.MouseEvent mouseEvent
+
+
+
+
+
+
+
+key
+
+public char key
+
+
Last key pressed.
+
+ If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT,
+ this will be set to CODED (0xffff or 65535).
+
+
+
+
+
+
+
+keyCode
+
+public int keyCode
+
+
When "key" is set to CODED, this will contain a Java key code.
+
+ For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT.
+ Also available are ALT, CONTROL and SHIFT. A full set of constants
+ can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables.
+
+
+
+
+
+
+
+keyPressed
+
+public boolean keyPressed
+
+
true if the mouse is currently pressed.
+
+
+
+
+
+
+
+keyEvent
+
+public java.awt.event.KeyEvent keyEvent
+
+
the last KeyEvent object passed into a mouse function.
+
+
+
+
+
+
+
+focused
+
+public boolean focused
+
+
Gets set to true/false as the applet gains/loses focus.
+
+
+
+
+
+
+
+online
+
+public boolean online
+
+
true if the applet is online.
+
+ This can be used to test how the applet should behave
+ since online situations are different (no file writing, etc).
+
+
+
+
+
+
+
+frameRate
+
+public float frameRate
+
+
The current value of frames per second.
+
+ The initial value will be 10 fps, and will be updated with each
+ frame thereafter. The value is not instantaneous (since that
+ wouldn't be very useful since it would jump around so much),
+ but is instead averaged (integrated) over several frames.
+ As such, this value won't be valid until after 5-10 frames.
+
+
+
+
+
+
+
+frameCount
+
+public int frameCount
+
+
How many frames have been displayed since the applet started.
+
+ This value is read-only do not attempt to set it,
+ otherwise bad things will happen.
+
+ Inside setup(), frameCount is 0.
+ For the first iteration of draw(), frameCount will equal 1.
+
+
+
+
+
+
+
+finished
+
+public boolean finished
+
+
true if this applet has had it.
+
+
+
+
+
+
+
+ARGS_EDITOR_LOCATION
+
+public static final java.lang.String ARGS_EDITOR_LOCATION
+
+
Position of the upper-lefthand corner of the editor window
+ that launched this applet.
+
+public static final java.lang.String ARGS_EXTERNAL
+
+
Location for where to position the applet window on screen.
+
+ This is used by the editor to when saving the previous applet
+ location, or could be used by other classes to launch at a
+ specific position on-screen.
+
By trial and error, four image loading threads seem to work best when
+ loading images from online. This is consistent with the number of open
+ connections that web browsers will maintain. The variable is made public
+ (however no accessor has been added since it's esoteric) if you really
+ want to have control over the value used. For instance, when loading local
+ files, it might be better to only have a single thread (or two) loading
+ images so that you're disk isn't simply jumping around.
+
+
+
+
+
+
+
+selectedFile
+
+public java.io.File selectedFile
+
+
+
+
+
+
+
+ICON_IMAGE
+
+public static final byte[] ICON_IMAGE
+
+
GIF image of the Processing logo.
+
+
+
+
+
+
+
+
+
+
+
+Constructor Detail
+
+
+
+
+PApplet
+
+public PApplet()
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+init
+
+public void init()
+
+
+
Overrides:
init in class java.applet.Applet
+
+
+
+
+
+
+
+
+getSketchWidth
+
+public int getSketchWidth()
+
+
+
+
+
+
+
+
+
+
+
+getSketchHeight
+
+public int getSketchHeight()
+
+
+
+
+
+
+
+
+
+
+
+getSketchRenderer
+
+public java.lang.String getSketchRenderer()
+
+
+
+
+
+
+
+
+
+
+
+start
+
+public void start()
+
+
Called by the browser or applet viewer to inform this applet that it
+ should start its execution. It is called after the init method and
+ each time the applet is revisited in a Web page.
+
+ Called explicitly via the first call to PApplet.paint(), because
+ PAppletGL needs to have a usable screen before getting things rolling.
+
+
+
Overrides:
start in class java.applet.Applet
+
+
+
+
+
+
+
+
+stop
+
+public void stop()
+
+
Called by the browser or applet viewer to inform
+ this applet that it should stop its execution.
+
+ Unfortunately, there are no guarantees from the Java spec
+ when or if stop() will be called (i.e. on browser quit,
+ or when moving between web pages), and it's not always called.
+
+
+
Overrides:
stop in class java.applet.Applet
+
+
+
+
+
+
+
+
+destroy
+
+public void destroy()
+
+
Called by the browser or applet viewer to inform this applet
+ that it is being reclaimed and that it should destroy
+ any resources that it has allocated.
+
+ This also attempts to call PApplet.stop(), in case there
+ was an inadvertent override of the stop() function by a user.
+
+ destroy() supposedly gets called as the applet viewer
+ is shutting down the applet. stop() is called
+ first, and then destroy() to really get rid of things.
+ no guarantees on when they're run (on browser quit, or
+ when moving between pages), though.
+
Starts up and creates a two-dimensional drawing surface,
+ or resizes the current drawing surface.
+
+ This should be the first thing called inside of setup().
+
+ If using Java 1.3 or later, this will default to using
+ PGraphics2, the Java2D-based renderer. If using Java 1.1,
+ or if PGraphics2 is not available, then PGraphics will be used.
+ To set your own renderer, use the other version of the size()
+ method that takes a renderer as its last parameter.
+
+ If called once a renderer has already been set, this will
+ use the previous renderer and simply resize it.
+
+
+
+
+
+
+
+
+
+
+
+size
+
+public void size(int iwidth,
+ int iheight,
+ java.lang.String irenderer)
Creates a new PGraphics object and sets it to the specified size.
+
+ Note that you cannot change the renderer once outside of setup().
+ In most cases, you can call size() to give it a new size,
+ but you need to always ask for the same renderer, otherwise
+ you're gonna run into trouble.
+
+ The size() method should *only* be called from inside the setup() or
+ draw() methods, so that it is properly run on the main animation thread.
+ To change the size of a PApplet externally, use setSize(), which will
+ update the component size, and queue a resize of the renderer as well.
+
+
+
+
+
+
+
+
+
+
+
+createGraphics
+
+public PGraphicscreateGraphics(int iwidth,
+ int iheight,
+ java.lang.String irenderer)
+
+
Create an offscreen PGraphics object for drawing. This can be used
+ for bitmap or vector images drawing or rendering.
+
+
Do not use "new PGraphicsXxxx()", use this method. This method
+ ensures that internal variables are set up properly that tie the
+ new graphics context back to its parent PApplet.
+
The basic way to create bitmap images is to use the saveFrame()
+ function.
+
If you want to create a really large scene and write that,
+ first make sure that you've allocated a lot of memory in the Preferences.
+
If you want to create images that are larger than the screen,
+ you should create your own PGraphics object, draw to that, and use
+ save().
+ For now, it's best to use P3D in this scenario.
+ P2D is currently disabled, and the JAVA2D default will give mixed
+ results. An example of using P3D:
+
+
+ PGraphics big;
+
+ void setup() {
+ big = createGraphics(3000, 3000, P3D);
+
+ big.beginDraw();
+ big.background(128);
+ big.line(20, 1800, 1800, 900);
+ // etc..
+ big.endDraw();
+
+ // make sure the file is written to the sketch folder
+ big.save("big.tif");
+ }
+
+
+
It's important to always wrap drawing to createGraphics() with
+ beginDraw() and endDraw() (beginFrame() and endFrame() prior to
+ revision 0115). The reason is that the renderer needs to know when
+ drawing has stopped, so that it can update itself internally.
+ This also handles calling the defaults() method, for people familiar
+ with that.
+
It's not possible to use createGraphics() with the OPENGL renderer,
+ because it doesn't allow offscreen use.
+
With Processing 0115 and later, it's possible to write images in
+ formats other than the default .tga and .tiff. The exact formats and
+ background information can be found in the developer's reference for
+ PImage.save().
+
Create an offscreen graphics surface for drawing, in this case
+ for a renderer that writes to a file (such as PDF or DXF).
+
+
+
+
+
+
Parameters:
ipath - can be an absolute or relative path
+
+
+
+
+
+createImage
+
+public PImagecreateImage(int wide,
+ int high,
+ int format)
+
+
Preferred method of creating new PImage objects, ensures that a
+ reference to the parent PApplet is included, which makes save() work
+ without needing an absolute path.
+
If you override this or any function that takes a "MouseEvent e"
+ without calling its super.mouseXxxx() then mouseX, mouseY,
+ mousePressed, and mouseEvent will no longer be set.
+
+
+
Specified by:
mousePressed in interface java.awt.event.MouseListener
mouseMoved in interface java.awt.event.MouseMotionListener
+
+
+
+
+
+
+
+
+mousePressed
+
+public void mousePressed()
+
+
Mouse has been pressed, and should be considered "down"
+ until mouseReleased() is called. If you must, use
+ int button = mouseEvent.getButton();
+ to figure out which button was clicked. It will be one of:
+ MouseEvent.BUTTON1, MouseEvent.BUTTON2, MouseEvent.BUTTON3
+ Note, however, that this is completely inconsistent across
+ platforms.
+
+
+
+
+
+
+
+
+
+
+
+mouseReleased
+
+public void mouseReleased()
+
+
Mouse button has been released.
+
+
+
+
+
+
+
+
+
+
+
+mouseClicked
+
+public void mouseClicked()
+
+
When the mouse is clicked, mousePressed() will be called,
+ then mouseReleased(), then mouseClicked(). Note that
+ mousePressed is already false inside of mouseClicked().
+
+
+
+
+
+
+
+
+
+
+
+mouseDragged
+
+public void mouseDragged()
+
+
Mouse button is pressed and the mouse has been dragged.
+
+
+
+
+
+
+
+
+
+
+
+mouseMoved
+
+public void mouseMoved()
+
+
Mouse button is not pressed but the mouse has changed locations.
+
Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
+ 'keyCode', and 'keyEvent' variables to no longer work;
+ key events will no longer be queued until the end of draw();
+ and the keyPressed(), keyReleased() and keyTyped() methods
+ will no longer be called.
+
+
+
Specified by:
keyPressed in interface java.awt.event.KeyListener
keyReleased in interface java.awt.event.KeyListener
+
+
+
+
+
+
+
+
+keyTyped
+
+public void keyTyped(java.awt.event.KeyEvent e)
+
+
+
Specified by:
keyTyped in interface java.awt.event.KeyListener
+
+
+
+
+
+
+
+
+keyPressed
+
+public void keyPressed()
+
+
Called each time a single key on the keyboard is pressed.
+ Because of how operating systems handle key repeats, holding
+ down a key will cause multiple calls to keyPressed(), because
+ the OS repeat takes over.
+
+ Examples for key handling:
+ (Tested on Windows XP, please notify if different on other
+ platforms, I have a feeling Mac OS and Linux may do otherwise)
+
+ 1. Pressing 'a' on the keyboard:
+ keyPressed with key == 'a' and keyCode == 'A'
+ keyTyped with key == 'a' and keyCode == 0
+ keyReleased with key == 'a' and keyCode == 'A'
+
+ 2. Pressing 'A' on the keyboard:
+ keyPressed with key == 'A' and keyCode == 'A'
+ keyTyped with key == 'A' and keyCode == 0
+ keyReleased with key == 'A' and keyCode == 'A'
+
+ 3. Pressing 'shift', then 'a' on the keyboard (caps lock is off):
+ keyPressed with key == CODED and keyCode == SHIFT
+ keyPressed with key == 'A' and keyCode == 'A'
+ keyTyped with key == 'A' and keyCode == 0
+ keyReleased with key == 'A' and keyCode == 'A'
+ keyReleased with key == CODED and keyCode == SHIFT
+
+ 4. Holding down the 'a' key.
+ The following will happen several times,
+ depending on your machine's "key repeat rate" settings:
+ keyPressed with key == 'a' and keyCode == 'A'
+ keyTyped with key == 'a' and keyCode == 0
+ When you finally let go, you'll get:
+ keyReleased with key == 'a' and keyCode == 'A'
+
+ 5. Pressing and releasing the 'shift' key
+ keyPressed with key == CODED and keyCode == SHIFT
+ keyReleased with key == CODED and keyCode == SHIFT
+ (note there is no keyTyped)
+
+ 6. Pressing the tab key in an applet with Java 1.4 will
+ normally do nothing, but PApplet dynamically shuts
+ this behavior off if Java 1.4 is in use (tested 1.4.2_05 Windows).
+ Java 1.1 (Microsoft VM) passes the TAB key through normally.
+ Not tested on other platforms or for 1.3.
+
+
+
+
+
+
+
+
+
+
+
+
+keyReleased
+
+public void keyReleased()
+
+
See keyPressed().
+
+
+
+
+
+
+
+
+
+
+
+keyTyped
+
+public void keyTyped()
+
+
Only called for "regular" keys like letters,
+ see keyPressed() for full documentation.
+
focusLost in interface java.awt.event.FocusListener
+
+
+
+
+
+
+
+
+millis
+
+public int millis()
+
+
Get the number of milliseconds since the applet started.
+
+ This is a function, rather than a variable, because it may
+ change multiple times per frame.
+
+
+
+
+
+
+
+
+
+
+
+second
+
+public static int second()
+
+
Seconds position of the current time.
+
+
+
+
+
+
+
+
+
+
+
+minute
+
+public static int minute()
+
+
Minutes position of the current time.
+
+
+
+
+
+
+
+
+
+
+
+hour
+
+public static int hour()
+
+
Hour position of the current time in international format (0-23).
+
+ To convert this value to American time:
+
int yankeeHour = (hour() % 12);
+ if (yankeeHour == 0) yankeeHour = 12;
+
+
+
+
+
+
+
+
+
+
+
+day
+
+public static int day()
+
+
Get the current day of the month (1 through 31).
+
+ If you're looking for the day of the week (M-F or whatever)
+ or day of the year (1..365) then use java's Calendar.get()
+
+
+
+
+
+
+
+
+
+
+
+month
+
+public static int month()
+
+
Get the current month in range 1 through 12.
+
+
+
+
+
+
+
+
+
+
+
+year
+
+public static int year()
+
+
Get the current year.
+
+
+
+
+
+
+
+
+
+
+
+delay
+
+public void delay(int napTime)
+
+
The delay() function causes the program to halt for a specified time.
+ Delay times are specified in thousandths of a second. For example,
+ running delay(3000) will stop the program for three seconds and
+ delay(500) will stop the program for a half-second. Remember: the
+ display window is updated only at the end of draw(), so putting more
+ than one delay() inside draw() will simply add them together and the new
+ frame will be drawn when the total delay is over.
+
+ I'm not sure if this is even helpful anymore, as the screen isn't
+ updated before or after the delay, meaning which means it just
+ makes the app lock up temporarily.
+
+
+
+
+
+
+
+
+
+
+
+frameRate
+
+public void frameRate(float newRateTarget)
+
+
Set a target frameRate. This will cause delay() to be called
+ after each frame so that the sketch synchronizes to a particular speed.
+ Note that this only sets the maximum frame rate, it cannot be used to
+ make a slow sketch go faster. Sketches have no default frame rate
+ setting, and will attempt to use maximum processor power to achieve
+ maximum speed.
+
Get a param from the web page, or (eventually)
+ from a properties file.
+
+
+
+
+
+
+
+
+
+
+
+status
+
+public void status(java.lang.String what)
+
+
Show status in the status bar of a web browser, or in the
+ System.out console. Eventually this might show status in the
+ p5 environment itself, rather than relying on the console.
+
Launch a process using a platforms shell. This version uses an array
+ to make it easier to deal with spaces in the individual elements.
+ (This avoids the situation of trying to put single or double quotes
+ around different bits).
+
Same as above but with an exception. Also needs work.
+
+
+
+
+
+
+
+
+
+
+
+exit
+
+public void exit()
+
+
Call to safely exit the sketch when finished. For instance,
+ to render a single frame, save it, and quit.
+
+
+
+
+
+
+
+
+
+
+
+save
+
+public void save(java.lang.String filename)
+
+
Intercepts any relative paths to make them absolute (relative
+ to the sketch folder) before passing to save() in PImage.
+ (Changed in 0100)
+
+
+
+
+
+
+
+
+
+
+
+saveFrame
+
+public void saveFrame()
+
+
Grab an image of what's currently in the drawing area and save it
+ as a .tif or .tga file.
+
+ Best used just before endDraw() at the end of your draw().
+ This can only create .tif or .tga images, so if neither extension
+ is specified it defaults to writing a tiff and adds a .tif suffix.
+
+
+
+
+
+
+
+
+
+
+
+saveFrame
+
+public void saveFrame(java.lang.String what)
+
+
Save the current frame as a .tif or .tga image.
+
+ The String passed in can contain a series of # signs
+ that will be replaced with the screengrab number.
+
+ i.e. saveFrame("blah-####.tif");
+ // saves a numbered tiff image, replacing the
+ // #### signs with zeros and the frame number
Replace the cursor with the specified PImage. The x- and y-
+ coordinate of the center will be the center of the image.
+
+
+
+
+
+
+
+
+
+
+
+cursor
+
+public void cursor(PImage image,
+ int hotspotX,
+ int hotspotY)
+
+
Set a custom cursor to an image with a specific hotspot.
+ Only works with JDK 1.2 and later.
+ Currently seems to be broken on Java 1.4 for Mac OS X
+
+ Based on code contributed by Amit Pitaru, plus additional
+ code to handle Java versions via reflection by Jonathan Feinberg.
+ Reflection removed for release 0128 and later.
+
+
+
+
+
+
+
+
+
+
+
+cursor
+
+public void cursor()
+
+
Show the cursor after noCursor() was called.
+ Notice that the program remembers the last set cursor type
+
+
+
+
+
+
+
+
+
+
+
+noCursor
+
+public void noCursor()
+
+
Hide the cursor by creating a transparent image
+ and using it as a custom cursor.
+
Normalize a value to exist between 0 and 1 (inclusive).
+ Mathematically the opposite of lerp(), figures out what proportion
+ a particular value is relative to start and stop coordinates.
+
Convenience function to map a variable from one coordinate space
+ to another. Equivalent to unlerp() followed by lerp().
+
+
+
+
+
+
+
+
+
+
+
+random
+
+public final float random(float howbig)
+
+
Return a random number in the range [0, howbig).
+
+ The number returned will range from zero up to
+ (but not including) 'howbig'.
+
+
+
+
+
+
+
+
+
+
+
+random
+
+public final float random(float howsmall,
+ float howbig)
+
+
Return a random number in the range [howsmall, howbig).
+
+ The number returned will range from 'howsmall' up to
+ (but not including 'howbig'.
+
+ If howsmall is >= howbig, howsmall will be returned,
+ meaning that random(5, 5) will return 5 (useful)
+ and random(7, 4) will return 7 (not useful.. better idea?)
+
+
+
+
+
+
+
+
+
+
+
+randomSeed
+
+public final void randomSeed(long what)
+
+
+
+
+
+
+
+
+
+
+
+noise
+
+public float noise(float x)
+
+
Computes the Perlin noise function value at point x.
+
+
+
+
+
+
+
+
+
+
+
+noise
+
+public float noise(float x,
+ float y)
+
+
Computes the Perlin noise function value at the point x, y.
+
+
+
+
+
+
+
+
+
+
+
+noise
+
+public float noise(float x,
+ float y,
+ float z)
+
+
Computes the Perlin noise function value at x, y, z.
+
Load an image from the data folder or a local directory.
+ Supports .gif (including transparency), .tga, and .jpg images.
+ In Java 1.3 or later, .png images are
+
+ also supported.
+
+ Generally, loadImage() should only be used during setup, because
+ re-loading images inside draw() is likely to cause a significant
+ delay while memory is allocated and the thread blocks while waiting
+ for the image to load because loading is not asynchronous.
+
+ To load several images asynchronously, see more information in the
+ FAQ about writing your own threaded image loading method.
+
+ As of 0096, returns null if no image of that name is found,
+ rather than an error.
+
+ Release 0115 also provides support for reading TIFF and RLE-encoded
+ Targa (.tga) files written by Processing via save() and saveFrame().
+ Other TIFF and Targa files will probably not load, use a different
+ format (gif, jpg and png are safest bets) when creating images with
+ another application to use with Processing.
+
+ Also in release 0115, more image formats (BMP and others) can
+ be read when using Java 1.4 and later. Because many people still
+ use Java 1.1 and 1.3, these formats are not recommended for
+ work that will be posted on the web. To get a list of possible
+ image formats for use with Java 1.4 and later, use the following:
+ println(javax.imageio.ImageIO.getReaderFormatNames())
+
+ Images are loaded via a byte array that is passed to
+ Toolkit.createImage(). Unfortunately, we cannot use Applet.getImage()
+ because it takes a URL argument, which would be a pain in the a--
+ to make work consistently for online and local sketches.
+ Sometimes this causes problems, resulting in issues like
+ Bug 279
+ and
+ Bug 305.
+ In release 0115, everything was instead run through javax.imageio,
+ but that turned out to be very slow, see
+ Bug 392.
+ As a result, starting with 0116, the following happens:
+
+
TGA and TIFF images are loaded using the internal load methods.
+
JPG, GIF, and PNG images are loaded via loadBytes().
+
If the image still isn't loaded, it's passed to javax.imageio.
+
+ For releases 0116 and later, if you have problems such as those seen
+ in Bugs 279 and 305, use Applet.getImage() instead. You'll be stuck
+ with the limitations of getImage() (the headache of dealing with
+ online/offline use). Set up your own MediaTracker, and pass the resulting
+ java.awt.Image to the PImage constructor that takes an AWT image.
+
Create a .vlw font on the fly from either a font name that's
+ installed on the system, or from a .ttf or .otf that's inside
+ the data folder of this sketch.
+
+ Only works with Java 1.3 or later. Many .otf fonts don't seem
+ to be supported by Java, perhaps because they're CFF based?
+
+ Font names are inconsistent across platforms and Java versions.
+ On Mac OS X, Java 1.3 uses the font menu name of the font,
+ whereas Java 1.4 uses the PostScript name of the font. Java 1.4
+ on OS X will also accept the font menu name as well. On Windows,
+ it appears that only the menu names are used, no matter what
+ Java version is in use. Naming system unknown/untested for 1.5.
+
+ Use 'null' for the charset if you want to use any of the 65,536
+ unicode characters that exist in the font. Note that this can
+ produce an enormous file or may cause an OutOfMemoryError.
+
+
+
+
+
+
+
+
+
+
+
+selectInput
+
+public java.lang.String selectInput()
+
+
Open a platform-specific file chooser dialog to select a file for input.
+
+
+
+
+
+
+
Returns:
full path to the selected file, or null if no selection.
+ This method is useful if you want to use the facilities provided
+ by PApplet to easily open things from the data folder or from a URL,
+ but want an InputStream object so that you can use other Java
+ methods to take more control of how the stream is read.
+
+ If the requested item doesn't exist, null is returned.
+ (Prior to 0096, die() would be called, killing the applet)
+
+ For 0096+, the "data" folder is exported intact with subfolders,
+ and openStream() properly handles subdirectories from the data folder
+
+ If not online, this will also check to see if the user is asking
+ for a file whose name isn't properly capitalized. This helps prevent
+ issues when a sketch is exported to the web, where case sensitivity
+ matters, as opposed to Windows and the Mac OS default where
+ case sensitivity is preserved but ignored.
+
+ It is strongly recommended that libraries use this method to open
+ data files, so that the loading sequence is handled in the same way
+ as functions like loadBytes(), loadImage(), etc.
+
+ The filename passed in can be:
+
+
A URL, for instance openStream("http://processing.org/");
+
A file in the sketch's data folder
+
Another file to be opened locally (when running as an application)
+
Load data from a file and shove it into a String array.
+
+ Exceptions are handled internally, when an error, occurs, an
+ exception is printed to the console and 'null' is returned,
+ but the program continues running. This is a tradeoff between
+ 1) showing the user that there was a problem but 2) not requiring
+ that all i/o code is contained in try/catch blocks, for the sake
+ of new users (or people who are just trying to get things done
+ in a "scripting" fashion. If you want to handle exceptions,
+ use Java methods for I/O.
+
Similar to createInput() (formerly openStream), this creates a Java
+ OutputStream for a given filename or path. The file will be created in
+ the sketch folder, or in the same folder as an exported application.
+
+ If the path does not exist, intermediate folders will be created. If an
+ exception occurs, it will be printed to the console, and null will be
+ returned.
+
+ Future releases may also add support for handling HTTP POST via this
+ method (for better symmetry with createInput), however that's maybe a
+ little too clever (and then we'd have to add the same features to the
+ other file functions like createWriter). Who you callin' bloated?
+
Save the contents of a stream to a file in the sketch folder.
+ This is basically saveBytes(blah, loadBytes()), but done
+ more efficiently (and with less confusing syntax).
+
Identical to the other saveStream(), but writes to a File
+ object, for greater control over the file location.
+ Note that unlike other api methods, this will not automatically
+ compress or uncompress gzip files.
+
Saves bytes to a file to inside the sketch folder.
+ The filename can be a relative path, i.e. "poo/bytefun.txt"
+ would save to a file named "bytefun.txt" to a subfolder
+ called 'poo' inside the sketch folder. If the in-between
+ subfolders don't exist, they'll be created.
+
Prepend the sketch folder path to the filename (or path) that is
+ passed in. External libraries should use this function to save to
+ the sketch folder.
+
+ Note that when running as an applet inside a web browser,
+ the sketchPath will be set to null, because security restrictions
+ prevent applets from accessing that information.
+
+ This will also cause an error if the sketch is not inited properly,
+ meaning that init() was never called on the PApplet when hosted
+ my some other main() or by other code. For proper use of init(),
+ see the examples in the main description text for PApplet.
+
Returns a path inside the applet folder to save to. Like sketchPath(),
+ but creates any in-between folders so that things save properly.
+
+ All saveXxxx() functions use the path to the sketch folder, rather than
+ its data folder. Once exported, the data folder will be found inside the
+ jar file of the exported application or applet. In this case, it's not
+ possible to save data into the jar file, because it will often be running
+ from a server, or marked in-use if running from a local file system.
+ With this in mind, saving to the data path doesn't make sense anyway.
+ If you know you're running locally, and want to save to the data folder,
+ use saveXxxx("data/blah.dat").
+
Return a full path to an item in the data folder.
+
+ In this method, the data path is defined not as the applet's actual
+ data path, but a folder titled "data" in the sketch's working
+ directory. When running inside the PDE, this will be the sketch's
+ "data" folder. However, when exported (as application or applet),
+ sketch's data folder is exported as part of the applications jar file,
+ and it's not possible to read/write from the jar file in a generic way.
+ If you need to read data from the jar file, you should use createInput().
+
Takes a path and creates any in-between folders if they don't
+ already exist. Useful when trying to save to a subfolder that
+ may not actually exist.
+
+
+
+
+
+
+
+
+
+
+
+createPath
+
+public static void createPath(java.io.File file)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static byte[] sort(byte[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static byte[] sort(byte[] what,
+ int count)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static char[] sort(char[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static char[] sort(char[] what,
+ int count)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static int[] sort(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static int[] sort(int[] what,
+ int count)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static float[] sort(float[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static float[] sort(float[] what,
+ int count)
Remove whitespace characters from the beginning and ending
+ of a String. Works like String.trim() but includes the
+ unicode nbsp character as well.
+
Split the provided String at wherever whitespace occurs.
+ Multiple whitespace (extra spaces or tabs or whatever)
+ between items will count as a single break.
+
+ The whitespace characters are "\t\n\r\f", which are the defaults
+ for java.util.StringTokenizer, plus the unicode non-breaking space
+ character, which is found commonly on files created by or used
+ in conjunction with Mac OS X (character 160, or 0x00A0 in hex).
+
Splits a string into pieces, using any of the chars in the
+ String 'delim' as separator characters. For instance,
+ in addition to white space, you might want to treat commas
+ as a separator. The delimeter characters won't appear in
+ the returned String array.
+
Split a string into pieces along a specific character.
+ Most commonly used to break up a String along a space or a tab
+ character.
+
+ This operates differently than the others, where the
+ single delimeter is the only breaking point, and consecutive
+ delimeters will produce an empty string (""). This way,
+ one can split on tab characters, but maintain the column
+ alignments (of say an excel file) where there are empty columns.
+
Split a String on a specific delimiter. Unlike Java's String.split()
+ method, this does not parse the delimiter as a regexp because it's more
+ confusing than necessary, and String.split() is always available for
+ those who want regexp.
+
Match a string with a regular expression, and returns the match as an
+ array. The first index is the matching expression, and array elements
+ [1] and higher represent each of the groups (sequences found in parens).
+
+ This uses multiline matching (Pattern.MULTILINE) and dotall mode
+ (Pattern.DOTALL) by default, so that ^ and $ match the beginning and
+ end of any lines found in the source, and the . operator will also
+ pick up newline characters.
+
Identical to match(), except that it returns an array of all matches in
+ the specified String, rather than just the first.
+
+
+
+
+
+
+
+
+
+
+
+parseBoolean
+
+public static final boolean parseBoolean(int what)
+
+
Convert an integer to a boolean. Because of how Java handles upgrading
+ numbers, this will also cover byte and char (as they will upgrade to
+ an int without any sort of explicit cast).
+
The preprocessor will convert boolean(what) to parseBoolean(what).
+
+
+
+
+
+
+
Returns:
false if 0, true if any other number
+
+
+
+
+
+parseBoolean
+
+public static final boolean parseBoolean(java.lang.String what)
+
+
Convert the string "true" or "false" to a boolean.
+
+
+
+
+
+
+
Returns:
true if 'what' is "true" or "TRUE", false otherwise
+
+
+
+
+
+parseBoolean
+
+public static final boolean[] parseBoolean(byte[] what)
+
+
Convert a byte array to a boolean array. Each element will be
+ evaluated identical to the integer case, where a byte equal
+ to zero will return false, and any other value will return true.
+
+
+
+
+
+
+
Returns:
array of boolean elements
+
+
+
+
+
+parseBoolean
+
+public static final boolean[] parseBoolean(int[] what)
+
+
Convert an int array to a boolean array. An int equal
+ to zero will return false, and any other value will return true.
+
+
+
+
+
+
+
Returns:
array of boolean elements
+
+
+
+
+
+parseBoolean
+
+public static final boolean[] parseBoolean(java.lang.String[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(boolean what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(char what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(int what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(float what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(boolean[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(char[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(float[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char parseChar(byte what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char parseChar(int what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char[] parseChar(byte[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char[] parseChar(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(boolean what)
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(byte what)
+
+
Note that parseInt() will un-sign a signed byte value.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(char what)
+
+
Note that parseInt('5') is unlike String in the sense that it
+ won't return 5, but the ascii value. This is because ((int) someChar)
+ returns the ascii value, and parseInt() is just longhand for the cast.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(float what)
+
+
Same as floor(), or an (int) cast.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(java.lang.String what)
+
+
Parse a String into an int value. Returns 0 if the value is bad.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(java.lang.String what,
+ int otherwise)
+
+
Parse a String to an int, and provide an alternate value that
+ should be used when the number is invalid.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int[] parseInt(boolean[] what)
Make an array of int elements from an array of String objects.
+ If the String can't be parsed as a number, it will be set to zero.
+
+ String s[] = { "1", "300", "44" };
+ int numbers[] = parseInt(s);
+
+ numbers will contain { 1, 300, 44 }
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static int[] parseInt(java.lang.String[] what,
+ int missing)
+
+
Make an array of int elements from an array of String objects.
+ If the String can't be parsed as a number, its entry in the
+ array will be set to the value of the "missing" parameter.
+
+ String s[] = { "1", "300", "apple", "44" };
+ int numbers[] = parseInt(s, 9999);
+
+ numbers will contain { 1, 300, 9999, 44 }
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float parseFloat(int what)
+
+
Convert an int to a float value. Also handles bytes because of
+ Java's rules for upgrading values.
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float parseFloat(java.lang.String what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float parseFloat(java.lang.String what,
+ float otherwise)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final float[] parseByte(byte[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float[] parseFloat(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float[] parseFloat(java.lang.String[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float[] parseFloat(java.lang.String[] what,
+ float missing)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(boolean x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(byte x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(char x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(int x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(float x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(boolean[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(byte[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(char[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(int[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(float[] x)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String[] nf(int[] num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String nf(int num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String[] nfc(int[] num)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String nfc(int num)
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String nfs(int num,
+ int digits)
+
+
number format signed (or space)
+ Formats a number but leaves a blank space in the front
+ when it's positive so that it can be properly aligned with
+ numbers that have a negative sign in front of them.
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String[] nfs(int[] num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String nfp(int num,
+ int digits)
+
+
number format positive (or plus)
+ Formats a number, always placing a - or + sign
+ in the front when it's negative or positive.
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String[] nfp(int[] num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String[] nf(float[] num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String nf(float num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String[] nfc(float[] num,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String nfc(float num,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String[] nfs(float[] num,
+ int left,
+ int right)
+
+
Number formatter that takes into account whether the number
+ has a sign (positive, negative, etc) in front of it.
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String nfs(float num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String[] nfp(float[] num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String nfp(float num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(byte what)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(char what)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(int what)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(int what,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+unhex
+
+public static final int unhex(java.lang.String what)
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(byte what)
+
+
Returns a String that contains the binary value of a byte.
+ The returned value will always have 8 digits.
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(char what)
+
+
Returns a String that contains the binary value of a char.
+ The returned value will always have 16 digits because chars
+ are two bytes long.
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(int what)
+
+
Returns a String that contains the binary value of an int.
+ The length depends on the size of the number itself.
+ An int can be up to 32 binary digits, but that seems like
+ overkill for almost any situation, so this function just
+ auto-size. If you want a specific number of digits (like all 32)
+ use binary(int what, int digits) to specify how many digits.
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(int what,
+ int digits)
+
+
Returns a String that contains the binary value of an int.
+ The digits parameter determines how many digits will be used.
+
+
+
+
+
+
+
+
+
+
+
+unbinary
+
+public static final int unbinary(java.lang.String what)
+
+
Unpack a binary String into an int.
+ i.e. unbinary("00001000") would return 8.
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int gray)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float fgray)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int gray,
+ int alpha)
+
+
As of 0116 this also takes color(#FF8800, alpha)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float fgray,
+ float falpha)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int x,
+ int y,
+ int z)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float x,
+ float y,
+ float z)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int x,
+ int y,
+ int z,
+ int a)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float x,
+ float y,
+ float z,
+ float a)
+
+
+
+
+
+
+
+
+
+
+
+setupExternalMessages
+
+public void setupExternalMessages()
+
+
Set this sketch to communicate its state back to the PDE.
+
+ This uses the stderr stream to write positions of the window
+ (so that it will be saved by the PDE for the next run) and
+ notify on quit. See more notes in the Worker class.
+
+
+
+
+
+
+
+
+
+
+
+setupFrameResizeListener
+
+public void setupFrameResizeListener()
+
+
Set up a listener that will fire proper component resize events
+ in cases where frame.setResizable(true) is called.
+
+
+
+
+
+
+
+
+
+
+
+main
+
+public static void main(java.lang.String[] args)
+
+
main() method for running this class from the command line.
+
+ The options shown here are not yet finalized and will be
+ changing over the next several releases.
+
+ The simplest way to turn and applet into an application is to
+ add the following code to your program:
+
+ This will properly launch your applet from a double-clickable
+ .jar or from the command line.
+
+ Parameters useful for launching or also used by the PDE:
+
+ --location=x,y upper-lefthand corner of where the applet
+ should appear on screen. if not used,
+ the default is to center on the main screen.
+
+ --present put the applet into full screen presentation
+ mode. requires java 1.4 or later.
+
+ --exclusive use full screen exclusive mode when presenting.
+ disables new windows or interaction with other
+ monitors, this is like a "game" mode.
+
+ --hide-stop use to hide the stop button in situations where
+ you don't want to allow users to exit. also
+ see the FAQ on information for capturing the ESC
+ key when running in presentation mode.
+
+ --stop-color=#xxxxxx color of the 'stop' text used to quit an
+ sketch when it's in present mode.
+
+ --bgcolor=#xxxxxx background color of the window.
+
+ --sketch-path location of where to save files from functions
+ like saveStrings() or saveFrame(). defaults to
+ the folder that the java application was
+ launched from, which means if this isn't set by
+ the pde, everything goes into the same folder
+ as processing.exe.
+
+ --display=n set what display should be used by this applet.
+ displays are numbered starting from 1.
+
+ Parameters used by Processing when running via the PDE
+
+ --external set when the applet is being used by the PDE
+
+ --editor-location=x,y position of the upper-lefthand corner of the
+ editor window, for placement of applet window
+
Begin recording raw shape data to a renderer of the specified type,
+ using the width and height of the main drawing surface.
+
+ If hashmarks (###) are found in the filename, they'll be replaced
+ by the current frame number (frameCount).
+
Begin recording raw shape data to the specified renderer.
+
+ This simply echoes to g.beginRaw(), but since is placed here (rather than
+ generated by preproc.pl) for clarity and so that it doesn't echo the
+ command should beginRecord() be in use.
+
+
+
+
+
+
+
+
+
+
+
+endRaw
+
+public void endRaw()
+
+
Stop recording raw shape data to the specified renderer.
+
+ This simply echoes to g.beginRaw(), but since is placed here (rather than
+ generated by preproc.pl) for clarity and so that it doesn't echo the
+ command should beginRecord() be in use.
+
+
+
+
+
+
+
+
+
+
+
+loadPixels
+
+public void loadPixels()
+
+
Override the g.pixels[] function to set the pixels[] array
+ that's part of the PApplet object. Allows the use of
+ pixels[] in the code, rather than g.pixels[].
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels()
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels(int x1,
+ int y1,
+ int x2,
+ int y2)
+ An attempt is made to keep the constants as short/non-verbose
+ as possible. For instance, the constant is TIFF instead of
+ FILE_TYPE_TIFF. We'll do this as long as we can get away with it.
+
MAX_FLOAT
+
+
+ Same as Float.MAX_VALUE, but included for parity with MIN_VALUE,
+ and to avoid teaching static methods on the first day.
+
+
+
+static int
+
MAX_INT
+
+
+ Largest possible (positive) integer value
+
+
+
+static float
+
MIN_FLOAT
+
+
+ Note that Float.MIN_VALUE is the smallest positive value
+ for a floating point number, not actually the minimum (negative) value
+ for a float.
+
+
+
+static int
+
MIN_INT
+
+
+ Smallest possible (negative) integer value
Note that Float.MIN_VALUE is the smallest positive value
+ for a floating point number, not actually the minimum (negative) value
+ for a float. This constant equals 0xFF7FFFFF, the smallest (farthest
+ negative) value a float can have before it hits NaN.
+
textMode(MODEL) is the default, meaning that characters
+ will be affected by transformations like any other shapes.
+
+ Changed value in 0093 to not interfere with LEFT, CENTER, and RIGHT.
+
textMode(SHAPE) draws text using the the glyph outlines of
+ individual characters rather than as textures. If the outlines are
+ not available, then textMode(SHAPE) will be ignored and textMode(MODEL)
+ will be used instead. For this reason, be sure to call textMode()
+ after calling textFont().
+
+ Currently, textMode(SHAPE) is only supported by OPENGL mode.
+ It also requires Java 1.2 or higher (OPENGL requires 1.4 anyway)
+
+Grayscale bitmap font class used by Processing.
+
+ Awful (and by that, I mean awesome) ascii (non)art for how this works:
+
+ |
+ | height is the full used height of the image
+ |
+ | ..XX.. }
+ | ..XX.. }
+ | ...... }
+ | XXXX.. } topExtent (top y is baseline - topExtent)
+ | ..XX.. }
+ | ..XX.. } dotted areas are where the image data
+ | ..XX.. } is actually located for the character
+ +---XXXXXX---- } (it extends to the right and down
+ | for power of two texture sizes)
+ ^^^^ leftExtent (amount to move over before drawing the image
+
+ ^^^^^^^^^^^^^^ setWidth (width displaced by char)
+
Name of the font as seen by Java when it was created.
+ If the font is available, the native version will be used.
+
+
+
+
+
+
+
+psname
+
+public java.lang.String psname
+
+
Postscript name of the font that this bitmap was created from.
+
+
+
+
+
+
+
+size
+
+public int size
+
+
"natural" size of the font (most often 48)
+
+
+
+
+
+
+
+smooth
+
+public boolean smooth
+
+
true if smoothing was enabled for this font, used for native impl
+
+
+
+
+
+
+
+mbox2
+
+public int mbox2
+
+
next power of 2 over the max image size (usually 64)
+
+
+
+
+
+
+
+twidth
+
+public int twidth
+
+
texture width, same as mbox2, but reserved for future use
+
+
+
+
+
+
+
+theight
+
+public int theight
+
+
texture height, same as mbox2, but reserved for future use
+
+
+
+
+
+
+
+value
+
+public int[] value
+
+
+
+
+
+
+
+height
+
+public int[] height
+
+
+
+
+
+
+
+width
+
+public int[] width
+
+
+
+
+
+
+
+setWidth
+
+public int[] setWidth
+
+
+
+
+
+
+
+topExtent
+
+public int[] topExtent
+
+
+
+
+
+
+
+leftExtent
+
+public int[] leftExtent
+
+
+
+
+
+
+
+ascent
+
+public int ascent
+
+
+
+
+
+
+
+descent
+
+public int descent
+
+
+
+
+
+
+
+DEFAULT_CHARSET
+
+public static char[] DEFAULT_CHARSET
+
+
The default Processing character set.
+
+ This is the union of the Mac Roman and Windows ANSI (CP1250)
+ character sets. ISO 8859-1 Latin 1 is Unicode characters 0x80 -> 0xFF,
+ and would seem a good standard, but in practice, most P5 users would
+ rather have characters that they expect from their platform's fonts.
+
+ This is more of an interim solution until a much better
+ font solution can be determined. (i.e. create fonts on
+ the fly from some sort of vector format).
+
+ This is used by the Create Font tool, or whatever anyone else dreams
+ up for messing with fonts themselves.
+
+ It is assumed that the calling class will handle closing
+ the stream when finished.
+
+
+
+
+
+
+
Throws:
+
java.io.IOException
+
+
+
+
+
+index
+
+public int index(char c)
+
+
Get index for the char (convert from unicode to bagel charset).
+
+
+
+
+
+
+
Returns:
index into arrays or -1 if not found
+
+
+
+
+
+kern
+
+public float kern(char a,
+ char b)
+
+
Currently un-implemented for .vlw fonts,
+ but honored for layout in case subclasses use it.
+
+
+
+
+
+
+
+
+
+
+
+ascent
+
+public float ascent()
+
+
Returns the ascent of this font from the baseline.
+ The value is based on a font of size 1.
+
+
+
+
+
+
+
+
+
+
+
+descent
+
+public float descent()
+
+
Returns how far this font descends from the baseline.
+ The value is based on a font size of 1.
+
+
+
+
+
+
+
+
+
+
+
+width
+
+public float width(char c)
+
+
Width of this character for a font of size 1.
+
+
+
+
+
+
+
+
+
+
+
+list
+
+public static java.lang.String[] list()
+
+
Get a list of the fonts installed on the system that can be used
+ by Java. Not all fonts can be used in Java, in fact it's mostly
+ only TrueType fonts. OpenType fonts with CFF data such as Adobe's
+ OpenType fonts seem to have trouble (even though they're sort of
+ TrueType fonts as well, or may have a .ttf extension). Regular
+ PostScript fonts seem to work OK, however.
+
+ Not recommended for use in applets, but this is implemented
+ in PFont because the Java methods to access this information
+ have changed between 1.1 and 1.4, and the 1.4 method is
+ typical of the sort of undergraduate-level over-abstraction
+ that the seems to have made its way into the Java API after 1.1.
+
Starting with Java 1.5, Apple broke the ability to specify most fonts.
+ This has been filed as bug #4769141 at bugreporter.apple.com. More info at
+ Bug 407.
+
+Main graphics and rendering context, as well as the base API implementation.
+
+
Subclassing and initializing PGraphics objects
+ Starting in release 0149, subclasses of PGraphics are handled differently.
+ The constructor for subclasses takes no parameters, instead a series of
+ functions are called by the hosting PApplet to specify its attributes.
+
+
setParent(PApplet) - is called to specify the parent PApplet.
+
setPrimary(boolean) - called with true if this PGraphics will be the
+ primary drawing surface used by the sketch, or false if not.
+
setPath(String) - called when the renderer needs a filename or output
+ path, such as with the PDF or DXF renderers.
+
setSize(int, int) - this is called last, at which point it's safe for
+ the renderer to complete its initialization routine.
+
+ The functions were broken out because of the growing number of parameters
+ such as these that might be used by a renderer, yet with the exception of
+ setSize(), it's not clear which will be necessary. So while the size could
+ be passed in to the constructor instead of a setSize() function, a function
+ would still be needed that would notify the renderer that it was time to
+ finish its initialization. Thus, setSize() simply does both.
+
+
Know your rights: public vs. private methods
+ Methods that are protected are often subclassed by other renderers, however
+ they are not set 'public' because they shouldn't be part of the user-facing
+ public API accessible from PApplet. That is, we don't want sketches calling
+ textModeCheck() or vertexTexture() directly.
+
+
Handling warnings and exceptions
+ Methods that are unavailable generally show a warning, unless their lack of
+ availability will soon cause another exception. For instance, if a method
+ like getMatrix() returns null because it is unavailable, an exception will
+ be thrown stating that the method is unavailable, rather than waiting for
+ the NullPointerException that will occur when the sketch tries to use that
+ method. As of release 0149, warnings will only be shown once, and exceptions
+ have been changed to warnings where possible.
+
+
Using xxxxImpl() for subclassing smoothness
+ The xxxImpl() methods are generally renderer-specific handling for some
+ subset if tasks for a particular function (vague enough for you?) For
+ instance, imageImpl() handles drawing an image whose x/y/w/h and u/v coords
+ have been specified, and screen placement (independent of imageMode) has
+ been determined. There's no point in all renderers implementing the
+ if (imageMode == BLAH) placement/sizing logic, so that's handled
+ by PGraphics, which then calls imageImpl() once all that is figured out.
+
+
His brother PImage
+ PGraphics subclasses PImage so that it can be drawn and manipulated in a
+ similar fashion. As such, many methods are inherited from PGraphics,
+ though many are unavailable: for instance, resize() is not likely to be
+ implemented; the same goes for mask(), depending on the situation.
+
+
What's in PGraphics, what ain't
+ For the benefit of subclasses, as much as possible has been placed inside
+ PGraphics. For instance, bezier interpolation code and implementations of
+ the strokeCap() method (that simply sets the strokeCap variable) are
+ handled here. Features that will vary widely between renderers are located
+ inside the subclasses themselves. For instance, all matrix handling code
+ is per-renderer: Java 2D uses its own AffineTransform, P2D uses a PMatrix2D,
+ and PGraphics3D needs to keep continually update forward and reverse
+ transformations. A proper (future) OpenGL implementation will have all its
+ matrix madness handled by the card. Lighting also falls under this
+ category, however the base material property settings (emissive, specular,
+ et al.) are handled in PGraphics because they use the standard colorMode()
+ logic. Subclasses should override methods like emissiveFromCalc(), which
+ is a point where a valid color has been defined internally, and can be
+ applied in some manner based on the calcXxxx values.
+
+
What's in the PGraphics documentation, what ain't
+ Some things are noted here, some things are not. For public API, always
+ refer to the reference
+ on Processing.org for proper explanations. No attempt has been made to
+ keep the javadoc up to date or complete. It's an enormous task for
+ which we simply do not have the time. That is, it's not something that
+ to be done once—it's a matter of keeping the multiple references
+ synchronized (to say nothing of the translation issues), while targeting
+ them for their separate audiences. Ouch.
+
textureImage
+
+
+ Current image being used as a texture
+
+
+
+ int
+
textureMode
+
+
+ Sets whether texture coordinates passed to
+ vertex() calls will be based on coordinates that are
+ based on the IMAGE or NORMALIZED.
+
+
+
+ float
+
textureU
+
+
+ Current horizontal coordinate for texture, will always
+ be between 0 and 1, even if using textureMode(IMAGE).
+
+
+
+ float
+
textureV
+
+
+ Current vertical coordinate for texture, see above.
arc(float a,
+ float b,
+ float c,
+ float d,
+ float start,
+ float stop)
+
+
+ Identical parameters and placement to ellipse,
+ but draws only an arc of that ellipse.
+
+
+
+ void
+
background(float gray)
+
+
+ Set the background to a grayscale value, based on the
+ current colorMode.
+
+
+
+ void
+
background(float gray,
+ float alpha)
+
+
+ See notes about alpha in background(x, y, z, a).
+
+
+
+ void
+
background(float x,
+ float y,
+ float z)
+
+
+ Set the background to an r, g, b or h, s, b value,
+ based on the current colorMode.
+
+
+
+ void
+
background(float x,
+ float y,
+ float z,
+ float a)
+
+
+ Clear the background with a color that includes an alpha value.
+
+
+
+ void
+
background(int rgb)
+
+
+ Set the background to a gray or ARGB color.
+
+
+
+ void
+
background(int rgb,
+ float alpha)
+
+
+ See notes about alpha in background(x, y, z, a).
+
+
+
+ void
+
background(PImage image)
+
+
+ Takes an RGB or ARGB image and sets it as the background.
scale(float sx,
+ float sy)
+
+
+ Scale in X and Y.
+
+
+
+ void
+
scale(float x,
+ float y,
+ float z)
+
+
+ Scale in X, Y, and Z.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenX(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenZ(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ void
+
setMatrix(PMatrix source)
+
+
+ Set the current transformation matrix to the contents of another.
+
+
+
+ void
+
setMatrix(PMatrix2D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setMatrix(PMatrix3D source)
+
+
+ Set the current transformation to the contents of the specified source.
textFont(PFont which,
+ float size)
+
+
+ Useful function to set the font and size at the same time.
+
+
+
+ void
+
textLeading(float leading)
+
+
+ Set the text leading to a specific value.
+
+
+
+ void
+
textMode(int mode)
+
+
+ Sets the text rendering/placement to be either SCREEN (direct
+ to the screen, exact coordinates, only use the font's original size)
+ or MODEL (the default, where text is manipulated by translate() and
+ can have a textSize).
+
+
+
+ void
+
textSize(float size)
+
+
+ Sets the text size, also resets the value for the leading.
+
+
+
+ void
+
texture(PImage image)
+
+
+ Set texture image for current shape.
+
+
+
+ void
+
textureMode(int mode)
+
+
+ Set texture mode to either to use coordinates based on the IMAGE
+ (more intuitive for new users) or NORMALIZED (better for advanced chaps)
Max value for green (or saturation) set by colorMode
+
+
+
+
+
+
+
+colorModeZ
+
+public float colorModeZ
+
+
Max value for blue (or value) set by colorMode
+
+
+
+
+
+
+
+colorModeA
+
+public float colorModeA
+
+
Max value for alpha set by colorMode
+
+
+
+
+
+
+
+tint
+
+public boolean tint
+
+
True if tint() is enabled (read-only).
+
+ Using tint/tintColor seems a better option for naming than
+ tintEnabled/tint because the latter seems ugly, even though
+ g.tint as the actual color seems a little more intuitive,
+ it's just that g.tintEnabled is even more unintuitive.
+ Same goes for fill and stroke, et al.
+
+
+
+
+
+
+
+tintColor
+
+public int tintColor
+
+
tint that was last set (read-only)
+
+
+
+
+
+
+
+fill
+
+public boolean fill
+
+
true if fill() is enabled, (read-only)
+
+
+
+
+
+
+
+fillColor
+
+public int fillColor
+
+
fill that was last set (read-only)
+
+
+
+
+
+
+
+stroke
+
+public boolean stroke
+
+
true if stroke() is enabled, (read-only)
+
+
+
+
+
+
+
+strokeColor
+
+public int strokeColor
+
+
stroke that was last set (read-only)
+
+
+
+
+
+
+
+strokeWeight
+
+public float strokeWeight
+
+
Last value set by strokeWeight() (read-only). This has a default
+ setting, rather than fighting with renderers about whether that
+ renderer supports thick lines.
+
+
+
+
+
+
+
+strokeJoin
+
+public int strokeJoin
+
+
Set by strokeJoin() (read-only). This has a default setting
+ so that strokeJoin() need not be called by defaults,
+ because subclasses may not implement it (i.e. PGraphicsGL)
+
+
+
+
+
+
+
+strokeCap
+
+public int strokeCap
+
+
Set by strokeCap() (read-only). This has a default setting
+ so that strokeCap() need not be called by defaults,
+ because subclasses may not implement it (i.e. PGraphicsGL)
+
Last background color that was set, zero if an image
+
+
+
+
+
+
+
+image
+
+public java.awt.Image image
+
+
Java AWT Image object associated with this renderer. For P2D and P3D,
+ this will be associated with their MemoryImageSource. For PGraphicsJava2D,
+ it will be the offscreen drawing buffer.
+
+
+
+
+
+
+
+bezierDetail
+
+public int bezierDetail
+
+
+
+
+
+
+
+curveTightness
+
+public float curveTightness
+
+
+
+
+
+
+
+edge
+
+public boolean edge
+
+
+
+
+
+
+
+normalX
+
+public float normalX
+
+
Current normal vector.
+
+
+
+
+
+
+
+normalY
+
+public float normalY
+
+
Current normal vector.
+
+
+
+
+
+
+
+normalZ
+
+public float normalZ
+
+
Current normal vector.
+
+
+
+
+
+
+
+textureMode
+
+public int textureMode
+
+
Sets whether texture coordinates passed to
+ vertex() calls will be based on coordinates that are
+ based on the IMAGE or NORMALIZED.
+
+
+
+
+
+
+
+textureU
+
+public float textureU
+
+
Current horizontal coordinate for texture, will always
+ be between 0 and 1, even if using textureMode(IMAGE).
+
+
+
+
+
+
+
+textureV
+
+public float textureV
+
+
Current vertical coordinate for texture, see above.
+
Constructor for the PGraphics object. Use this to ensure that
+ the defaults get set properly. In a subclass, use this(w, h)
+ as the first line of a subclass' constructor to properly set
+ the internal fields and defaults.
+
Set (or unset) this as the main drawing surface. Meaning that it can
+ safely be set to opaque (and given a default gray background), or anything
+ else that goes along with that.
+
+
+
+
+
+
+
+
+
+
+
+setPath
+
+public void setPath(java.lang.String path)
+
+
+
+
+
+
+
+
+
+
+
+setSize
+
+public void setSize(int w,
+ int h)
+
+
The final step in setting up a renderer, set its size of this renderer.
+ This was formerly handled by the constructor, but instead it's been broken
+ out so that setParent/setPrimary/setPath can be handled differently.
+
+ Important that this is ignored by preproc.pl because otherwise it will
+ override setSize() in PApplet/Applet/Component, which will 1) not call
+ super.setSize(), and 2) will cause the renderer to be resized from the
+ event thread (EDT), causing a nasty crash as it collides with the
+ animation thread.
+
+
+
+
+
+
+
+
+
+
+
+dispose
+
+public void dispose()
+
+
Handle any takedown for this graphics context.
+
+ This is called when a sketch is shut down and this renderer was
+ specified using the size() command, or inside endRecord() and
+ endRaw(), in order to shut things off.
+
+
+
+
+
+
+
+
+
+
+
+canDraw
+
+public boolean canDraw()
+
+
Some renderers have requirements re: when they are ready to draw.
+
+
+
+
+
+
+
+
+
+
+
+beginDraw
+
+public void beginDraw()
+
+
Prepares the PGraphics for drawing.
+
+ When creating your own PGraphics, you should call this before
+ drawing anything.
+
+
+
+
+
+
+
+
+
+
+
+endDraw
+
+public void endDraw()
+
+
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
+
+
+
+
+
+
+
+
+
+
+flush
+
+public void flush()
+
+
+
+
+
+
+
+
+
+
+
+hint
+
+public void hint(int which)
+
+
Enable a hint option.
+
+ For the most part, hints are temporary api quirks,
+ for which a proper api hasn't been properly worked out.
+ for instance SMOOTH_IMAGES existed because smooth()
+ wasn't yet implemented, but it will soon go away.
+
+ They also exist for obscure features in the graphics
+ engine, like enabling/disabling single pixel lines
+ that ignore the zbuffer, the way they do in alphabot.
+
+ Current hint options:
+
+
DISABLE_DEPTH_TEST -
+ turns off the z-buffer in the P3D or OPENGL renderers.
+
+
+
+
+
+
+
+
+
+
+
+
+beginShape
+
+public void beginShape()
+
+
Start a new shape of type POLYGON
+
+
+
+
+
+
+
+
+
+
+
+beginShape
+
+public void beginShape(int kind)
+
+
Start a new shape.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
+
+
+
+
+
+
+
+
+
+
+edge
+
+public void edge(boolean edge)
+
+
Sets whether the upcoming vertex is part of an edge.
+ Equivalent to glEdgeFlag(), for people familiar with OpenGL.
+
Sets the current normal vector. Only applies with 3D rendering
+ and inside a beginShape/endShape block.
+
+ This is for drawing three dimensional shapes and surfaces,
+ allowing you to specify a vector perpendicular to the surface
+ of the shape, which determines how lighting affects it.
+
+ For the most part, PGraphics3D will attempt to automatically
+ assign normals to shapes, but since that's imperfect,
+ this is a better option when you want more control.
+
+ For people familiar with OpenGL, this function is basically
+ identical to glNormal3f().
+
+
+
+
+
+
+
+
+
+
+
+textureMode
+
+public void textureMode(int mode)
+
+
Set texture mode to either to use coordinates based on the IMAGE
+ (more intuitive for new users) or NORMALIZED (better for advanced chaps)
+
Identical parameters and placement to ellipse,
+ but draws only an arc of that ellipse.
+
+ start and stop are always radians because angleMode() was goofy.
+ ellipseMode() sets the placement.
+
+ also tries to be smart about start < stop.
+
+
+
+
+
+
+
+
+
+
+
+box
+
+public void box(float size)
+
+
+
+
+
+
+
+
+
+
+
+box
+
+public void box(float w,
+ float h,
+ float d)
+
+
+
+
+
+
+
+
+
+
+
+sphereDetail
+
+public void sphereDetail(int res)
+
+
+
+
+
+
+
+
+
+
+
+sphereDetail
+
+public void sphereDetail(int ures,
+ int vres)
+
+
Set the detail level for approximating a sphere. The ures and vres params
+ control the horizontal and vertical resolution.
+
+ Code for sphereDetail() submitted by toxi [031031].
+ Code for enhanced u/v version from davbol [080801].
+
+
+
+
+
+
+
+
+
+
+
+sphere
+
+public void sphere(float r)
+
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Evalutes quadratic bezier at point t for points a, b, c, d.
+ t varies between 0 and 1, and a and d are the on curve points,
+ b and c are the control points. this can be done once with the
+ x coordinates and a second time with the y coordinates to get
+ the location of a bezier curve at t.
+
+ For instance, to convert the following example:
+ stroke(255, 102, 0);
+ line(85, 20, 10, 10);
+ line(90, 90, 15, 80);
+ stroke(0, 0, 0);
+ bezier(85, 20, 10, 10, 90, 90, 15, 80);
+
+ // draw it in gray, using 10 steps instead of the default 20
+ // this is a slower way to do it, but useful if you need
+ // to do things with the coordinates at each step
+ stroke(128);
+ beginShape(LINE_STRIP);
+ for (int i = 0; i <= 10; i++) {
+ float t = i / 10.0f;
+ float x = bezierPoint(85, 10, 90, 15, t);
+ float y = bezierPoint(20, 10, 90, 80, t);
+ vertex(x, y);
+ }
+ endShape();
Draw a cubic bezier curve. The first and last points are
+ the on-curve points. The middle two are the 'control' points,
+ or 'handles' in an application like Illustrator.
+
+ As of 0070, this function no longer doubles the first and
+ last points. The curves are a bit more boring, but it's more
+ mathematically correct, and properly mirrored in curvePoint().
+
+public void image(PImage image,
+ float a,
+ float b,
+ float c,
+ float d,
+ int u1,
+ int v1,
+ int u2,
+ int v2)
+
+
Draw an image(), also specifying u/v coordinates.
+ In this method, the u, v coordinates are always based on image space
+ location, regardless of the current textureMode().
+
+
+
+
+
+
+
+
+
+
+
+shapeMode
+
+public void shapeMode(int mode)
+
+
Set the orientation for the shape() command (like imageMode() or rectMode()).
+
Sets the alignment of the text to one of LEFT, CENTER, or RIGHT.
+ This will also reset the vertical text alignment to BASELINE.
+
+
+
+
+
+
+
+
+
+
+
+textAlign
+
+public void textAlign(int alignX,
+ int alignY)
+
+
Sets the horizontal and vertical alignment of the text. The horizontal
+ alignment can be one of LEFT, CENTER, or RIGHT. The vertical alignment
+ can be TOP, BOTTOM, CENTER, or the BASELINE (the default).
+
+
+
+
+
+
+
+
+
+
+
+textAscent
+
+public float textAscent()
+
+
Returns the ascent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
+
+
+
+
+
+
+
+
+
+
+textDescent
+
+public float textDescent()
+
+
Returns the descent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Sets the current font. The font's size will be the "natural"
+ size of this font (the size that was set when using "Create Font").
+ The leading will also be reset.
+
Useful function to set the font and size at the same time.
+
+
+
+
+
+
+
+
+
+
+
+textLeading
+
+public void textLeading(float leading)
+
+
Set the text leading to a specific value. If using a custom
+ value for the text leading, you'll have to call textLeading()
+ again after any calls to textSize().
+
+
+
+
+
+
+
+
+
+
+
+textMode
+
+public void textMode(int mode)
+
+
Sets the text rendering/placement to be either SCREEN (direct
+ to the screen, exact coordinates, only use the font's original size)
+ or MODEL (the default, where text is manipulated by translate() and
+ can have a textSize). The text size cannot be set when using
+ textMode(SCREEN), because it uses the pixels directly from the font.
+
+
+
+
+
+
+
+
+
+
+
+textSize
+
+public void textSize(float size)
+
+
Sets the text size, also resets the value for the leading.
+
+
+
+
+
+
+
+
+
+
+
+textWidth
+
+public float textWidth(char c)
+
+
+
+
+
+
+
+
+
+
+
+textWidth
+
+public float textWidth(java.lang.String str)
+
+
Return the width of a line of text. If the text has multiple
+ lines, this returns the length of the longest line.
+
+
+
+
+
+
+
+
+
+
+
+text
+
+public void text(char c)
+
+
Write text where we just left off.
+
+
+
+
+
+
+
+
+
+
+
+text
+
+public void text(char c,
+ float x,
+ float y)
+
+
Draw a single character on screen.
+ Extremely slow when used with textMode(SCREEN) and Java 2D,
+ because loadPixels has to be called first and updatePixels last.
+
Draw a chunk of text.
+ Newlines that are \n (Unix newline or linefeed char, ascii 10)
+ are honored, but \r (carriage return, Windows and Mac OS) are
+ ignored.
+
+
+
+
+
+
+
+
+
+
+
+text
+
+public void text(char[] chars,
+ int start,
+ int stop,
+ float x,
+ float y)
+
+
Method to draw text from an array of chars. This method will usually be
+ more efficient than drawing from a String object, because the String will
+ not be converted to a char array before drawing.
+
Draw text in a box that is constrained to a particular size.
+ The current rectMode() determines what the coordinates mean
+ (whether x1/y1/x2/y2 or x/y/w/h).
+
+ Note that the x,y coords of the start of the box
+ will align with the *ascent* of the text, not the baseline,
+ as is the case for the other text() functions.
+
+ Newlines that are \n (Unix newline or linefeed char, ascii 10)
+ are honored, and \r (carriage return, Windows and Mac OS) are
+ ignored.
+
This does a basic number formatting, to avoid the
+ generally ugly appearance of printing floats.
+ Users who want more control should use their own nf() cmmand,
+ or if they want the long, ugly version of float,
+ use String.valueOf() to convert the float to a String first.
+
Two dimensional rotation.
+
+ Same as rotateZ (this is identical to a 3D rotation along the z-axis)
+ but included for clarity. It'd be weird for people drawing 2D graphics
+ to be using rotateZ. And they might kick our a-- for the confusion.
+
+ Additional background.
+
+
+
+
+
+
+
+
+
+
+
+rotateX
+
+public void rotateX(float angle)
+
+
Rotate around the X axis.
+
+
+
+
+
+
+
+
+
+
+
+rotateY
+
+public void rotateY(float angle)
+
+
Rotate around the Y axis.
+
+
+
+
+
+
+
+
+
+
+
+rotateZ
+
+public void rotateZ(float angle)
+
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Rotate about a vector in space. Same as the glRotatef() function.
+
+
+
+
+
+
+
+
+
+
+
+scale
+
+public void scale(float s)
+
+
Scale in all dimensions.
+
+
+
+
+
+
+
+
+
+
+
+scale
+
+public void scale(float sx,
+ float sy)
+
+
Scale in X and Y. Equivalent to scale(sx, sy, 1).
+
+ Not recommended for use in 3D, because the z-dimension is just
+ scaled by 1, since there's no way to know what else to scale it by.
+
+
+
+
+
+
+
+
+
+
+
+scale
+
+public void scale(float x,
+ float y,
+ float z)
+
+
Scale in X, Y, and Z.
+
+
+
+
+
+
+
+
+
+
+
+resetMatrix
+
+public void resetMatrix()
+
+
Set the current transformation matrix to identity.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenY
+
+public float screenY(float x,
+ float y)
+
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenX
+
+public float screenX(float x,
+ float y,
+ float z)
+
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenY
+
+public float screenY(float x,
+ float y,
+ float z)
+
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenZ
+
+public float screenZ(float x,
+ float y,
+ float z)
+
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns its z value.
+ This value can be used to determine if an (x, y, z) coordinate
+ is in front or in back of another (x, y, z) coordinate.
+ The units are based on how the zbuffer is set up, and don't
+ relate to anything "real". They're only useful for in
+ comparison to another value obtained from screenZ(),
+ or directly out of the zbuffer[].
+
+
+
+
+
+
+
+
+
+
+
+modelX
+
+public float modelX(float x,
+ float y,
+ float z)
+
+
Returns the model space x value for an x, y, z coordinate.
+
+ This will give you a coordinate after it has been transformed
+ by translate(), rotate(), and camera(), but not yet transformed
+ by the projection matrix. For instance, his can be useful for
+ figuring out how points in 3D space relate to the edge
+ coordinates of a shape.
+
+
+
+
+
+
+
+
+
+
+
+modelY
+
+public float modelY(float x,
+ float y,
+ float z)
+
+
Returns the model space y value for an x, y, z coordinate.
+
+
+
+
+
+
+
+
+
+
+
+modelZ
+
+public float modelZ(float x,
+ float y,
+ float z)
+
+
Returns the model space z value for an x, y, z coordinate.
+
+public void lightSpecular(float x,
+ float y,
+ float z)
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(int rgb)
+
+
Set the background to a gray or ARGB color.
+
+ For the main drawing surface, the alpha value will be ignored. However,
+ alpha can be used on PGraphics objects from createGraphics(). This is
+ the only way to set all the pixels partially transparent, for instance.
+
+ Note that background() should be called before any transformations occur,
+ because some implementations may require the current transformation matrix
+ to be identity before drawing.
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(int rgb,
+ float alpha)
+
+
See notes about alpha in background(x, y, z, a).
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(float gray)
+
+
Set the background to a grayscale value, based on the
+ current colorMode.
+
See notes about alpha in background(x, y, z, a).
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(float x,
+ float y,
+ float z)
+
+
Set the background to an r, g, b or h, s, b value,
+ based on the current colorMode.
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(float x,
+ float y,
+ float z,
+ float a)
+
+
Clear the background with a color that includes an alpha value. This can
+ only be used with objects created by createGraphics(), because the main
+ drawing surface cannot be set transparent.
+
+ It might be tempting to use this function to partially clear the screen
+ on each frame, however that's not how this function works. When calling
+ background(), the pixels will be replaced with pixels that have that level
+ of transparency. To do a semi-transparent overlay, use fill() with alpha
+ and draw a rectangle.
+
Takes an RGB or ARGB image and sets it as the background.
+ The width and height of the image must be the same size as the sketch.
+ Use image.resize(width, height) to make short work of such a task.
+
+ Note that even if the image is set as RGB, the high 8 bits of each pixel
+ should be set opaque (0xFF000000), because the image data will be copied
+ directly to the screen, and non-opaque background images may have strange
+ behavior. Using image.filter(OPAQUE) will handle this easily.
+
+ When using 3D, this will also clear the zbuffer (if it exists).
+
+
+
+
+
+
+
+
+
+
+
+colorMode
+
+public void colorMode(int mode)
+
+
Callback to handle clearing the background when begin/endRaw is in use.
+ Handled as separate function for OpenGL (or other) subclasses that
+ override backgroundImpl() but still needs this to work properly.
+
Show an renderer-related exception that halts the program. Currently just
+ wraps the message as a RuntimeException and throws it, but might do
+ something more specific might be used in the future.
+
+
+
+
+
+
+
+
+
+
+
+displayable
+
+public boolean displayable()
+
+
Return true if this renderer should be drawn to the screen. Defaults to
+ returning true, since nearly all renderers are on-screen beasts. But can
+ be overridden for subclasses like PDF so that a window doesn't open up.
+
+ A better name? showFrame, displayable, isVisible, visible, shouldDisplay,
+ what to call this?
+
+
+
+
+
+
+
+
+
+
+
+is2D
+
+public boolean is2D()
+
+
Return true if this renderer supports 2D drawing. Defaults to true.
+
+
+
+
+
+
+
+
+
+
+
+is3D
+
+public boolean is3D()
+
+
Return true if this renderer supports 2D drawing. Defaults to true.
+
+Subclass of PGraphics that handles fast 2D rendering using a
+ MemoryImageSource. The renderer found in this class is not as accurate as
+ PGraphicsJava2D, but offers certain speed tradeoffs, particular when
+ messing with the pixels array, or displaying image or video data.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from class processing.core.PGraphics
scale(float sx,
+ float sy)
+
+
+ Scale in X and Y.
+
+
+
+ void
+
scale(float x,
+ float y,
+ float z)
+
+
+ Scale in X, Y, and Z.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ void
+
sphere(float r)
+
+
+ Draw a sphere with radius r centered at coordinate 0, 0, 0.
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Set the detail level for approximating a sphere. The ures and vres params
+ control the horizontal and vertical resolution.
+
+ Code for sphereDetail() submitted by toxi [031031].
+ Code for enhanced u/v version from davbol [080801].
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Two dimensional rotation.
+
+ Same as rotateZ (this is identical to a 3D rotation along the z-axis)
+ but included for clarity. It'd be weird for people drawing 2D graphics
+ to be using rotateZ. And they might kick our a-- for the confusion.
+
+ Additional background.
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Scale in X and Y. Equivalent to scale(sx, sy, 1).
+
+ Not recommended for use in 3D, because the z-dimension is just
+ scaled by 1, since there's no way to know what else to scale it by.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+Subclass of PGraphics that handles 3D rendering.
+ It can render 3D inside a browser window and requires no plug-ins.
+
+ The renderer is mostly set up based on the structure of the OpenGL API,
+ if you have questions about specifics that aren't covered here,
+ look for reference on the OpenGL implementation of a similar feature.
+
+ Lighting and camera implementation by Simon Greenwold.
+
flush()
+
+
+ Emit any sorted geometry that's been collected on this frame.
+
+
+
+ void
+
frustum(float left,
+ float right,
+ float bottom,
+ float top,
+ float znear,
+ float zfar)
+
+
+ Same as glFrustum(), except that it wipes out (rather than
+ multiplies against) the current perspective matrix.
ortho()
+
+
+ Calls ortho() with the proper parameters for Processing's
+ standard orthographic projection.
+
+
+
+ void
+
ortho(float left,
+ float right,
+ float bottom,
+ float top,
+ float near,
+ float far)
+
+
+ Similar to gluOrtho(), but wipes out the current projection matrix.
+
+
+
+ void
+
perspective()
+
+
+ Calls perspective() with Processing's standard coordinate projection.
+
+
+
+ void
+
perspective(float fov,
+ float aspect,
+ float zNear,
+ float zFar)
+
+
+ Similar to gluPerspective().
popMatrix()
+
+
+ Replace the current transformation matrix with the top of the stack.
+
+
+
+ void
+
printCamera()
+
+
+ Print the current camera matrix.
+
+
+
+ void
+
printMatrix()
+
+
+ Print the current model (or "transformation") matrix.
+
+
+
+ void
+
printProjection()
+
+
+ Print the current projection matrix.
+
+
+
+ void
+
pushMatrix()
+
+
+ Push a copy of the current transformation matrix onto the stack.
+
+
+
+ void
+
resetMatrix()
+
+
+ Set the current transformation matrix to identity.
+
+
+
+ void
+
rotate(float angle)
+
+
+ Two dimensional rotation.
+
+
+
+ void
+
rotate(float angle,
+ float v0,
+ float v1,
+ float v2)
+
+
+ Rotate around an arbitrary vector, similar to glRotate(),
+ except that it takes radians (instead of degrees).
+
+
+
+ void
+
rotateX(float angle)
+
+
+ Rotate around the X axis.
+
+
+
+ void
+
rotateY(float angle)
+
+
+ Rotate around the Y axis.
+
+
+
+ void
+
rotateZ(float angle)
+
+
+ Rotate around the Z axis.
scale(float sx,
+ float sy)
+
+
+ Same as scale(sx, sy, 1).
+
+
+
+ void
+
scale(float x,
+ float y,
+ float z)
+
+
+ Scale in three dimensions.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenX(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenZ(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ void
+
setMatrix(PMatrix2D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setMatrix(PMatrix3D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setSize(int iwidth,
+ int iheight)
+
+
+ Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+
+
+ void
+
smooth()
+
+
+ If true in PImage, use bilinear interpolation for copy()
+ operations.
+
+
+
+ void
+
sphere(float r)
+
+
+ Draw a sphere with radius r centered at coordinate 0, 0, 0.
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+ Note that this will nuke any cameraMode() settings.
+
See notes in PGraphics.
+ If z-sorting has been turned on, then the triangles will
+ all be quicksorted here (to make alpha work more properly)
+ and then blit to the screen.
+
+ For the most part, hints are temporary api quirks,
+ for which a proper api hasn't been properly worked out.
+ for instance SMOOTH_IMAGES existed because smooth()
+ wasn't yet implemented, but it will soon go away.
+
+ They also exist for obscure features in the graphics
+ engine, like enabling/disabling single pixel lines
+ that ignore the zbuffer, the way they do in alphabot.
+
+ Current hint options:
+
+
DISABLE_DEPTH_TEST -
+ turns off the z-buffer in the P3D or OPENGL renderers.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Two dimensional rotation. Same as rotateZ (this is identical
+ to a 3D rotation along the z-axis) but included for clarity --
+ it'd be weird for people drawing 2D graphics to be using rotateZ.
+ And they might kick our a-- for the confusion.
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Apply a 4x4 transformation matrix. Same as glMultMatrix().
+ This call will be slow because it will try to calculate the
+ inverse of the transform. So avoid it whenever possible.
+
Set matrix mode to the camera matrix (instead of the current
+ transformation matrix). This means applyMatrix, resetMatrix, etc.
+ will affect the camera.
+
+ Note that the camera matrix is *not* the perspective matrix,
+ it is in front of the modelview matrix (hence the name "model"
+ and "view" for that matrix).
+
+ beginCamera() specifies that all coordinate transforms until endCamera()
+ should be pre-applied in inverse to the camera transform matrix.
+ Note that this is only challenging when a user specifies an arbitrary
+ matrix with applyMatrix(). Then that matrix will need to be inverted,
+ which may not be possible. But take heart, if a user is applying a
+ non-invertible matrix to the camera transform, then he is clearly
+ up to no good, and we can wash our hands of those bad intentions.
+
+ begin/endCamera clauses do not automatically reset the camera transform
+ matrix. That's because we set up a nice default camera transform int
+ setup(), and we expect it to hold through draw(). So we don't reset
+ the camera transform matrix at the top of draw(). That means that an
+ innocuous-looking clause like
+
+ at the top of draw(), will result in a runaway camera that shoots
+ infinitely out of the screen over time. In order to prevent this,
+ it is necessary to call some function that does a hard reset of the
+ camera transform matrix inside of begin/endCamera. Two options are
+
+ camera(); // sets up the nice default camera transform
+ resetMatrix(); // sets up the identity camera transform
+
+ So to rotate a camera a constant amount, you might try
+
Record the current settings into the camera matrix, and set
+ the matrix mode back to the current transformation matrix.
+
+ Note that this will destroy any settings to scale(), translate(),
+ or whatever, because the final camera matrix will be copied
+ (not multiplied) into the modelview.
+
+ Camera behavior can be split into two separate components, camera
+ transformation, and projection. The transformation corresponds to the
+ physical location, orientation, and scale of the camera. In a physical
+ camera metaphor, this is what can manipulated by handling the camera
+ body (with the exception of scale, which doesn't really have a physcial
+ analog). The projection corresponds to what can be changed by
+ manipulating the lens.
+
+ We maintain separate matrices to represent the camera transform and
+ projection. An important distinction between the two is that the camera
+ transform should be invertible, where the projection matrix should not,
+ since it serves to map three dimensions to two. It is possible to bake
+ the two matrices into a single one just by multiplying them together,
+ but it isn't a good idea, since lighting, z-ordering, and z-buffering
+ all demand a true camera z coordinate after modelview and camera
+ transforms have been applied but before projection. If the camera
+ transform and projection are combined there is no way to recover a
+ good camera-space z-coordinate from a model coordinate.
+
+ Fortunately, there are no functions that manipulate both camera
+ transformation and projection.
+
+ camera() sets the camera position, orientation, and center of the scene.
+ It replaces the camera transform with a new one. This is different from
+ gluLookAt(), but I think the only reason that GLU's lookat doesn't fully
+ replace the camera matrix with the new one, but instead multiplies it,
+ is that GL doesn't enforce the separation of camera transform and
+ projection, so it wouldn't be safe (you'd probably stomp your projection).
+
+ The transformation functions are the same ones used to manipulate the
+ modelview matrix (scale, translate, rotate, etc.). But they are bracketed
+ with beginCamera(), endCamera() to indicate that they should apply
+ (in inverse), to the camera transformation matrix.
+
+ This differs considerably from camera transformation in OpenGL.
+ OpenGL only lets you say, apply everything from here out to the
+ projection or modelview matrix. This makes it very hard to treat camera
+ manipulation as if it were a physical camera. Imagine that you want to
+ move your camera 100 units forward. In OpenGL, you need to apply the
+ inverse of that transformation or else you'll move your scene 100 units
+ forward--whether or not you've specified modelview or projection matrix.
+ Remember they're just multiplied by model coods one after another.
+ So in order to treat a camera like a physical camera, it is necessary
+ to pre-apply inverse transforms to a matrix that will be applied to model
+ coordinates. OpenGL provides nothing of this sort, but Processing does!
+ This is the camera transform matrix.
+
+ do not need to be called from with beginCamera();/endCamera();
+ That's because they always apply to the camera transformation,
+ and they always totally replace it. That means that any coordinate
+ transforms done before camera(); in draw() will be wiped out.
+ It also means that camera() always operates in untransformed world
+ coordinates. Therefore it is always redundant to call resetMatrix();
+ before camera(); This isn't technically true of gluLookat, but it's
+ pretty much how it's used.
+
+ Now, beginCamera(); and endCamera(); are useful if you want to move
+ the camera around using transforms like translate(), etc. They will
+ wipe out any coordinate system transforms that occur before them in
+ draw(), but they will not automatically wipe out the camera transform.
+ This means that they should be at the top of draw(). It also means
+ that the following:
+
+ will result in a camera that spins without stopping. If you want to
+ just rotate a small constant amount, try this:
+
+ beginCamera();
+ camera(); // sets up the default view
+ rotateY(PI/8);
+ endCamera();
+
+ That will rotate a little off of the default view. Note that this
+ is entirely equivalent to
+
+ camera(); // sets up the default view
+ beginCamera();
+ rotateY(PI/8);
+ endCamera();
+
+ because camera() doesn't care whether or not it's inside a
+ begin/end clause. Basically it's safe to use camera() or
+ camera(ex, ey, ez, cx, cy, cz, ux, uy, uz) as naked calls because
+ they do all the matrix resetting automatically.
+
Calls perspective() with Processing's standard coordinate projection.
+
+ Projection functions:
+
+
frustrum()
+
ortho()
+
perspective()
+
+ Each of these three functions completely replaces the projection
+ matrix with a new one. They can be called inside setup(), and their
+ effects will be felt inside draw(). At the top of draw(), the projection
+ matrix is not reset. Therefore the last projection function to be
+ called always dominates. On resize, the default projection is always
+ established, which has perspective.
+
+ This behavior is pretty much familiar from OpenGL, except where
+ functions replace matrices, rather than multiplying against the
+ previous.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns its z value.
+ This value can be used to determine if an (x, y, z) coordinate
+ is in front or in back of another (x, y, z) coordinate.
+ The units are based on how the zbuffer is set up, and don't
+ relate to anything "real". They're only useful for in
+ comparison to another value obtained from screenZ(),
+ or directly out of the zbuffer[].
+
Returns the model space x value for an x, y, z coordinate.
+
+ This will give you a coordinate after it has been transformed
+ by translate(), rotate(), and camera(), but not yet transformed
+ by the projection matrix. For instance, his can be useful for
+ figuring out how points in 3D space relate to the edge
+ coordinates of a shape.
+
+ The Lighting Skinny:
+
+ The way lighting works is complicated enough that it's worth
+ producing a document to describe it. Lighting calculations proceed
+ pretty much exactly as described in the OpenGL red book.
+
+ Light-affecting material properties:
+
+ AMBIENT COLOR
+ - multiplies by light's ambient component
+ - for believability this should match diffuse color
+
+ DIFFUSE COLOR
+ - multiplies by light's diffuse component
+
+ SPECULAR COLOR
+ - multiplies by light's specular component
+ - usually less colored than diffuse/ambient
+
+ SHININESS
+ - the concentration of specular effect
+ - this should be set pretty high (20-50) to see really
+ noticeable specularity
+
+ EMISSIVE COLOR
+ - constant additive color effect
+
+ Light types:
+
+ AMBIENT
+ - one color
+ - no specular color
+ - no direction
+ - may have falloff (constant, linear, and quadratic)
+ - may have position (which matters in non-constant falloff case)
+ - multiplies by a material's ambient reflection
+
+ DIRECTIONAL
+ - has diffuse color
+ - has specular color
+ - has direction
+ - no position
+ - no falloff
+ - multiplies by a material's diffuse and specular reflections
+
+ POINT
+ - has diffuse color
+ - has specular color
+ - has position
+ - no direction
+ - may have falloff (constant, linear, and quadratic)
+ - multiplies by a material's diffuse and specular reflections
+
+ SPOT
+ - has diffuse color
+ - has specular color
+ - has position
+ - has direction
+ - has cone angle (set to half the total cone angle)
+ - has concentration value
+ - may have falloff (constant, linear, and quadratic)
+ - multiplies by a material's diffuse and specular reflections
+
+ Normal modes:
+
+ All of the primitives (rect, box, sphere, etc.) have their normals
+ set nicely. During beginShape/endShape normals can be set by the user.
+
+ AUTO-NORMAL
+ - if no normal is set during the shape, we are in auto-normal mode
+ - auto-normal calculates one normal per triangle (face-normal mode)
+
+ SHAPE-NORMAL
+ - if one normal is set during the shape, it will be used for
+ all vertices
+
+ VERTEX-NORMAL
+ - if multiple normals are set, each normal applies to
+ subsequent vertices
+ - (except for the first one, which applies to previous
+ and subsequent vertices)
+
+ Efficiency consequences:
+
+ There is a major efficiency consequence of position-dependent
+ lighting calculations per vertex. (See below for determining
+ whether lighting is vertex position-dependent.) If there is no
+ position dependency then the only factors that affect the lighting
+ contribution per vertex are its colors and its normal.
+ There is a major efficiency win if
+
+ 1) lighting is not position dependent
+ 2) we are in AUTO-NORMAL or SHAPE-NORMAL mode
+
+ because then we can calculate one lighting contribution per shape
+ (SHAPE-NORMAL) or per triangle (AUTO-NORMAL) and simply multiply it
+ into the vertex colors. The converse is our worst-case performance when
+
+ 1) lighting is position dependent
+ 2) we are in AUTO-NORMAL mode
+
+ because then we must calculate lighting per-face * per-vertex.
+ Each vertex has a different lighting contribution per face in
+ which it appears. Yuck.
+
+ Determining vertex position dependency:
+
+ If any of the following factors are TRUE then lighting is
+ vertex position dependent:
+
+ 1) Any lights uses non-constant falloff
+ 2) There are any point or spot lights
+ 3) There is a light with specular color AND there is a
+ material with specular color
+
+ So worth noting is that default lighting (a no-falloff ambient
+ and a directional without specularity) is not position-dependent.
+ We should capitalize.
+
+ Simon Greenwold, April 2005
+
Add an ambient light based on the current color mode.
+ This version includes an (x, y, z) position for situations
+ where the falloff distance is used.
+
+Subclass for PGraphics that implements the graphics API using Java2D.
+
+
Pixel operations too slow? As of release 0085 (the first beta),
+ the default renderer uses Java2D. It's more accurate than the renderer
+ used in alpha releases of Processing (it handles stroke caps and joins,
+ and has better polygon tessellation), but it's super slow for handling
+ pixels. At least until we get a chance to get the old 2D renderer
+ (now called P2D) working in a similar fashion, you can use
+ size(w, h, P3D) instead of size(w, h) which will
+ be faster for general pixel flipping madness.
+
+
To get access to the Java 2D "Graphics2D" object for the default
+ renderer, use:
+
Graphics2D g2 = ((PGraphicsJava2D)g).g2;
+ This will let you do Java 2D stuff directly, but is not supported in
+ any way shape or form. Which just means "have fun, but don't complain
+ if it breaks."
breakShape()
+
+
+ This feature is in testing, do not use or rely upon its implementation
+
+
+
+ boolean
+
canDraw()
+
+
+ Some renderers have requirements re: when they are ready to draw.
+
+
+
+ void
+
copy(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
+ Copy things from one area of this image
+ to another area in the same image.
getImpl(int x,
+ int y,
+ int w,
+ int h)
+
+
+ Internal function to actually handle getting a block of pixels that
+ has already been properly cropped to a valid region.
scale(float sx,
+ float sy)
+
+
+ Scale in X and Y.
+
+
+
+ void
+
scale(float sx,
+ float sy,
+ float sz)
+
+
+ Scale in X, Y, and Z.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenX(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenZ(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ void
+
set(int x,
+ int y,
+ int argb)
+
+
+ Set a single pixel to the specified color.
+
+
+
+ void
+
setMatrix(PMatrix2D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setMatrix(PMatrix3D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setSize(int iwidth,
+ int iheight)
+
+
+ Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+
+
+ void
+
smooth()
+
+
+ If true in PImage, use bilinear interpolation for copy()
+ operations.
+
+
+
+ void
+
sphere(float r)
+
+
+ Draw a sphere with radius r centered at coordinate 0, 0, 0.
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+ Note that this will nuke any cameraMode() settings.
+
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Returns the ascent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Returns the descent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Two dimensional rotation.
+
+ Same as rotateZ (this is identical to a 3D rotation along the z-axis)
+ but included for clarity. It'd be weird for people drawing 2D graphics
+ to be using rotateZ. And they might kick our a-- for the confusion.
+
+ Additional background.
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Scale in X and Y. Equivalent to scale(sx, sy, 1).
+
+ Not recommended for use in 3D, because the z-dimension is just
+ scaled by 1, since there's no way to know what else to scale it by.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns its z value.
+ This value can be used to determine if an (x, y, z) coordinate
+ is in front or in back of another (x, y, z) coordinate.
+ The units are based on how the zbuffer is set up, and don't
+ relate to anything "real". They're only useful for in
+ comparison to another value obtained from screenZ(),
+ or directly out of the zbuffer[].
+
Actual implementation of clearing the background, now that the
+ internal variables for background color have been set. Called by the
+ backgroundFromCalc() method, which is what all the other background()
+ methods call once the work is done.
+
Call this when you want to mess with the pixels[] array.
+
+ For subclasses where the pixels[] buffer isn't set by default,
+ this should copy all data into the pixels[] array
+
Returns an ARGB "color" type (a packed 32 bit int with the color.
+ If the coordinate is outside the image, zero is returned
+ (black, but completely transparent).
+
+ If the image is in RGB format (i.e. on a PVideo object),
+ the value will get its high bits set, just to avoid cases where
+ they haven't been set already.
+
+ If the image is in ALPHA format, this returns a white with its
+ alpha value set.
+
+ This function is included primarily for beginners. It is quite
+ slow because it has to check to see if the x, y that was provided
+ is inside the bounds, and then has to check to see what image
+ type it is. If you want things to be more efficient, access the
+ pixels[] array directly.
+
Internal function to actually handle getting a block of pixels that
+ has already been properly cropped to a valid region. That is, x/y/w/h
+ are guaranteed to be inside the image space, so the implementation can
+ use the fastest possible pixel copying method.
+
Set alpha channel for an image. Black colors in the source
+ image will make the destination image completely transparent,
+ and white will make things fully opaque. Gray values will
+ be in-between steps.
+
+ Strictly speaking the "blue" value from the source image is
+ used as the alpha color. For a fully grayscale image, this
+ is correct, but for a color image it's not 100% accurate.
+ For a more accurate conversion, first use filter(GRAY)
+ which will make the image into a "correct" grayscake by
+ performing a proper luminance-based conversion.
+
PImage()
+
+
+ Create an empty image object, set its format to RGB.
+
+
+
PImage(java.awt.Image img)
+
+
+ Construct a new PImage from a java.awt.Image.
+
+
+
PImage(int width,
+ int height)
+
+
+ Create a new RGB (alpha ignored) image of a specific size.
+
+
+
PImage(int width,
+ int height,
+ int format)
+
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
blend(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ int mode)
+
+
+ Blends one area of this image to another area.
+
+
+
+ void
+
blend(PImage src,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ int mode)
+
+
+ Copies area of one image into another PImage object.
+
+
+
+static int
+
blendColor(int c1,
+ int c2,
+ int mode)
+
+
+ Blend two colors based on a particular mode.
+
+
+
+ java.lang.Object
+
clone()
+
+
+ Duplicate an image, returns new PImage object.
+
+
+
+ void
+
copy(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
+ Copy things from one area of this image
+ to another area in the same image.
+
+
+
+ void
+
copy(PImage src,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
+ Copies area of one image into another PImage object.
+
+
+
+ void
+
filter(int kind)
+
+
+ Method to apply a variety of basic filters to this image.
+
+
+
+ void
+
filter(int kind,
+ float param)
+
+
+ Method to apply a variety of basic filters to this image.
get(int x,
+ int y,
+ int w,
+ int h)
+
+
+ Grab a subsection of a PImage, and copy it into a fresh PImage.
+
+
+
+ java.lang.Object
+
getCache(java.lang.Object parent)
+
+
+ Get cache storage data for the specified renderer.
+
+
+
+ java.awt.Image
+
getImage()
+
+
+ Returns a BufferedImage from this PImage.
+
+
+
+ void
+
init(int width,
+ int height,
+ int format)
+
+
+ Function to be used by subclasses of PImage to init later than
+ at the constructor, or re-init later when things changes.
loadPixels()
+
+
+ Call this when you want to mess with the pixels[] array.
+
+
+
+ void
+
mask(int[] alpha)
+
+
+ Set alpha channel for an image.
+
+
+
+ void
+
mask(PImage alpha)
+
+
+ Set alpha channel for an image using another image as the source.
+
+
+
+ void
+
removeCache(java.lang.Object parent)
+
+
+ Remove information associated with this renderer from the cache, if any.
+
+
+
+ void
+
resize(int wide,
+ int high)
+
+
+ Resize this image to a new width and height.
+
+
+
+ void
+
save(java.lang.String path)
+
+
+ Save this image to disk.
+
+
+
+ void
+
set(int x,
+ int y,
+ int c)
+
+
+ Set a single pixel to the specified color.
+
+
+
+ void
+
set(int x,
+ int y,
+ PImage src)
+
+
+ Efficient method of drawing an image's pixels directly to this surface.
+
+
+
+ void
+
setCache(java.lang.Object parent,
+ java.lang.Object storage)
+
+
+ Store data of some kind for a renderer that requires extra metadata of
+ some kind.
Format for this image, one of RGB, ARGB or ALPHA.
+ note that RGB images still require 0xff in the high byte
+ because of how they'll be manipulated by other functions
+
Path to parent object that will be used with save().
+ This prevents users from needing savePath() to use PImage.save().
+
+
+
+
+
+
+
+
+
+
+
+Constructor Detail
+
+
+
+
+PImage
+
+public PImage()
+
+
Create an empty image object, set its format to RGB.
+ The pixel array is not allocated.
+
+
+
+
+
+PImage
+
+public PImage(int width,
+ int height)
+
+
Create a new RGB (alpha ignored) image of a specific size.
+ All pixels are set to zero, meaning black, but since the
+ alpha is zero, it will be transparent.
+
+
+
+
+
+PImage
+
+public PImage(int width,
+ int height,
+ int format)
+
+
+
+
+
+PImage
+
+public PImage(java.awt.Image img)
+
+
Construct a new PImage from a java.awt.Image. This constructor assumes
+ that you've done the work of making sure a MediaTracker has been used
+ to fully download the data and that the img is valid.
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+init
+
+public void init(int width,
+ int height,
+ int format)
+
+
Function to be used by subclasses of PImage to init later than
+ at the constructor, or re-init later when things changes.
+ Used by Capture and Movie classes (and perhaps others),
+ because the width/height will not be known when super() is called.
+ (Leave this public so that other libraries can do the same.)
+
Store data of some kind for a renderer that requires extra metadata of
+ some kind. Usually this is a renderer-specific representation of the
+ image data, for instance a BufferedImage with tint() settings applied for
+ PGraphicsJava2D, or resized image data and OpenGL texture indices for
+ PGraphicsOpenGL.
+
Get cache storage data for the specified renderer. Because each renderer
+ will cache data in different formats, it's necessary to store cache data
+ keyed by the renderer object. Otherwise, attempting to draw the same
+ image to both a PGraphicsJava2D and a PGraphicsOpenGL will cause errors.
+
+
+
+
+
+
Parameters:
parent - The PGraphics object (or any object, really) associated
+
Returns:
data stored for the specified parent
+
+
+
+
+
+removeCache
+
+public void removeCache(java.lang.Object parent)
+
+
Remove information associated with this renderer from the cache, if any.
+
+
+
+
+
+
Parameters:
parent - The PGraphics object whose cache data should be removed
+
+
+
+
+
+isModified
+
+public boolean isModified()
+
+
+
+
+
+
+
+
+
+
+
+setModified
+
+public void setModified()
+
+
+
+
+
+
+
+
+
+
+
+setModified
+
+public void setModified(boolean m)
+
+
+
+
+
+
+
+
+
+
+
+loadPixels
+
+public void loadPixels()
+
+
Call this when you want to mess with the pixels[] array.
+
+ For subclasses where the pixels[] buffer isn't set by default,
+ this should copy all data into the pixels[] array
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels()
+
+
Call this when finished messing with the pixels[] array.
+
+ Mark all pixels as needing update.
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels(int x,
+ int y,
+ int w,
+ int h)
+
+
Mark the pixels in this region as needing an update.
+
+ This is not currently used by any of the renderers, however the api
+ is structured this way in the hope of being able to use this to
+ speed things up in the future.
+
Duplicate an image, returns new PImage object.
+ The pixels[] array for the new object will be unique
+ and recopied from the source image. This is implemented as an
+ override of Object.clone(). We recommend using get() instead,
+ because it prevents you from needing to catch the
+ CloneNotSupportedException, and from doing a cast from the result.
+
+
+
Overrides:
clone in class java.lang.Object
+
+
+
+
Throws:
+
java.lang.CloneNotSupportedException
+
+
+
+
+
+resize
+
+public void resize(int wide,
+ int high)
+
+
Resize this image to a new width and height.
+ Use 0 for wide or high to make that dimension scale proportionally.
+
+
+
+
+
+
+
+
+
+
+
+get
+
+public int get(int x,
+ int y)
+
+
Returns an ARGB "color" type (a packed 32 bit int with the color.
+ If the coordinate is outside the image, zero is returned
+ (black, but completely transparent).
+
+ If the image is in RGB format (i.e. on a PVideo object),
+ the value will get its high bits set, just to avoid cases where
+ they haven't been set already.
+
+ If the image is in ALPHA format, this returns a white with its
+ alpha value set.
+
+ This function is included primarily for beginners. It is quite
+ slow because it has to check to see if the x, y that was provided
+ is inside the bounds, and then has to check to see what image
+ type it is. If you want things to be more efficient, access the
+ pixels[] array directly.
+
+
+
+
+
+
+
+
+
+
+
+get
+
+public PImageget(int x,
+ int y,
+ int w,
+ int h)
+
+
Grab a subsection of a PImage, and copy it into a fresh PImage.
+ As of release 0149, no longer honors imageMode() for the coordinates.
+
Efficient method of drawing an image's pixels directly to this surface.
+ No variations are employed, meaning that any scale, tint, or imageMode
+ settings will be ignored.
+
+
+
+
+
+
+
+
+
+
+
+mask
+
+public void mask(int[] alpha)
+
+
Set alpha channel for an image. Black colors in the source
+ image will make the destination image completely transparent,
+ and white will make things fully opaque. Gray values will
+ be in-between steps.
+
+ Strictly speaking the "blue" value from the source image is
+ used as the alpha color. For a fully grayscale image, this
+ is correct, but for a color image it's not 100% accurate.
+ For a more accurate conversion, first use filter(GRAY)
+ which will make the image into a "correct" grayscake by
+ performing a proper luminance-based conversion.
+
Set alpha channel for an image using another image as the source.
+
+
+
+
+
+
+
+
+
+
+
+filter
+
+public void filter(int kind)
+
+
Method to apply a variety of basic filters to this image.
+
+
+
filter(BLUR) provides a basic blur.
+
filter(GRAY) converts the image to grayscale based on luminance.
+
filter(INVERT) will invert the color components in the image.
+
filter(OPAQUE) set all the high bits in the image to opaque
+
filter(THRESHOLD) converts the image to black and white.
+
filter(DILATE) grow white/light areas
+
filter(ERODE) shrink white/light areas
+
+ Luminance conversion code contributed by
+ toxi
+
+ Gaussian blur code contributed by
+ Mario Klingemann
+
+
+
+
+
+
+
+
+
+
+
+filter
+
+public void filter(int kind,
+ float param)
+
+
Method to apply a variety of basic filters to this image.
+ These filters all take a parameter.
+
+
+
filter(BLUR, int radius) performs a gaussian blur of the
+ specified radius.
+
filter(POSTERIZE, int levels) will posterize the image to
+ between 2 and 255 levels.
+
filter(THRESHOLD, float center) allows you to set the
+ center point for the threshold. It takes a value from 0 to 1.0.
+
+ Gaussian blur code contributed by
+ Mario Klingemann
+ and later updated by toxi for better speed.
+
+
+
+
+
+
+
+
+
+
+
+copy
+
+public void copy(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
Copy things from one area of this image
+ to another area in the same image.
+
+
+
+
+
+
+
+
+
+
+
+copy
+
+public void copy(PImage src,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
Copies area of one image into another PImage object.
+
+
+
+
+
+
+
+
+
+
+
+blendColor
+
+public static int blendColor(int c1,
+ int c2,
+ int mode)
+
+
Blend two colors based on a particular mode.
+
+
REPLACE - destination colour equals colour of source pixel: C = A.
+ Sometimes called "Normal" or "Copy" in other software.
+
+
BLEND - linear interpolation of colours:
+ C = A*factor + B
+
+
ADD - additive blending with white clip:
+ C = min(A*factor + B, 255).
+ Clipped to 0..255, Photoshop calls this "Linear Burn",
+ and Director calls it "Add Pin".
+
+
SUBTRACT - substractive blend with black clip:
+ C = max(B - A*factor, 0).
+ Clipped to 0..255, Photoshop calls this "Linear Dodge",
+ and Director calls it "Subtract Pin".
+
+
DARKEST - only the darkest colour succeeds:
+ C = min(A*factor, B).
+ Illustrator calls this "Darken".
+
+
LIGHTEST - only the lightest colour succeeds:
+ C = max(A*factor, B).
+ Illustrator calls this "Lighten".
+
+
DIFFERENCE - subtract colors from underlying image.
+
+
EXCLUSION - similar to DIFFERENCE, but less extreme.
+
+
MULTIPLY - Multiply the colors, result will always be darker.
+
+
SCREEN - Opposite multiply, uses inverse values of the colors.
+
+
OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values,
+ and screens light values.
+
+
HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
+
+
SOFT_LIGHT - Mix of DARKEST and LIGHTEST.
+ Works like OVERLAY, but not as harsh.
+
+
DODGE - Lightens light tones and increases contrast, ignores darks.
+ Called "Color Dodge" in Illustrator and Photoshop.
+
+
BURN - Darker areas are applied, increasing contrast, ignores lights.
+ Called "Color Burn" in Illustrator and Photoshop.
+
+
A useful reference for blending modes and their algorithms can be
+ found in the SVG
+ specification.
+
It is important to note that Processing uses "fast" code, not
+ necessarily "correct" code. No biggie, most software does. A nitpicker
+ can find numerous "off by 1 division" problems in the blend code where
+ >>8 or >>7 is used when strictly speaking
+ /255.0 or /127.0 should have been used.
+
For instance, exclusion (not intended for real-time use) reads
+ r1 + r2 - ((2 * r1 * r2) / 255) because 255 == 1.0
+ not 256 == 1.0. In other words, (255*255)>>8 is not
+ the same as (255*255)/255. But for real-time use the shifts
+ are preferrable, and the difference is insignificant for applications
+ built with Processing.
+
+
+
+
+
+
+
+
+
+
+
+blend
+
+public void blend(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ int mode)
+ As of revision 0100, this function requires an absolute path,
+ in order to avoid confusion. To save inside the sketch folder,
+ use the function savePath() from PApplet, or use saveFrame() instead.
+ As of revision 0116, savePath() is not needed if this object has been
+ created (as recommended) via createImage() or createGraphics() or
+ one of its neighbors.
+
+ As of revision 0115, when using Java 1.4 and later, you can write
+ to several formats besides tga and tiff. If Java 1.4 is installed
+ and the extension used is supported (usually png, jpg, jpeg, bmp,
+ and tiff), then those methods will be used to write the image.
+ To get a list of the supported formats for writing, use:
+ println(javax.imageio.ImageIO.getReaderFormatNames())
+
+ To use the original built-in image writers, use .tga or .tif as the
+ extension, or don't include an extension. When no extension is used,
+ the extension .tif will be added to the file name.
+
+ The ImageIO API claims to support wbmp files, however they probably
+ require a black and white image. Basic testing produced a zero-length
+ file with no error.
+
Multiply a two element vector against this matrix.
+ If out is null or not length four, a new float array will be returned.
+ The values for vec and out can be the same (though that's less efficient).
+
+In-progress class to handle shape data, currently to be considered of
+ alpha or beta quality. Major structural work may be performed on this class
+ after the release of Processing 1.0. Such changes may include:
+
+
+
addition of proper accessors to read shape vertex and coloring data
+ (this is the second most important part of having a PShape class after all).
+
a means of creating PShape objects ala beginShape() and endShape().
+
load(), update(), and cache methods ala PImage, so that shapes can
+ have renderer-specific optimizations, such as vertex arrays in OpenGL.
+
splitting this class into multiple classes to handle different
+ varieties of shape data (primitives vs collections of vertices vs paths)
+
change of package declaration, for instance moving the code into
+ package processing.shape (if the code grows too much).
+
+
+
For the time being, this class and its shape() and loadShape() friends in
+ PApplet exist as placeholders for more exciting things to come. If you'd
+ like to work with this class, make a subclass (see how PShapeSVG works)
+ and you can play with its internal methods all you like.
+
+
Library developers are encouraged to create PShape objects when loading
+ shape data, so that they can eventually hook into the bounty that will be
+ the PShape interface, and the ease of loadShape() and shape().
findChild(java.lang.String target)
+
+
+ Same as getChild(name), except that it first walks all the way up the
+ hierarchy to the farthest parent, so that children can be found anywhere.
Overrides this shape's style information and uses PGraphics styles and
+ colors. Identical to ignoreStyles(true). Also disables styles for all
+ child shapes.
+
+
+
+
+
+
+
+
+
+
+
+enableStyle
+
+public void enableStyle()
+
+
Re-enables style information (fill and stroke) set in the shape.
+
+
+
+
+
+
+
+
+
+
+
+getWidth
+
+public float getWidth()
+
+
Get the width of the drawing area (not necessarily the shape boundary).
+
+
+
+
+
+
+
+
+
+
+
+getHeight
+
+public float getHeight()
+
+
Get the height of the drawing area (not necessarily the shape boundary).
+
+SVG stands for Scalable Vector Graphics, a portable graphics format. It is
+ a vector format so it allows for infinite resolution and relatively small
+ file sizes. Most modern media software can view SVG files, including Adobe
+ products, Firefox, etc. Illustrator and Inkscape can edit SVG files.
+
+ We have no intention of turning this into a full-featured SVG library.
+ The goal of this project is a basic shape importer that is small enough
+ to be included with applets, meaning that its download size should be
+ in the neighborhood of 25-30k. Starting with release 0149, this library
+ has been incorporated into the core via the loadShape() command, because
+ vector shape data is just as important as the image data from loadImage().
+
+ For more sophisticated import/export, consider the
+ Batik
+ library from the Apache Software Foundation. Future improvements to this
+ library may focus on this properly supporting a specific subset of SVG,
+ for instance the simpler SVG profiles known as
+ SVG Tiny or Basic,
+ although we still would not support the interactivity options.
+
+
+
+ A minimal example program using SVG:
+ (assuming a working moo.svg is in your data folder)
+
+
+
+ This code is based on the Candy library written by Michael Chang, which was
+ later revised and expanded for use as a Processing core library by Ben Fry.
+ Thanks to Ricard Marxer Pinon for help with better Inkscape support in 0154.
+
+
+
+ Late October 2008 revisions from ricardmp, incorporated by fry (0154)
+
Get a particular element based on its SVG ID. When editing SVG by hand,
+ this is the id="" tag on any SVG element. When editing from Illustrator,
+ these IDs can be edited by expanding the layers palette. The names used
+ in the layers palette, both for the layers or the shapes and groups
+ beneath them can be used here.
+
+ // This code grabs "Layer 3" and the shapes beneath it.
+ SVG layer3 = svg.getChild("Layer 3");
+
+Smoothed triangle renderer for P3D.
+
+ Based off of the PPolygon class in old versions of Processing.
+ Name and location of this class will change in a future release.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from interface processing.core.PConstants
Pass camera-space coordinates for the triangle.
+ Needed to render if hint(ENABLE_ACCURATE_TEXTURES) enabled.
+ Generally this will not need to be called manually,
+ currently called from PGraphics3D.render_triangles()
+
Pass camera-space coordinates for the triangle.
+ Needed to render if hint(ENABLE_ACCURATE_TEXTURES) enabled.
+ Generally this will not need to be called manually,
+ currently called from PGraphics3D.render_triangles()
+
Set the power of two used for linear interpolation of texture coordinates.
+ A true texture coordinate is computed every 2^pwr pixels along a scanline.
+
+A class to describe a two or three dimensional vector.
+
+ The result of all functions are applied to the vector itself, with the
+ exception of cross(), which returns a new PVector (or writes to a specified
+ 'target' PVector). That is, add() will add the contents of one vector to
+ this one. Using add() with additional parameters allows you to put the
+ result into a new PVector. Functions that act on multiple vectors also
+ include static versions. Because creating new objects can be computationally
+ expensive, most functions include an optional 'target' PVector, so that a
+ new PVector object is not created with each operation.
+
+ Initially based on the Vector3D class by Dan Shiffman.
+
div(PVector v1,
+ PVector v2)
+
+
+ Multiply each element of one vector by the individual elements of another
+ vector, and return the result as a new PVector.
div(PVector v1,
+ PVector v2,
+ PVector target)
+
+
+ Divide each element of one vector by the individual elements of another
+ vector, and write the result into a target vector.
mult(PVector v1,
+ PVector v2)
+
+
+ Multiply each element of one vector by the individual elements of another
+ vector, and return the result as a new PVector.
mult(PVector v1,
+ PVector v2,
+ PVector target)
+
+
+ Multiply each element of one vector by the individual elements of another
+ vector, and write the result into a target vector.
+
+
+
+ void
+
normalize()
+
+
+ Normalize the vector to length 1 (make it a unit vector)
Calculate the angle between two vectors, using the dot product
+
+
+
Parameters:
v1 - a vector
v2 - another vector
+
Returns:
the angle between the vectors
+
+
+
+
+
+toString
+
+public java.lang.String toString()
+
+
+
Overrides:
toString in class java.lang.Object
+
+
+
+
+
+
+
+
+array
+
+public float[] array()
+
+
Return a representation of this vector as a float array. This is only for
+ temporary use. If used in any other fashion, the contents should be copied
+ by using the get() command to copy into your own array.
+
addAttribute(java.lang.String key,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI,
+ java.lang.String value,
+ java.lang.String type)
+
+
+ This method is called when a new attribute of an XML element is
+ encountered.
+
+
+
+ void
+
addPCData(java.io.Reader reader,
+ java.lang.String systemID,
+ int lineNr)
+
+
+ This method is called when a PCDATA element is encountered.
+
+
+
+ void
+
elementAttributesProcessed(java.lang.String name,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI)
+
+
+ This method is called when the attributes of an XML element have been
+ processed.
+
+
+
+ void
+
endElement(java.lang.String name,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI)
+
+
+ This method is called when the end of an XML elemnt is encountered.
+
+
+
+ java.lang.Object
+
getResult()
+
+
+ Returns the result of the building process.
+
+
+
+ void
+
newProcessingInstruction(java.lang.String target,
+ java.io.Reader reader)
+
+
+ This method is called when a processing instruction is encountered.
+
+
+
+ void
+
startBuilding(java.lang.String systemID,
+ int lineNr)
+
+
+ This method is called before the parser starts processing its input.
+
+
+
+ void
+
startElement(java.lang.String name,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI,
+ java.lang.String systemID,
+ int lineNr)
+
+
+ This method is called when a new XML element is encountered.
This method is called when a new attribute of an XML element is
+ encountered.
+
+
+
Parameters:
key - the key (name) of the attribute.
nsPrefix - the prefix used to identify the namespace. If no
+ namespace has been specified, this parameter is null.
nsURI - the URI associated with the namespace. If no
+ namespace has been specified, or no URI is
+ associated with nsPrefix, this parameter is null.
value - the value of the attribute.
type - the type of the attribute. If no type is known,
+ "CDATA" is returned.
+
Throws:
+
java.lang.Exception - If an exception occurred while processing the event.
+
+
+
+
+
+addPCData
+
+public void addPCData(java.io.Reader reader,
+ java.lang.String systemID,
+ int lineNr)
+
+
This method is called when a PCDATA element is encountered. A Java
+ reader is supplied from which you can read the data. The reader will
+ only read the data of the element. You don't need to check for
+ boundaries. If you don't read the full element, the rest of the data
+ is skipped. You also don't have to care about entities; they are
+ resolved by the parser.
+
+
+
Parameters:
reader - the Java reader from which you can retrieve the data.
systemID - the system ID of the XML data source.
lineNr - the line in the source where the element starts.
+
+
+
+
+
+getResult
+
+public java.lang.Object getResult()
+
+
Returns the result of the building process. This method is called just
+ before the parse method of StdXMLParser returns.
+
Starts a new stream from a Java reader. The new stream is used
+ temporary to read data from. If that stream is exhausted, control
+ returns to the parent stream.
+
+
+
Parameters:
reader - the non-null reader to read the new data from
Starts a new stream from a Java reader. The new stream is used
+ temporary to read data from. If that stream is exhausted, control
+ returns to the parent stream.
+
+
+
Parameters:
reader - the non-null reader to read the new data from
isInternalEntity - true if the reader is produced by resolving
+ an internal entity
+
+
+
+
+
+getStreamLevel
+
+public int getStreamLevel()
+
+
Returns the current "level" of the stream on the stack of streams.
+
+
+
+
+
+
+
+
+getLineNr
+
+public int getLineNr()
+
+
Returns the line number of the data in the current stream.
+
+XMLElement is an XML element. This is the base class used for the
+ Processing XML library, representing a single node of an XML tree.
+
+ This code is based on a modified version of NanoXML by Marc De Scheemaecker.
+
Begin parsing XML data passed in from a PApplet. This code
+ wraps exception handling, for more advanced exception handling,
+ use the constructor that takes a Reader or InputStream.
+
Return the #PCDATA content of the element. If the element has a
+ combination of #PCDATA content and child elements, the #PCDATA
+ sections can be retrieved as unnamed child objects. In this case,
+ this method returns null.
+
+
+
+
+
+
+
Returns:
the content.
+
+
+
+
+
+setContent
+
+public void setContent(java.lang.String content)
+
+
Sets the #PCDATA content. It is an error to call this method with a
+ non-null value if there are child objects.
+
+XMLValidator implementation based on NonValidator (which implemented
+ IXMLValidator in the original NanoXML).
+ This implementation processes the DTD and handles entity definitions.
+ It does not do any validation itself.
+
attributeAdded(java.lang.String key,
+ java.lang.String value,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ Indicates that an attribute has been added to the current element.
+
+
+
+ void
+
elementAttributesProcessed(java.lang.String name,
+ java.util.Properties extraAttributes,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ This method is called when the attributes of an XML element have been
+ processed.
+
+
+
+ void
+
elementEnded(java.lang.String name,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ Indicates that the current element has ended.
+
+
+
+ void
+
elementStarted(java.lang.String name,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ Indicates that an element has been started.
This method is called when the attributes of an XML element have been
+ processed.
+ If there are attributes with a default value which have not been
+ specified yet, they have to be put into extraAttributes.
+
+
+
Parameters:
name - the name of the element.
extraAttributes - where to put extra attributes.
systemId - the system ID of the XML data of the element.
lineNr - the line number in the XML data of the element.
The PGraphics renderer associated with this PApplet
+
+
+
+
+
+
+frame
+
+java.awt.Frame frame
+
+
The frame containing this applet (if any)
+
+
+
+
+
+
+screen
+
+java.awt.Dimension screen
+
+
The screen size when the applet was started.
+
+ Access this via screen.width and screen.height. To make an applet
+ run at full screen, use size(screen.width, screen.height).
+
+ If you have multiple displays, this will be the size of the main
+ display. Running full screen across multiple displays isn't
+ particularly supported, and requires more monkeying with the values.
+ This probably can't/won't be fixed until/unless I get a dual head
+ system.
+
+ Note that this won't update if you change the resolution
+ of your screen once the the applet is running.
+
+ This variable is not static, because future releases need to be better
+ at handling multiple displays.
+
A leech graphics object that is echoing all events.
+
+
+
+
+
+
+args
+
+java.lang.String[] args
+
+
Command line options passed in from main().
+
+ This does not include the arguments passed in to PApplet itself.
+
+
+
+
+
+
+sketchPath
+
+java.lang.String sketchPath
+
+
Path to sketch folder
+
+
+
+
+
+
+defaultSize
+
+boolean defaultSize
+
+
true if no size() command has been executed. This is used to wait until
+ a size has been set before placing in the window and showing it.
+
+
+
+
+
+
+resizeRequest
+
+boolean resizeRequest
+
+
+
+
+
+
+resizeWidth
+
+int resizeWidth
+
+
+
+
+
+
+resizeHeight
+
+int resizeHeight
+
+
+
+
+
+
+pixels
+
+int[] pixels
+
+
Pixel buffer from this applet's PGraphics.
+
+ When used with OpenGL or Java2D, this value will
+ be null until loadPixels() has been called.
+
+
+
+
+
+
+width
+
+int width
+
+
width of this applet's associated PGraphics
+
+
+
+
+
+
+height
+
+int height
+
+
height of this applet's associated PGraphics
+
+
+
+
+
+
+mouseX
+
+int mouseX
+
+
current x position of the mouse
+
+
+
+
+
+
+mouseY
+
+int mouseY
+
+
current y position of the mouse
+
+
+
+
+
+
+pmouseX
+
+int pmouseX
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+pmouseY
+
+int pmouseY
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+dmouseX
+
+int dmouseX
+
+
previous mouseX/Y for the draw loop, separated out because this is
+ separate from the pmouseX/Y when inside the mouse event handlers.
+
+
+
+
+
+
+dmouseY
+
+int dmouseY
+
+
previous mouseX/Y for the draw loop, separated out because this is
+ separate from the pmouseX/Y when inside the mouse event handlers.
+
+
+
+
+
+
+emouseX
+
+int emouseX
+
+
pmouseX/Y for the event handlers (mousePressed(), mouseDragged() etc)
+ these are different because mouse events are queued to the end of
+ draw, so the previous position has to be updated on each event,
+ as opposed to the pmouseX/Y that's used inside draw, which is expected
+ to be updated once per trip through draw().
+
+
+
+
+
+
+emouseY
+
+int emouseY
+
+
pmouseX/Y for the event handlers (mousePressed(), mouseDragged() etc)
+ these are different because mouse events are queued to the end of
+ draw, so the previous position has to be updated on each event,
+ as opposed to the pmouseX/Y that's used inside draw, which is expected
+ to be updated once per trip through draw().
+
+
+
+
+
+
+firstMouse
+
+boolean firstMouse
+
+
Used to set pmouseX/Y to mouseX/Y the first time mouseX/Y are used,
+ otherwise pmouseX/Y are always zero, causing a nasty jump.
+
+ Just using (frameCount == 0) won't work since mouseXxxxx()
+ may not be called until a couple frames into things.
+
+
+
+
+
+
+mouseButton
+
+int mouseButton
+
+
Last mouse button pressed, one of LEFT, CENTER, or RIGHT.
+
+ If running on Mac OS, a ctrl-click will be interpreted as
+ the righthand mouse button (unlike Java, which reports it as
+ the left mouse).
+
+
+
+
+
+
+mousePressed
+
+boolean mousePressed
+
+
+
+
+
+
+mouseEvent
+
+java.awt.event.MouseEvent mouseEvent
+
+
+
+
+
+
+key
+
+char key
+
+
Last key pressed.
+
+ If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT,
+ this will be set to CODED (0xffff or 65535).
+
+
+
+
+
+
+keyCode
+
+int keyCode
+
+
When "key" is set to CODED, this will contain a Java key code.
+
+ For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT.
+ Also available are ALT, CONTROL and SHIFT. A full set of constants
+ can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables.
+
+
+
+
+
+
+keyPressed
+
+boolean keyPressed
+
+
true if the mouse is currently pressed.
+
+
+
+
+
+
+keyEvent
+
+java.awt.event.KeyEvent keyEvent
+
+
the last KeyEvent object passed into a mouse function.
+
+
+
+
+
+
+focused
+
+boolean focused
+
+
Gets set to true/false as the applet gains/loses focus.
+
+
+
+
+
+
+online
+
+boolean online
+
+
true if the applet is online.
+
+ This can be used to test how the applet should behave
+ since online situations are different (no file writing, etc).
+
+
+
+
+
+
+millisOffset
+
+long millisOffset
+
+
Time in milliseconds when the applet was started.
+
+ Used by the millis() function.
+
+
+
+
+
+
+frameRate
+
+float frameRate
+
+
The current value of frames per second.
+
+ The initial value will be 10 fps, and will be updated with each
+ frame thereafter. The value is not instantaneous (since that
+ wouldn't be very useful since it would jump around so much),
+ but is instead averaged (integrated) over several frames.
+ As such, this value won't be valid until after 5-10 frames.
+
+
+
+
+
+
+frameRateLastNanos
+
+long frameRateLastNanos
+
+
Last time in nanoseconds that frameRate was checked
+
+
+
+
+
+
+frameRateTarget
+
+float frameRateTarget
+
+
As of release 0116, frameRate(60) is called as a default
+
+
+
+
+
+
+frameRatePeriod
+
+long frameRatePeriod
+
+
+
+
+
+
+looping
+
+boolean looping
+
+
+
+
+
+
+redraw
+
+boolean redraw
+
+
flag set to true when a redraw is asked for by the user
+
+
+
+
+
+
+frameCount
+
+int frameCount
+
+
How many frames have been displayed since the applet started.
+
+ This value is read-only do not attempt to set it,
+ otherwise bad things will happen.
+
+ Inside setup(), frameCount is 0.
+ For the first iteration of draw(), frameCount will equal 1.
+
+
+
+
+
+
+finished
+
+boolean finished
+
+
true if this applet has had it.
+
+
+
+
+
+
+exitCalled
+
+boolean exitCalled
+
+
true if exit() has been called so that things shut down
+ once the main thread kicks off.
+
By trial and error, four image loading threads seem to work best when
+ loading images from online. This is consistent with the number of open
+ connections that web browsers will maintain. The variable is made public
+ (however no accessor has been added since it's esoteric) if you really
+ want to have control over the value used. For instance, when loading local
+ files, it might be better to only have a single thread (or two) loading
+ images so that you're disk isn't simply jumping around.
+
+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
+
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.
+
+
+
+
+
+
Parameters:
tokenType - integer representing the token type to copied
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.
+
+
+
Specified by:
nextToken in interface antlr.TokenStream
Overrides:
nextToken in class antlr.TokenStreamHiddenTokenFilter
+ Run 'java Main [-showtree] directory-full-of-java-files'
+
+ [The -showtree option pops up a Swing frame that shows
+ the AST constructed from the parser.]
+
+ Run 'java Main '
+
+ Contributing authors:
+ John Mitchell johnm@non.net
+ Terence Parr parrt@magelang.com
+ John Lilley jlilley@empathy.com
+ Scott Stanchfield thetick@magelang.com
+ Markus Mohnen mohnen@informatik.rwth-aachen.de
+ Peter Williams pete.williams@sun.com
+ Allan Jacobs Allan.Jacobs@eng.sun.com
+ Steve Messick messick@redhills.com
+ John Pybus john@pybus.org
+
+ Version 1.00 December 9, 1997 -- initial release
+ Version 1.01 December 10, 1997
+ fixed bug in octal def (0..7 not 0..8)
+ Version 1.10 August 1998 (parrt)
+ added tree construction
+ fixed definition of WS,comments for mac,pc,unix newlines
+ added unary plus
+ Version 1.11 (Nov 20, 1998)
+ Added "shutup" option to turn off last ambig warning.
+ Fixed inner class def to allow named class defs as statements
+ synchronized requires compound not simple statement
+ add [] after builtInType DOT class in primaryExpression
+ "const" is reserved but not valid..removed from modifiers
+ Version 1.12 (Feb 2, 1999)
+ Changed LITERAL_xxx to xxx in tree grammar.
+ Updated java.g to use tokens {...} now for 2.6.0 (new feature).
+
+ Version 1.13 (Apr 23, 1999)
+ Didn't have (stat)? for else clause in tree parser.
+ Didn't gen ASTs for interface extends. Updated tree parser too.
+ Updated to 2.6.0.
+ Version 1.14 (Jun 20, 1999)
+ Allowed final/abstract on local classes.
+ Removed local interfaces from methods
+ Put instanceof precedence where it belongs...in relationalExpr
+ It also had expr not type as arg; fixed it.
+ Missing ! on SEMI in classBlock
+ fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
+ fixed: didn't like Object[].class in parser or tree parser
+ Version 1.15 (Jun 26, 1999)
+ Screwed up rule with instanceof in it. :( Fixed.
+ Tree parser didn't like (expr).something; fixed.
+ Allowed multiple inheritance in tree grammar. oops.
+ Version 1.16 (August 22, 1999)
+ Extending an interface built a wacky tree: had extra EXTENDS.
+ Tree grammar didn't allow multiple superinterfaces.
+ Tree grammar didn't allow empty var initializer: {}
+ Version 1.17 (October 12, 1999)
+ ESC lexer rule allowed 399 max not 377 max.
+ java.tree.g didn't handle the expression of synchronized
+ statements.
+ Version 1.18 (August 12, 2001)
+ Terence updated to Java 2 Version 1.3 by
+ observing/combining work of Allan Jacobs and Steve
+ Messick. Handles 1.3 src. Summary:
+ o primary didn't include boolean.class kind of thing
+ o constructor calls parsed explicitly now:
+ see explicitConstructorInvocation
+ o add strictfp modifier
+ o missing objBlock after new expression in tree grammar
+ o merged local class definition alternatives, moved after declaration
+ o fixed problem with ClassName.super.field
+ o reordered some alternatives to make things more efficient
+ o long and double constants were not differentiated from int/float
+ o whitespace rule was inefficient: matched only one char
+ o add an examples directory with some nasty 1.3 cases
+ o made Main.java use buffered IO and a Reader for Unicode support
+ o supports UNICODE?
+ Using Unicode charVocabulay makes code file big, but only
+ in the bitsets at the end. I need to make ANTLR generate
+ unicode bitsets more efficiently.
+ Version 1.19 (April 25, 2002)
+ Terence added in nice fixes by John Pybus concerning floating
+ constants and problems with super() calls. John did a nice
+ reorg of the primary/postfix expression stuff to read better
+ and makes f.g.super() parse properly (it was METHOD_CALL not
+ a SUPER_CTOR_CALL). Also:
+
+ o "finally" clause was a root...made it a child of "try"
+ o Added stuff for asserts too for Java 1.4, but *commented out*
+ as it is not backward compatible.
+
+ Version 1.20 (October 27, 2002)
+
+ Terence ended up reorging John Pybus' stuff to
+ remove some nondeterminisms and some syntactic predicates.
+ Note that the grammar is stricter now; e.g., this(...) must
+ be the first statement.
+
+ Trinary ?: operator wasn't working as array name:
+ (isBig ? bigDigits : digits)[i];
+
+ Checked parser/tree parser on source for
+ Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4,
+ and the 110k-line jGuru server source.
+
+ This grammar is in the PUBLIC DOMAIN
+
declaration()
+
+
+ A declaration is the creation of a reference or primitive-type variable
+ Create a separate Type/Var tree for each var in the var list.
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 API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+Overview
+
+
+
+The Overview 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.
+
+Package
+
+
+
+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:
+
Interfaces (italic)
Classes
Enums
Exceptions
Errors
Annotation Types
+
+
+Class/Interface
+
+
+
+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:
+
Class inheritance diagram
Direct Subclasses
All Known Subinterfaces
All Known Implementing Classes
Class/interface declaration
Class/interface description
+
+
Nested Class Summary
Field Summary
Constructor Summary
Method Summary
+
+
Field Detail
Constructor Detail
Method Detail
+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.
+
+
+Annotation Type
+
+
+
+Each annotation type has its own separate page with the following sections:
+
Annotation Type declaration
Annotation Type description
Required Element Summary
Optional Element Summary
Element Detail
+
+
+
+Enum
+
+
+
+Each enum has its own separate page with the following sections:
+
Enum declaration
Enum description
Enum Constant Summary
Enum Constant Detail
+
+
+Tree (Class Hierarchy)
+
+There is a Class Hierarchy 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 java.lang.Object. The interfaces do not inherit from java.lang.Object.
+
When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
+
+
+Deprecated API
+
+The Deprecated API 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.
+
+Index
+
+The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
+
+Prev/Next
+These links take you to the next or previous class, interface, package, or related page.
+Frames/No Frames
+These links show and hide the HTML frames. All pages are available with or without frames.
+
+
+Serialized Form
+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.
+
If 'name' is null or the empty string, it won't set a specific
+ device, which means that QuickTime will use that last device
+ used by a QuickTime application.
+
Create a .vlw font on the fly from either a font name that's
+ installed on the system, or from a .ttf or .otf that's inside
+ the data folder of this sketch.
+
Preferred method of creating new PImage objects, ensures that a
+ reference to the parent PApplet is included, which makes save() work
+ without needing an absolute path.
+
Called by the browser or applet viewer to inform this applet
+ that it is being reclaimed and that it should destroy
+ any resources that it has allocated.
+
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)
+
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).
+
Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
+ 'keyCode', and 'keyEvent' variables to no longer work;
+ key events will no longer be queued until the end of draw();
+ and the keyPressed(), keyReleased() and keyTyped() methods
+ will no longer be called.
+
If you override this or any function that takes a "MouseEvent e"
+ without calling its super.mouseXxxx() then mouseX, mouseY,
+ mousePressed, and mouseEvent will no longer be set.
+
number format signed (or space)
+ Formats a number but leaves a blank space in the front
+ when it's positive so that it can be properly aligned with
+ numbers that have a negative sign in front of them.
+
Implements the cross-platform headache of opening URLs
+ TODO This code should be replaced by PApplet.link(),
+ however that's not a static method (because it requires
+ an AppletContext when used as an applet), so it's mildly
+ trickier than just removing this method.
+
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.
+
Recursively remove all files within a directory,
+ used with removeDir(), or when the contents of a dir
+ should be removed, but not the directory itself.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
If this client property is set to Boolean.TRUE on the text area,
+ the home/end keys will support 'smart' BRIEF-like behaviour
+ (one press = start/end of line, two presses = start/end of
+ viewscreen, three presses = start/end of document).
+
Sets the text rendering/placement to be either SCREEN (direct
+ to the screen, exact coordinates, only use the font's original size)
+ or MODEL (the default, where text is manipulated by translate() and
+ can have a textSize).
+
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 document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+
+Link toNon-frame version.
+
+The base class for the main processing application.
+ Primary role of this class is for platform identification and
+ general interaction with the system (launching URLs, loading
+ files and images, etc) that comes from that.
+
countLines(java.lang.String what)
+
+
+ Get the number of lines in a file by counting the number of newline
+ characters inside a String (and adding 1).
+
+
+
+static java.io.File
+
createTempFolder(java.lang.String name)
+
+
+ Get the path to the platform's temporary folder, by creating
+ a temporary temporary file and getting its parent folder.
listFiles(java.lang.String path,
+ boolean relative)
+
+
+ Recursively creates a list of all files within the specified folder,
+ and returns a list of their relative paths.
+
+
+
+static byte[]
+
loadBytesRaw(java.io.File file)
+
+
+ Same as PApplet.loadBytes(), however never does gzip decoding.
+
+
+
+static java.lang.String
+
loadFile(java.io.File file)
+
+
+ Grab the contents of a file as a string.
openFolder(java.io.File file)
+
+
+ Implements the other cross-platform headache of opening
+ a folder in the machine's native file browser.
+
+
+
+static void
+
openURL(java.lang.String url)
+
+
+ Implements the cross-platform headache of opening URLs
+ TODO This code should be replaced by PApplet.link(),
+ however that's not a static method (because it requires
+ an AppletContext when used as an applet), so it's mildly
+ trickier than just removing this method.
registerWindowCloseKeys(javax.swing.JRootPane root,
+ java.awt.event.ActionListener disposer)
+
+
+ Registers key events for a Ctrl-W and ESC with an ActionListener
+ that will take care of disposing the window.
+
+
+
+static void
+
removeDescendants(java.io.File dir)
+
+
+ Recursively remove all files within a directory,
+ used with removeDir(), or when the contents of a dir
+ should be removed, but not the directory itself.
+
+
+
+static void
+
removeDir(java.io.File dir)
+
+
+ Remove all files in a directory and the directory itself.
+
+
+
+static void
+
saveFile(java.lang.String str,
+ java.io.File file)
+
+
+ Spew the contents of a String object out to a file.
+
+
+
+static java.io.File
+
selectFolder(java.lang.String prompt,
+ java.io.File folder,
+ java.awt.Frame frame)
+
+
+ Prompt for a fodler and return it as a File object (or null).
+
+
+
+static void
+
setIcon(java.awt.Frame frame)
+
+
+ Give this Frame a Processing icon.
Convenience method to get a File object for the specified filename inside
+ the settings folder.
+ For now, only used by Preferences to get the preferences.txt file.
+
+
+
Parameters:
filename - A file inside the settings folder.
+
Returns:
filename wrapped as a File object inside the settings folder
Get the path to the platform's temporary folder, by creating
+ a temporary temporary file and getting its parent folder.
+
+ Modified for revision 0094 to actually make the folder randomized
+ to avoid conflicts in multi-user environments. (Bug 177)
+
Implements the cross-platform headache of opening URLs
+ TODO This code should be replaced by PApplet.link(),
+ however that's not a static method (because it requires
+ an AppletContext when used as an applet), so it's mildly
+ trickier than just removing this method.
+
+
+
+
+
+
+
+
+openFolder
+
+public static void openFolder(java.io.File file)
+
+
Implements the other cross-platform headache of opening
+ a folder in the machine's native file browser.
+
Prompt for a fodler and return it as a File object (or null).
+ Implementation for choosing directories that handles both the
+ Mac OS X hack to allow the native AWT file dialog, or uses
+ the JFileChooser on other platforms. Mac AWT trick obtained from
+ this post
+ on the OS X Java dev archive which explains the cryptic note in
+ Apple's Java 1.4 release docs about the special System property.
+
Show an error message that's actually fatal to the program.
+ This is an error that can't be recovered. Use showWarning()
+ for errors that allow P5 to continue running.
+
Copy a folder from one place to another. This ignores all dot files and
+ folders found in the source directory, to avoid copying silly .DS_Store
+ files and potentially troublesome .svn folders.
+
+
+
+
Throws:
+
java.io.IOException
+
+
+
+
+
+removeDir
+
+public static void removeDir(java.io.File dir)
+
+
Remove all files in a directory and the directory itself.
+
Recursively remove all files within a directory,
+ used with removeDir(), or when the contents of a dir
+ should be removed, but not the directory itself.
+ (i.e. when cleaning temp files from lib/build)
+
+
+
+
+
+
+
+
+calcFolderSize
+
+public static int calcFolderSize(java.io.File folder)
+
+
Calculate the size of the contents of a folder.
+ Used to determine whether sketches are empty or not.
+ Note that the function calls itself recursively.
+
Recursively creates a list of all files within the specified folder,
+ and returns a list of their relative paths.
+ Ignores any files/folders prefixed with a dot.
+
+Class to handle running Processing from the command line.
+
+ --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).
+
+
+ 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.
+
newJMenuItem(java.lang.String title,
+ int what)
+
+
+ A software engineer, somewhere, needs to have his abstraction
+ taken away.
+
+
+
+static javax.swing.JMenuItem
+
newJMenuItemAlt(java.lang.String title,
+ int what)
+
+
+ Same as newJMenuItem(), but adds the ALT (on Linux and Windows)
+ or OPTION (on Mac OS X) key as a modifier.
+
+
+
+static javax.swing.JMenuItem
+
newJMenuItemShift(java.lang.String title,
+ int what)
+
+
+ Like newJMenuItem() but adds shift as a modifier for the key command.
+
+
+
+ void
+
setLineText(int line,
+ java.lang.String what)
+
+
+ Replace the text on a specified line.
Hack for #@#)$(* Mac OS X 10.2.
+
+ This appears to only be required on OS X 10.2, and is not
+ even being called on later versions of OS X or Windows.
+
+
+
Overrides:
getMinimumSize in class java.awt.Container
+
+
+
+
+
+
+
+
+newJMenuItem
+
+public static javax.swing.JMenuItem newJMenuItem(java.lang.String title,
+ int what)
+
+
A software engineer, somewhere, needs to have his abstraction
+ taken away. In some countries they jail or beat people for writing
+ the sort of API that would require a five line helper function
+ just to set the command key for a menu item.
+
+
+
+
+
+
+
+
+
+
+
+newJMenuItemShift
+
+public static javax.swing.JMenuItem newJMenuItemShift(java.lang.String title,
+ int what)
+
+
Like newJMenuItem() but adds shift as a modifier for the key command.
+
+
+
+
+
+
+
+
+
+
+
+newJMenuItemAlt
+
+public static javax.swing.JMenuItem newJMenuItemAlt(java.lang.String title,
+ int what)
+
+
Same as newJMenuItem(), but adds the ALT (on Linux and Windows)
+ or OPTION (on Mac OS X) key as a modifier.
+
Get the JEditTextArea object for use (not recommended). This should only
+ be used in obscure cases that really need to hack the internals of the
+ JEditTextArea. Most tools should only interface via the get/set functions
+ found in this class. This will maintain compatibility with future releases,
+ which will not use JEditTextArea.
+
+
+
+
+
+
+
+
+
+
+
+getText
+
+public java.lang.String getText()
+
+
Get the contents of the current buffer. Used by the Sketch class.
+
+
+
+
+
+
+
+
+
+
+
+getText
+
+public java.lang.String getText(int start,
+ int stop)
+
+
Get a range of text from the current buffer.
+
+
+
+
+
+
+
+
+
+
+
+setText
+
+public void setText(java.lang.String what)
+
+
Replace the entire contents of the front-most tab.
+
+
+
+
+
+
+
+
+
+
+
+insertText
+
+public void insertText(java.lang.String what)
+
+
+
+
+
+
+
+
+
+
+
+getSelectedText
+
+public java.lang.String getSelectedText()
+
+
Called to update the text but not switch to a different set of code
+ (which would affect the undo manager).
+
Get the position (character offset) of the caret. With text selected,
+ this will be the last character actually selected, no matter the direction
+ of the selection. That is, if the user clicks and drags to select lines
+ 7 up to 4, then the caret position will be somewhere on line four.
+
+
+
+
+
+
+
+
+
+
+
+isSelectionActive
+
+public boolean isSelectionActive()
+
+
True if some text is currently selected.
+
+
+
+
+
+
+
+
+
+
+
+getSelectionStart
+
+public int getSelectionStart()
+
+
Get the beginning point of the current selection.
+
Get character offset for the start of a given line of text.
+
+
+
+
+
+
+
+
+
+
+
+getLineStopOffset
+
+public int getLineStopOffset(int line)
+
+
Get character offset for end of a given line of text.
+
+
+
+
+
+
+
+
+
+
+
+getLineCount
+
+public int getLineCount()
+
+
Get the number of lines in the currently displayed buffer.
+
+
+
+
+
+
+
+
+
+
+
+startCompoundEdit
+
+public void startCompoundEdit()
+
+
Use before a manipulating text to group editing operations together as a
+ single undo. Use stopCompoundEdit() once finished.
+
+
+
+
+
+
+
+
+
+
+
+stopCompoundEdit
+
+public void stopCompoundEdit()
+
+
Use with startCompoundEdit() to group edit operations in a single undo.
+
+
+
+
+
+
+
+
+
+
+
+getScrollPosition
+
+public int getScrollPosition()
+
+
+
+
+
+
+
+
+
+
+
+handleCut
+
+public void handleCut()
+
+
Implements Edit → Cut.
+
+
+
+
+
+
+
+
+
+
+
+handleCopy
+
+public void handleCopy()
+
+
Implements Edit → Copy.
+
+
+
+
+
+
+
+
+
+
+
+handlePaste
+
+public void handlePaste()
+
+
Implements Edit → Paste.
+
+
+
+
+
+
+
+
+
+
+
+handleSelectAll
+
+public void handleSelectAll()
+
+
Implements Edit → Select All.
+
+
+
+
+
+
+
+
+
+
+
+handleRun
+
+public void handleRun(boolean present)
+
+
Implements Sketch → Run.
+
+
+
+
+
+
Parameters:
present - Set true to run in full screen (present mode).
+
+
+
+
+
+setSketchLocation
+
+public void setSketchLocation(java.awt.Point p)
+
+
Set the location of the sketch run window. Used by Runner to update the
+ Editor about window drag events while the sketch is running.
+
+
+
+
+
+
+
+
+
+
+
+getSketchLocation
+
+public java.awt.Point getSketchLocation()
+
+
Get the last location of the sketch's run window. Used by Runner to make
+ the window show up in the same location as when it was last closed.
+
+
+
+
+
+
+
+
+
+
+
+handleStop
+
+public void handleStop()
+
+
Implements Sketch → Stop, or pressing Stop on the toolbar.
+
+
+
+
+
+
+
+
+
+
+
+internalRunnerClosed
+
+public void internalRunnerClosed()
+
+
Called by Runner to notify that the sketch has stopped running.
+ Tools should not call this function, use handleStop() instead.
+
+
+
+
+
+
+
+
+
+
+
+internalCloseRunner
+
+public void internalCloseRunner()
+
+
Handle internal shutdown of the runner.
+
+
+
+
+
+
+
+
+
+
+
+handleSave
+
+public boolean handleSave(boolean immediately)
+
+
Actually handle the save command. If 'immediately' is set to false,
+ this will happen in another thread so that the message area
+ will update and the save button will stay highlighted while the
+ save is happening. If 'immediately' is true, then it will happen
+ immediately. This is used during a quit, because invokeLater()
+ won't run properly while a quit is happening. This fixes
+ Bug 276.
+
+
+
+
+
+
+
+
+
+
+
+handleSaveAs
+
+public boolean handleSaveAs()
+
+
+
+
+
+
+
+
+
+
+
+handleExport
+
+public void handleExport()
+
+
Called by Sketch → Export.
+ Handles calling the export() function on sketch, and
+ queues all the gui status stuff that comes along with it.
+
+ Made synchronized to (hopefully) avoid problems of people
+ hitting export twice, quickly, and horking things up.
+
+Message console that sits below the editing area.
+
+ 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.
+
Close the streams so that the temporary files can be deleted.
+
+ 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.
+
+
+
+
+
+
+
+
+write
+
+public void write(byte[] b,
+ int offset,
+ int length,
+ boolean err)
+Filters key events for tab expansion/indent/etc.
+
+ 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.
+
Intercepts key pressed events for JEditTextArea.
+
+ Called by JEditTextArea inside processKeyEvent(). Note that this
+ won't intercept actual characters, because those are fired on
+ keyTyped().
+
+
+
+
Returns:
true if the event has been handled (to remove it from the queue)
+Find & Replace window for the Processing editor.
+
+ 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
+ Bug 244
+ should anyone have clues about how to fix.
+
+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.)
+
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.
+
+Storage class for user preferences and environment settings.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ Would also be possible to change this to use the Java Preferences API.
+ Some useful articles
+ here and
+ here.
+ 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.
+
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.
+
+
+
+
+
+
+
+BUTTON_HEIGHT
+
+public static int BUTTON_HEIGHT
+
+
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.
+
+Stores information about files in the current sketch
+
+
+
+
+
+
+
+
+
+
+
+
+
+Constructor Summary
+
+
+
Sketch(Editor editor,
+ java.lang.String path)
+
+
+ path is location of the main .pde file, because this is also
+ simplest to use when opening the file from the finder/explorer.
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ boolean
+
addFile(java.io.File sourceFile)
+
+
+ Add a file to the sketch.
+
+
+
+ java.lang.String
+
build(java.lang.String buildPath)
+
+
+ Preprocess and compile all the code for this sketch.
+
+
+
+static java.lang.String
+
checkName(java.lang.String origName)
+
+
+ Convert to sanitized name and alert the user
+ if changes were made.
+
+
+
+ boolean
+
exportApplet(java.lang.String appletPath)
+
+
+ Handle export to applet.
+
+
+
+ boolean
+
exportApplication(java.lang.String destPath,
+ int exportPlatform)
+
+
+ Export to application without GUI.
Prompt the user for a new file to the sketch, then call the
+ other addFile() function to actually add it.
+
+
+
+
+
+
+
+
+addFile
+
+public boolean addFile(java.io.File sourceFile)
+
+
Add a file to the sketch.
+
+ .pde or .java files will be added to the sketch folder.
+ .jar, .class, .dll, .jnilib, and .so files will all
+ be added to the "code" folder.
+ All other files will be added to the "data" folder.
+
+ If they don't exist already, the "code" or "data" folder
+ will be created.
+
+
Build all the code for this sketch.
+
+ In an advanced program, the returned class name could be different,
+ which is why the className is set based on the return value.
+ A compilation error will burp up a RunnerException.
+
+ Setting purty to 'true' will cause exception line numbers to be incorrect.
+ Unless you know the code compiles, you should first run the preprocessor
+ with purty set to false to make sure there are no errors, then once
+ successful, re-export with purty set to true.
+
+
+
Parameters:
buildPath - Location to copy all the .java files
+
Returns:
null if compilation failed, main class name if not
+
Preprocess and compile all the code for this sketch.
+
+ In an advanced program, the returned class name could be different,
+ which is why the className is set based on the return value.
+ A compilation error will burp up a RunnerException.
+
+
+
+
Returns:
null if compilation failed, main class name if not
+
Returns true if this is a read-only sketch. Used for the
+ examples directory, or when sketches are loaded from read-only
+ volumes or folders without appropriate permissions.
+
Produce a sanitized name that fits our standards for likely to work.
+
+ Java classes have a wider range of names that are technically allowed
+ (supposedly any Unicode name) than what we support. The reason for
+ going more narrow is to avoid situations with text encodings and
+ converting during the process of moving files between operating
+ systems, i.e. uploading from a Windows machine to a Linux server,
+ or reading a FAT32 partition in OS X and using a thumb drive.
+
+ This helper function replaces everything but A-Z, a-z, and 0-9 with
+ underscores. Also disallows starting the sketch name with a digit.
+
+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.
+
+Threaded class to check for updates in the background.
+
+ 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.
+
+ 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.
+
contentsToClassPath(java.io.File folder)
+
+
+ Given a folder, return a list of absolute paths to all jar or zip files
+ inside that folder, separated by pathSeparatorChar.
+
+
+
+static java.lang.String[]
+
packageListFromClassPath(java.lang.String path)
+
+
+ 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.
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.
+
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.
+
+Interface for dealing with parser/compiler output.
+
+ 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.
+
+ Classes which consume messages and do something with them
+ should implement this interface.
+
+Runs a compiled sketch. As of release 0136, all sketches are run externally
+ to the environment so that a debugging interface can be used. This opens up
+ future options for a decent debugger, but in the meantime fixes several
+ problems with output and error streams, messages getting lost on Mac OS X,
+ the run/stop buttons not working, libraries not shutting down, exceptions
+ not coming through, exceptions being printed twice, having to force quit
+ if you make a bad while() loop, and so on.
+
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.
+
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.
+
+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.
+
+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.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from interface processing.app.preproc.PdeTokenTypes
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.
+
+Class that orchestrates preprocessing p5 syntax into straight Java.
+
+ Current Preprocessor Subsitutions:
+
+
any function not specified as being protected or private will
+ be made 'public'. this means that void setup() becomes
+ public void setup(). This is important to note when
+ coding with core.jar outside of the PDE.
+
compiler.substitute_floats (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.
+
compiler.enhanced_casting 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.
+
compiler.color_datatype '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.
+
compiler.web_colors (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.
+
+ Other preprocessor functionality
+
+
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/
+
+
+ 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.
+
+ Here's some info about the various files in this directory:
+
+ java.g: 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().
+
+ java.tree.g: 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.
+
+ pde.g: 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.
+ PdeEmitter.java: 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 ,
+ who has given permission for it to be distributed under the GPL.
+
+ ExtendedCommonASTWithHiddenTokens.java: 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.
+
+ TokenStreamCopyingHiddenTokenFilter.java: 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.
+
+ whitespace_test.pde: 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.
+
+ 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.
+
+
An abstract method that splits a line up into tokens. It
+ should parse the line, and call addToken() to
+ add syntax tokens to the token list. Then, it should return
+ the initial token type for the next line.
+
+ 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.
+
+
+
+
+
+
Parameters:
token - The initial token type for this line
line - The line to be tokenized
lineIndex - The index of the line in the document,
+ starting at 0
+
Adds a key binding to this input handler. The key binding is
+ a list of white space separated key strokes of the form
+ [modifiers+]key 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)
+
Converts a string to a keystroke. The string should be of the
+ form modifiers+shortcut where modifiers
+ is any combination of A for Alt, C for Control, S for Shift
+ or M for Meta, and shortcut is either a single character,
+ or a keycode name from the KeyEvent class, without
+ the VK_ prefix.
+
+
+
Parameters:
keyStroke - A string description of the key stroke
+An input handler converts the user's key strokes into concrete actions.
+ It also takes care of macro recording and action repetition.
+
+ This class provides all the necessary support code for an input
+ handler, but doesn't actually do any key binding logic. It is up
+ to the implementations of this class to do so.
+
SMART_HOME_END_PROPERTY
+
+
+ If this client property is set to Boolean.TRUE on the text area,
+ the home/end keys will support 'smart' BRIEF-like behaviour
+ (one press = start/end of line, two presses = start/end of
+ viewscreen, three presses = start/end of document).
getTextArea(java.util.EventObject evt)
+
+
+ Returns the text area that fired the specified event.
+
+
+
+ void
+
grabNextKeyStroke(java.awt.event.ActionListener listener)
+
+
+ Grabs the next key typed event and invokes the specified
+ action with the key as a the action command.
+public static final java.lang.String SMART_HOME_END_PROPERTY
+
+
If this client property is set to Boolean.TRUE on the text area,
+ the home/end keys will support 'smart' BRIEF-like behaviour
+ (one press = start/end of line, two presses = start/end of
+ viewscreen, three presses = start/end of document). By default,
+ this property is not set.
+
Returns the name of the specified text area action.
+
+
+
Parameters:
listener - The action
+
+
+
+
+
+getActions
+
+public static java.util.Enumeration getActions()
+
+
Returns an enumeration of all available actions.
+
+
+
+
+
+
+
+
+addDefaultKeyBindings
+
+public abstract void addDefaultKeyBindings()
+
+
Adds the default key bindings to this input handler.
+ This should not be called in the constructor of this
+ input handler, because applications might load the
+ key bindings from a file, etc.
+
Grabs the next key typed event and invokes the specified
+ action with the key as a the action command.
+
+
+
+
+
+
+
+
+isRepeatEnabled
+
+public boolean isRepeatEnabled()
+
+
Returns if repeating is enabled. When repeating is enabled,
+ actions will be executed multiple times. This is usually
+ invoked with a special key stroke in the input handler.
+
+
+
+
+
+
+
+
+setRepeatEnabled
+
+public void setRepeatEnabled(boolean repeat)
+
+
Enables repeating. When repeating is enabled, actions will be
+ executed multiple times. Once repeating is enabled, the input
+ handler should read a number from the keyboard.
+
+
+
+
+
+
+
+
+getRepeatCount
+
+public int getRepeatCount()
+
+
Returns the number of times the next action will be repeated.
+
+
+
+
+
+
+
+
+setRepeatCount
+
+public void setRepeatCount(int repeatCount)
+
+
Sets the number of times the next action will be repeated.
+
+jEdit's text area component. It is more suited for editing program
+ source code than JEditorPane, because it drops the unnecessary features
+ (images, variable-width lines, and so on) and adds a whole bunch of
+ useful goodies such as:
+
+
More flexible key binding scheme
+
Supports macro recorders
+
Rectangular selection
+
Bracket highlighting
+
Syntax highlighting
+
Command repetition
+
Block caret can be enabled
+
+ It is also faster and doesn't have as many problems. It can be used
+ in other applications; the only other part of jEdit it depends on is
+ the syntax package.
+
+ To use it in your app, treat it like any other component, for example:
+
JEditTextArea ta = new JEditTextArea();
+ ta.setTokenMarker(new JavaTokenMarker());
+ ta.setText("public class Test {\n"
+ + " public static void main(String[] args) {\n"
+ + " System.out.println(\"Hello World\");\n"
+ + " }\n"
+ + "}");
isSelectionRectangular()
+
+
+ Returns true if the selection is rectangular, false otherwise.
+
+
+
+ int
+
lineToY(int line)
+
+
+ Converts a line index to a y co-ordinate.
+
+
+
+ int
+
offsetToX(int line,
+ int offset)
+
+
+ Converts an offset in a line into an x co-ordinate.
+
+
+
+ void
+
overwriteSetSelectedText(java.lang.String str)
+
+
+ Similar to setSelectedText(), but overstrikes the
+ appropriate number of characters if overwrite mode is enabled.
+
+
+
+ void
+
paste()
+
+
+ Inserts the clipboard contents into the text.
setDocument(SyntaxDocument document,
+ int start,
+ int stop,
+ int scroll)
+
+
+ Set document with a twist, includes the old caret
+ and scroll positions, added for p5.
+
+
+
+ void
+
setEditable(boolean editable)
+
+
+ Sets if this component is editable.
+
+
+
+ void
+
setElectricScroll(int electricScroll)
+
+
+ Sets the number of lines from the top and bottom of the text
+ area that are always visible
+
+
+
+ void
+
setFirstLine(int firstLine)
+
+
+ Sets the line displayed at the text area's origin without
+ updating the scroll bars.
+
+
+
+ void
+
setHorizontalOffset(int horizontalOffset)
+
+
+ Sets the horizontal offset of drawn lines.
caretVisible - True if the caret should be visible, false
+ otherwise
+
+
+
+
+
+blinkCaret
+
+public final void blinkCaret()
+
+
Blinks the caret.
+
+
+
+
+
+
+
+
+getElectricScroll
+
+public final int getElectricScroll()
+
+
Returns the number of lines from the top and button of the
+ text area that are always visible.
+
+
+
+
+
+
+
+
+setElectricScroll
+
+public final void setElectricScroll(int electricScroll)
+
+
Sets the number of lines from the top and bottom of the text
+ area that are always visible
+
+
+
Parameters:
electricScroll - The number of lines always visible from
+ the top or bottom
+
+
+
+
+
+updateScrollBars
+
+public void updateScrollBars()
+
+
Updates the state of the scroll bars. This should be called
+ if the number of lines in the document changes, or when the
+ size of the text are changes.
+
+
+
+
+
+
+
+
+getFirstLine
+
+public final int getFirstLine()
+
+
Returns the line displayed at the text area's origin.
+
+
+
+
+
+
+
+
+setFirstLine
+
+public void setFirstLine(int firstLine)
+
+
Sets the line displayed at the text area's origin without
+ updating the scroll bars.
+
+
+
+
+
+
+
+
+getVisibleLines
+
+public final int getVisibleLines()
+
+
Returns the number of lines visible in this text area.
+
+
+
+
+
+
+
+
+recalculateVisibleLines
+
+public final void recalculateVisibleLines()
+
+
Recalculates the number of visible lines. This should not
+ be called directly.
+
Sets the horizontal offset of drawn lines. This can be used to
+ implement horizontal scrolling.
+
+
+
Parameters:
horizontalOffset - offset The new horizontal offset
+
+
+
+
+
+setOrigin
+
+public boolean setOrigin(int firstLine,
+ int horizontalOffset)
+
+
A fast way of changing both the first line and horizontal
+ offset.
+
+
+
Parameters:
firstLine - The new first line
horizontalOffset - The new horizontal offset
+
Returns:
True if any of the values were changed, false otherwise
+
+
+
+
+
+scrollToCaret
+
+public boolean scrollToCaret()
+
+
Ensures that the caret is visible by scrolling the text area if
+ necessary.
+
+
+
+
Returns:
True if scrolling was actually performed, false if the
+ caret was already visible
+
+
+
+
+
+scrollTo
+
+public boolean scrollTo(int line,
+ int offset)
+
+
Ensures that the specified line and offset is visible by scrolling
+ the text area if necessary.
+
+
+
Parameters:
line - The line to scroll to
offset - The offset in the line to scroll to
+
Returns:
True if scrolling was actually performed, false if the
+ line and offset was already visible
+
+
+
+
+
+lineToY
+
+public int lineToY(int line)
+
+
Converts a line index to a y co-ordinate.
+
+
+
Parameters:
line - The line
+
+
+
+
+
+yToLine
+
+public int yToLine(int y)
+
+
Converts a y co-ordinate to a line index.
+
+
+
Parameters:
y - The y co-ordinate
+
+
+
+
+
+offsetToX
+
+public final int offsetToX(int line,
+ int offset)
+
+
Converts an offset in a line into an x co-ordinate. This is a
+ slow version that can be used any time.
+
+
+
Parameters:
line - The line
offset - The offset, from the start of the line
+
+
+
+
+
+_offsetToX
+
+public int _offsetToX(int line,
+ int offset)
+
+
Converts an offset in a line into an x co-ordinate. This is a
+ fast version that should only be used if no changes were made
+ to the text since the last repaint.
+
+
+
Parameters:
line - The line
offset - The offset, from the start of the line
+
+
+
+
+
+xToOffset
+
+public int xToOffset(int line,
+ int x)
+
+
Converts an x co-ordinate to an offset within a line.
+
+
+
Parameters:
line - The line
x - The x co-ordinate
+
+
+
+
+
+xyToOffset
+
+public int xyToOffset(int x,
+ int y)
+
+
Converts a point to an offset, from the start of the text.
+
Returns the caret position. This will either be the selection
+ start or the selection end, depending on which direction the
+ selection was made in.
+
+
+
+
+
+
+
+
+getCaretLine
+
+public final int getCaretLine()
+
+
Returns the caret line.
+
+
+
+
+
+
+
+
+getMarkPosition
+
+public final int getMarkPosition()
+
+
Returns the mark position. This will be the opposite selection
+ bound to the caret position.
+
Selects from the start offset to the end offset. This is the
+ general selection method used by all other selecting methods.
+ The caret position will be start if start < end, and end
+ if end > start.
+
+
+
Parameters:
start - The start offset
end - The end offset
+
+
+
+
+
+getSelectedText
+
+public final java.lang.String getSelectedText()
+
+
Returns the selected text, or null if no selection is active.
+
+A KeywordMap 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.
+
+ This class is used by CTokenMarker to map keywords to ids.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Constructor Summary
+
+
+
KeywordMap(boolean ignoreCase)
+
+
+ Creates a new KeywordMap.
+
+
+
KeywordMap(boolean ignoreCase,
+ int mapLength)
+
+
+ Creates a new KeywordMap.
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.
+
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.
+
+
+
Parameters:
tm - The new token marker
+
+
+
+
+
+tokenizeLines
+
+public void tokenizeLines()
+
+
Reparses the document, by passing all lines to the token
+ marker. This should be called after the document is first
+ loaded.
+
+
+
+
+
+
+
+
+tokenizeLines
+
+public void tokenizeLines(int start,
+ int len)
+
+
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.
+
+
+
Parameters:
start - The first line to parse
len - The number of lines, after the first one to parse
+
+
+
+
+
+beginCompoundEdit
+
+public void beginCompoundEdit()
+
+
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.
+
+
+
+
+
+
+
+
+endCompoundEdit
+
+public void endCompoundEdit()
+
+
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.
+
+A simple text style class. It can specify the color, italic flag,
+ and bold flag of a run of text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Constructor Summary
+
+
+
SyntaxStyle(java.awt.Color color,
+ boolean italic,
+ boolean bold)
+
+
+ Creates a new SyntaxStyle.
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ java.awt.Color
+
getColor()
+
+
+ Returns the color specified in this style.
+
+
+
+ java.awt.FontMetrics
+
getFontMetrics(java.awt.Font font,
+ javax.swing.JComponent comp)
+
+
+ Returns the font metrics for the styled font.
+
+
+
+ java.awt.Font
+
getStyledFont(java.awt.Font font)
+
+
+ Returns the specified font, but with the style's bold and
+ italic flags applied.
+
+
+
+ boolean
+
isBold()
+
+
+ Returns true if boldface is enabled for this style.
+
+
+
+ boolean
+
isItalic()
+
+
+ Returns true if italics is enabled for this style.
+
+
+
+ boolean
+
isPlain()
+
+
+ Returns true if no font styles are enabled.
+
+
+
+ void
+
setGraphicsFlags(java.awt.Graphics gfx,
+ java.awt.Font font)
+
+
+ Sets the foreground color and font of the specified graphics
+ context to that specified in this style.
+
+
+
+ java.lang.String
+
toString()
+
+
+ Returns a string representation of this object.
paintSyntaxLine(javax.swing.text.Segment line,
+ Token tokens,
+ SyntaxStyle[] styles,
+ javax.swing.text.TabExpander expander,
+ java.awt.Graphics gfx,
+ int x,
+ int y)
+
+
+ Paints the specified line onto the graphics context.
+
+
+
+static boolean
+
regionMatches(boolean ignoreCase,
+ javax.swing.text.Segment text,
+ int offset,
+ char[] match)
+
+
+ Checks if a subregion of a Segment is equal to a
+ character array.
+
+
+
+static boolean
+
regionMatches(boolean ignoreCase,
+ javax.swing.text.Segment text,
+ int offset,
+ java.lang.String match)
+
+
+ Checks if a subregion of a Segment is equal to a
+ string.
+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.
+
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.
+
+public final void setCaretColor(java.awt.Color caretColor)
+
+
Sets the caret color.
+
+
+
+
+
+
Parameters:
caretColor - The caret color
+
+
+
+
+
+getSelectionColor
+
+public final java.awt.Color getSelectionColor()
+
+
Returns the selection color.
+
+
+
+
+
+
+
+
+
+
+
+setSelectionColor
+
+public final void setSelectionColor(java.awt.Color selectionColor)
+
+
Sets the selection color.
+
+
+
+
+
+
Parameters:
selectionColor - The selection color
+
+
+
+
+
+getLineHighlightColor
+
+public final java.awt.Color getLineHighlightColor()
+
+
Returns the line highlight color.
+
+
+
+
+
+
+
+
+
+
+
+setLineHighlightColor
+
+public final void setLineHighlightColor(java.awt.Color lineHighlightColor)
+
+
Sets the line highlight color.
+
+
+
+
+
+
Parameters:
lineHighlightColor - The line highlight color
+
+
+
+
+
+isLineHighlightEnabled
+
+public final boolean isLineHighlightEnabled()
+
+
Returns true if line highlight is enabled, false otherwise.
+
+
+
+
+
+
+
+
+
+
+
+setLineHighlightEnabled
+
+public final void setLineHighlightEnabled(boolean lineHighlight)
+
+
Enables or disables current line highlighting.
+
+
+
+
+
+
Parameters:
lineHighlight - True if current line highlight
+ should be enabled, false otherwise
+
+
+
+
+
+getBracketHighlightColor
+
+public final java.awt.Color getBracketHighlightColor()
+
+
Returns the bracket highlight color.
+
+
+
+
+
+
+
+
+
+
+
+setBracketHighlightColor
+
+public final void setBracketHighlightColor(java.awt.Color bracketHighlightColor)
+
+
Sets the bracket highlight color.
+
+
+
+
+
+
Parameters:
bracketHighlightColor - The bracket highlight color
+
+
+
+
+
+isBracketHighlightEnabled
+
+public final boolean isBracketHighlightEnabled()
+
+
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.
+
+
+
+
+
+
+
+
+
+
+
+setBracketHighlightEnabled
+
+public final void setBracketHighlightEnabled(boolean bracketHighlight)
+
+
Enables or disables bracket highlighting.
+ When bracket highlighting is enabled, the bracket matching the
+ one before the caret (if any) is highlighted.
+
+
+
+
+
+
Parameters:
bracketHighlight - True if bracket highlighting should be
+ enabled, false otherwise
+
+
+
+
+
+isBlockCaretEnabled
+
+public final boolean isBlockCaretEnabled()
+
+
Returns true if the caret should be drawn as a block, false otherwise.
+
+
+
+
+
+
+
+
+
+
+
+setBlockCaretEnabled
+
+public final void setBlockCaretEnabled(boolean blockCaret)
+
+
Sets if the caret should be drawn as a block, false otherwise.
+
+
+
+
+
+
Parameters:
blockCaret - True if the caret should be drawn as a block,
+ false otherwise.
+
+
+
+
+
+getEOLMarkerColor
+
+public final java.awt.Color getEOLMarkerColor()
+
+
Returns the EOL marker color.
+
+
+
+
+
+
+
+
+
+
+
+setEOLMarkerColor
+
+public final void setEOLMarkerColor(java.awt.Color eolMarkerColor)
+
+
Sets the EOL marker color.
+
+
+
+
+
+
Parameters:
eolMarkerColor - The EOL marker color
+
+
+
+
+
+getEOLMarkersPainted
+
+public final boolean getEOLMarkersPainted()
+
+
Returns true if EOL markers are drawn, false otherwise.
+
+
+
+
+
+
+
+
+
+
+
+setEOLMarkersPainted
+
+public final void setEOLMarkersPainted(boolean eolMarkers)
+
+
Sets if EOL markers are to be drawn.
+
+
+
+
+
+
Parameters:
eolMarkers - True if EOL markers should be drawn, false otherwise
+
+
+
+
+
+getInvalidLinesPainted
+
+public boolean getInvalidLinesPainted()
+
+
Returns true if invalid lines are painted as red tildes (~),
+ false otherwise.
+
findMatchingBracket(javax.swing.text.Document doc,
+ int offset)
+
+
+ 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).
+
+
+
+static int
+
findWordEnd(java.lang.String line,
+ int pos,
+ java.lang.String noWordSep)
+
+
+ Locates the end of the word at the specified position.
+
+
+
+static int
+
findWordStart(java.lang.String line,
+ int pos,
+ java.lang.String noWordSep)
+
+
+ Locates the start of the word at the specified position.
+public static int findMatchingBracket(javax.swing.text.Document doc,
+ int offset)
+ throws javax.swing.text.BadLocationException
+
+
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).
+
+
+
Parameters:
doc - The document
offset - The offset
+
Throws:
+
javax.swing.text.BadLocationException - If an out-of-bounds access
+ was attempted on the document text
+
+
+
+
+
+findWordStart
+
+public static int findWordStart(java.lang.String line,
+ int pos,
+ java.lang.String noWordSep)
+
+
Locates the start of the word at the specified position.
+
+
+
Parameters:
line - The text
pos - The position
+
+
+
+
+
+findWordEnd
+
+public static int findWordEnd(java.lang.String line,
+ int pos,
+ java.lang.String noWordSep)
+
+
Locates the end of the word at the specified position.
+
+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 SyntaxDocument.getColors()
+ 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.
+
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.
+
+
+
+
+
+
+
+
+
+
+
+Constructor Detail
+
+
+
+
+TokenMarker.LineInfo
+
+public TokenMarker.LineInfo()
+
+
Creates a new LineInfo object with token = Token.NULL
+ and obj = null.
+
+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.
+
+ For performance reasons, the linked list of tokens is reused after each
+ line is tokenized. Therefore, the return value of markTokens
+ should only be used for immediate painting. Notably, it cannot be
+ cached.
+
+
+
+
+
+
+
+
+
+
+
+
+Nested Class Summary
+
+
+
+ class
+
TokenMarker.LineInfo
+
+
+ Inner class for storing information about tokenized lines.
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
deleteLines(int index,
+ int lines)
+
+
+ Informs the token marker that line have been deleted from
+ the document.
+
+
+
+ int
+
getLineCount()
+
+
+ Returns the number of lines in this token marker.
+
+
+
+ void
+
insertLines(int index,
+ int lines)
+
+
+ Informs the token marker that lines have been inserted into
+ the document.
+
+
+
+ boolean
+
isNextLineRequested()
+
+
+ Returns true if the next line should be repainted.
markTokens(javax.swing.text.Segment line,
+ int lineIndex)
+
+
+ A wrapper for the lower-level markTokensImpl method
+ that is called to split a line up into tokens.
+
+
+
+ boolean
+
supportsMultilineTokens()
+
+
+ Returns if the token marker supports tokens that span multiple
+ lines.
+public TokenmarkTokens(javax.swing.text.Segment line,
+ int lineIndex)
+
+
A wrapper for the lower-level markTokensImpl method
+ that is called to split a line up into tokens.
+
+
+
Parameters:
line - The line
lineIndex - The line number
+
+
+
+
+
+supportsMultilineTokens
+
+public boolean supportsMultilineTokens()
+
+
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
+ markTokens() method (in turn).
+
+ The default implementation returns true; it should be overridden
+ to return false on simpler token markers for increased speed.
+
+
+
+
+
+
+
+
+insertLines
+
+public void insertLines(int index,
+ int lines)
+
+
Informs the token marker that lines have been inserted into
+ the document. This inserts a gap in the lineInfo
+ array.
+
+
+
Parameters:
index - The first line number
lines - The number of lines
+
+
+
+
+
+deleteLines
+
+public void deleteLines(int index,
+ int lines)
+
+
Informs the token marker that line have been deleted from
+ the document. This removes the lines in question from the
+ lineInfo array.
+
+
+
Parameters:
index - The first line number
lines - The number of lines
+
+
+
+
+
+getLineCount
+
+public int getLineCount()
+
+
Returns the number of lines in this token marker.
+
+
+
+
+
+
+
+
+isNextLineRequested
+
+public boolean isNextLineRequested()
+
+
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.
+
Mouse has been pressed, and should be considered "down"
+ until mouseReleased() is called. If you must, use
+ int button = mouseEvent.getButton();
+ to figure out which button was clicked. It will be one of:
+ MouseEvent.BUTTON1, MouseEvent.BUTTON2, MouseEvent.BUTTON3
+ Note, however, that this is completely inconsistent across
+ platforms.
+
Mouse has been pressed, and should be considered "down"
+ until mouseReleased() is called. If you must, use
+ int button = mouseEvent.getButton();
+ to figure out which button was clicked. It will be one of:
+ MouseEvent.BUTTON1, MouseEvent.BUTTON2, MouseEvent.BUTTON3
+ Note, however, that this is completely inconsistent across
+ platforms.
+
+ 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).
+
+ Original code by owd.
+ 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.
+
+ Updated for 0122 to simply copy the code directly to the clipboard,
+ rather than opening a new window.
+
+ Updated for 0144 to only format the selected lines.
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Constructor Summary
+
+
+
DiscourseFormat(Editor editor)
+
+
+ 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)
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)
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+show
+
+public void show()
+
+
Format and render sketch code.
+
+
+
+
+
+
+
+
+appendFormattedLine
+
+public void appendFormattedLine(java.lang.StringBuffer cf,
+ int line)
Returns an array containing the constants of this enum type, in
+the order they're declared. This method may be used to iterate
+over the constants as follows:
+
+for(Registry.REGISTRY_ROOT_KEY c : Registry.REGISTRY_ROOT_KEY.values())
+ System.out.println(c);
+
+
+
+
+
Returns:
an array containing the constants of this enum type, in
+the order they're declared
Returns the enum constant of this type with the specified name.
+The string must match exactly an identifier used to declare an
+enum constant in this type. (Extraneous whitespace characters are
+not permitted.)
+
+
+
Parameters:
name - the name of the enum constant to be returned.
+
Returns:
the enum constant with the specified name
+
Throws:
+
java.lang.IllegalArgumentException - if this enum type has no constant
+with the specified name
Get a particular element based on its SVG ID. When editing SVG by hand,
+ this is the id="" tag on any SVG element. When editing from Illustrator,
+ these IDs can be edited by expanding the layers palette. The names used
+ in the layers palette, both for the layers or the shapes and groups
+ beneath them can be used here.
+
+ // This code grabs "Layer 3" and the shapes beneath it.
+ SVG layer3 = svg.get("Layer 3");
+
+Candy is a minimal SVG import library for Processing.
+ Candy was written by Michael Chang, and later revised and
+ expanded for use as a Processing core library by Ben Fry.
+
+ SVG stands for Scalable Vector Graphics, a portable graphics format. It is
+ a vector format so it allows for infinite resolution and relatively small
+ file sizes. Most modern media software can view SVG files, including Adobe
+ products, Firefox, etc. Illustrator and Inkscape can edit SVG files.
+
+ We have no intention of turning this into a full-featured SVG library.
+ The goal of this project is a basic shape importer that is small enough
+ to be included with applets, meaning that its download size should be
+ in the neighborhood of 25-30k. Because of this size, it is not made part
+ of processing.core, as it's not a feature that will be used by the majority
+ of our audience.
+
+ For more sophisticated import/export, consider the
+ Batik
+ library from the Apache Software Foundation. Future improvements to this
+ library may focus on this properly supporting a specific subset of SVG,
+ for instance the simpler SVG profiles known as
+ SVG Tiny or Basic,
+ although we still would not support the interactivity options.
+
+ This library was specifically tested under SVG files created with Adobe
+ Illustrator. We can't guarantee that it will work for any SVGs created with
+ other software. In the future we would like to improve compatibility with
+ Open Source software such as Inkscape, however initial tests show its
+ base implementation produces more complicated files, and this will require
+ more time.
+
+ An SVG created under Illustrator must be created in one of two ways:
+
+
File → Save for Web (or control-alt-shift-s on a PC). Under
+ settings, make sure the CSS properties is set to "Presentation Attributes".
+
With Illustrator CS2, it is also possible to use "Save As" with "SVG"
+ as the file setting, but the CSS properties should also be set similarly.
+
+ Saving it any other way will most likely break Candy.
+
+
+
+ A minimal example program using Candy:
+ (assuming a working moo.svg is in your data folder)
+
+
+
+ Note that processing.xml needs to be imported as well.
+ This may not be required when running code within the Processing
+ environment, but when exported it may cause a NoClassDefError.
+ This will be fixed in later releases of Processing
+ (Bug 518).
+
+
+
+ August 2008 revisions by fry (Processing 0149)
+
+
Major changes to rework around PShape.
+
Now implementing more of the "transform" attribute.
+
+
+ February 2008 revisions by fry (Processing 0136)
+
+
Added support for quadratic curves in paths (Q, q, T, and t operators)
+
Support for reading SVG font data (though not rendering it yet)
+
+
+ Revisions for "Candy 2" November 2006 by fry
+
+
Switch to the new processing.xml library
+
Several bug fixes for parsing of shape data
+
Support for linear and radial gradients
+
Support for additional types of shapes
+
Added compound shapes (shapes with interior points)
+
Added methods to get shapes from an internal table
+
+
+ Revision 10/31/06 by flux
+
+
Now properly supports Processing 0118
+
Fixed a bunch of things for Casey's students and general buggity.
+
Will now properly draw #FFFFFFFF colors (were being represented as -1)
+
SVGs without tags are now properly caught and loaded
+
Added a method customStyle() for overriding SVG colors/styles
+
Added a method SVGStyle() to go back to using SVG colors/styles
+
+
+ Some SVG objects and features may not yet be supported.
+ Here is a partial list of non-included features
+
+
Rounded rectangles
+
Drop shadow objects
+
Typography
+
Layers added for Candy 2
+
Patterns
+
Embedded images
+
+
+ For those interested, the SVG specification can be found
+ here.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from interface processing.core.PConstants
remove(java.lang.Object object,
+ java.lang.reflect.Method method)
+
+
+ Removes first object/method pair matched (and only the first,
+ must be called multiple times if object is registered multiple times).
Removes first object/method pair matched (and only the first,
+ must be called multiple times if object is registered multiple times).
+ Does not shrink array afterwards, silently returns if method not found.
+
public static class PApplet.RendererChangeException
extends java.lang.RuntimeException
+
+
+
+Exception thrown when size() is called the first time.
+
+ This is used internally so that setup() is forced to run twice
+ when the renderer is changed. This is the only way for us to handle
+ invoking the new renderer while also in the midst of rendering.
+
+Base class for all sketches that use processing.core.
+
+ Note that you should not use AWT or Swing components inside a Processing
+ applet. The surface is made to automatically update itself, and will cause
+ problems with redraw of components drawn above it. If you'd like to
+ integrate other Java components, see below.
+
+ As of release 0145, Processing uses active mode rendering in all cases.
+ All animation tasks happen on the "Processing Animation Thread". The
+ setup() and draw() methods are handled by that thread, and events (like
+ mouse movement and key presses, which are fired by the event dispatch
+ thread or EDT) are queued to be (safely) handled at the end of draw().
+ For code that needs to run on the EDT, use SwingUtilities.invokeLater().
+ When doing so, be careful to synchronize between that code (since
+ invokeLater() will make your code run from the EDT) and the Processing
+ animation thread. Use of a callback function or the registerXxx() methods
+ in PApplet can help ensure that your code doesn't do something naughty.
+
+ As of release 0136 of Processing, we have discontinued support for versions
+ of Java prior to 1.5. We don't have enough people to support it, and for a
+ project of our size, we should be focusing on the future, rather than
+ working around legacy Java code. In addition, Java 1.5 gives us access to
+ better timing facilities which will improve the steadiness of animation.
+
+ This class extends Applet instead of JApplet because 1) historically,
+ we supported Java 1.1, which does not include Swing (without an
+ additional, sizable, download), and 2) Swing is a bloated piece of crap.
+ A Processing applet is a heavyweight AWT component, and can be used the
+ same as any other AWT component, with or without Swing.
+
+ Similarly, Processing runs in a Frame and not a JFrame. However, there's
+ nothing to prevent you from embedding a PApplet into a JFrame, it's just
+ that the base version uses a regular AWT frame because there's simply
+ no need for swing in that context. If people want to use Swing, they can
+ embed themselves as they wish.
+
+ It is possible to use PApplet, along with core.jar in other projects.
+ In addition to enabling you to use Java 1.5+ features with your sketch,
+ this also allows you to embed a Processing drawing area into another Java
+ application. This means you can use standard GUI controls with a Processing
+ sketch. Because AWT and Swing GUI components cannot be used on top of a
+ PApplet, you can instead embed the PApplet inside another GUI the way you
+ would any other Component.
+
+ It is also possible to resize the Processing window by including
+ frame.setResizable(true) inside your setup() method.
+ Note that the Java method frame.setSize() will not work unless
+ you first set the frame to be resizable.
+
+ Because the default animation thread will run at 60 frames per second,
+ an embedded PApplet can make the parent sluggish. You can use frameRate()
+ to make it update less often, or you can use noLoop() and loop() to disable
+ and then re-enable looping. If you want to only update the sketch
+ intermittently, use noLoop() inside setup(), and redraw() whenever
+ the screen needs to be updated once (or loop() to re-enable the animation
+ thread). The following example embeds a sketch and also uses the noLoop()
+ and redraw() methods. You need not use noLoop() and redraw() when embedding
+ if you want your application to animate continuously.
+
+ public class ExampleFrame extends Frame {
+
+ public ExampleFrame() {
+ super("Embedded PApplet");
+
+ setLayout(new BorderLayout());
+ PApplet embed = new Embedded();
+ add(embed, BorderLayout.CENTER);
+
+ // important to call this whenever embedding a PApplet.
+ // It ensures that the animation thread is started and
+ // that other internal variables are properly set.
+ embed.init();
+ }
+ }
+
+ public class Embedded extends PApplet {
+
+ public void setup() {
+ // original setup code here ...
+ size(400, 400);
+
+ // prevent thread from starving everything else
+ noLoop();
+ }
+
+ public void draw() {
+ // drawing code goes here
+ }
+
+ public void mousePressed() {
+ // do something based on mouse movement
+
+ // update the screen (run draw once)
+ redraw();
+ }
+ }
+
+
+
Processing on multiple displays
+
I was asked about Processing with multiple displays, and for lack of a
+ better place to document it, things will go here.
+
You can address both screens by making a window the width of both,
+ and the height of the maximum of both screens. In this case, do not use
+ present mode, because that's exclusive to one screen. Basically it'll
+ give you a PApplet that spans both screens. If using one half to control
+ and the other half for graphics, you'd just have to put the 'live' stuff
+ on one half of the canvas, the control stuff on the other. This works
+ better in windows because on the mac we can't get rid of the menu bar
+ unless it's running in present mode.
+
For more control, you need to write straight java code that uses p5.
+ You can create two windows, that are shown on two separate screens,
+ that have their own PApplet. this is just one of the tradeoffs of one of
+ the things that we don't support in p5 from within the environment
+ itself (we must draw the line somewhere), because of how messy it would
+ get to start talking about multiple screens. It's also not that tough to
+ do by hand w/ some Java code.
arraycopy(java.lang.Object src,
+ int srcPosition,
+ java.lang.Object dst,
+ int dstPosition,
+ int length)
+
+
+ Deprecated.Use arrayCopy() instead.
+
+
+
+static void
+
arrayCopy(java.lang.Object src,
+ int srcPosition,
+ java.lang.Object dst,
+ int dstPosition,
+ int length)
+
+
+ Calls System.arraycopy(), included here so that we can
+ avoid people needing to learn about the System object
+ before they can just copy an array.
beginRaw(java.lang.String renderer,
+ java.lang.String filename)
+
+
+ Begin recording raw shape data to a renderer of the specified type,
+ using the width and height of the main drawing surface.
+
+
+
+ void
+
beginRecord(PGraphics recorder)
+
+
+ Begin recording (echoing) commands to the specified PGraphics object.
beginRecord(java.lang.String renderer,
+ java.lang.String filename)
+
+
+ Begin recording to a new renderer of the specified type, using the width
+ and height of the main drawing surface.
createFont(java.lang.String name,
+ float size,
+ boolean smooth,
+ char[] charset)
+
+
+ Create a .vlw font on the fly from either a font name that's
+ installed on the system, or from a .ttf or .otf that's inside
+ the data folder of this sketch.
createGraphics(int iwidth,
+ int iheight,
+ java.lang.String irenderer,
+ java.lang.String ipath)
+
+
+ Create an offscreen graphics surface for drawing, in this case
+ for a renderer that writes to a file (such as PDF or DXF).
createImage(int wide,
+ int high,
+ int format)
+
+
+ Preferred method of creating new PImage objects, ensures that a
+ reference to the parent PApplet is included, which makes save() work
+ without needing an absolute path.
createOutput(java.lang.String filename)
+
+
+ Similar to createInput() (formerly openStream), this creates a Java
+ OutputStream for a given filename or path.
delay(int napTime)
+
+
+ The delay() function causes the program to halt for a specified time.
+
+
+
+ void
+
destroy()
+
+
+ Called by the browser or applet viewer to inform this applet
+ that it is being reclaimed and that it should destroy
+ any resources that it has allocated.
+
+
+
+ void
+
die(java.lang.String what)
+
+
+ Function for an applet/application to kill itself and
+ display an error.
+
+
+
+ void
+
die(java.lang.String what,
+ java.lang.Exception e)
+
+
+ Same as above but with an exception.
join(java.lang.String[] str,
+ char separator)
+
+
+ Join an array of Strings together as a single String,
+ separated by the whatever's passed in for the separator.
+
+
+
+static java.lang.String
+
join(java.lang.String[] str,
+ java.lang.String separator)
+
+
+ Join an array of Strings together as a single String,
+ separated by the whatever's passed in for the separator.
+
+
+
+ void
+
keyPressed()
+
+
+ Called each time a single key on the keyboard is pressed.
+
+
+
+ void
+
keyPressed(java.awt.event.KeyEvent e)
+
+
+ Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
+ 'keyCode', and 'keyEvent' variables to no longer work;
+ key events will no longer be queued until the end of draw();
+ and the keyPressed(), keyReleased() and keyTyped() methods
+ will no longer be called.
loadImage(java.lang.String filename,
+ java.lang.String extension)
+
+
+ Identical to loadImage, but allows you to specify the type of
+ image by its extension.
+
+
+
+ void
+
loadPixels()
+
+
+ Override the g.pixels[] function to set the pixels[] array
+ that's part of the PApplet object.
main(java.lang.String[] args)
+
+
+ main() method for running this class from the command line.
+
+
+
+static float
+
map(float value,
+ float istart,
+ float istop,
+ float ostart,
+ float ostop)
+
+
+ Convenience function to map a variable from one coordinate space
+ to another.
match(java.lang.String what,
+ java.lang.String regexp)
+
+
+ Match a string with a regular expression, and returns the match as an
+ array.
+
+
+
+static java.lang.String[][]
+
matchAll(java.lang.String what,
+ java.lang.String regexp)
+
+
+ Identical to match(), except that it returns an array of all matches in
+ the specified String, rather than just the first.
+
+
+
+static float
+
max(float[] list)
+
+
+ Find the maximum value in an array.
mousePressed()
+
+
+ Mouse has been pressed, and should be considered "down"
+ until mouseReleased() is called.
+
+
+
+ void
+
mousePressed(java.awt.event.MouseEvent e)
+
+
+ If you override this or any function that takes a "MouseEvent e"
+ without calling its super.mouseXxxx() then mouseX, mouseY,
+ mousePressed, and mouseEvent will no longer be set.
+
+
+
+ void
+
mouseReleased()
+
+
+ Mouse button has been released.
nfp(int num,
+ int digits)
+
+
+ number format positive (or plus)
+ Formats a number, always placing a - or + sign
+ in the front when it's negative or positive.
+
+
+
+static java.lang.String[]
+
nfs(float[] num,
+ int left,
+ int right)
+
+
+ Number formatter that takes into account whether the number
+ has a sign (positive, negative, etc) in front of it.
nfs(int num,
+ int digits)
+
+
+ number format signed (or space)
+ Formats a number but leaves a blank space in the front
+ when it's positive so that it can be properly aligned with
+ numbers that have a negative sign in front of them.
+
+
+
+ void
+
noCursor()
+
+
+ Hide the cursor by creating a transparent image
+ and using it as a custom cursor.
parseInt(java.lang.String what)
+
+
+ Parse a String into an int value.
+
+
+
+static int[]
+
parseInt(java.lang.String[] what)
+
+
+ Make an array of int elements from an array of String objects.
+
+
+
+static int[]
+
parseInt(java.lang.String[] what,
+ int missing)
+
+
+ Make an array of int elements from an array of String objects.
+
+
+
+static int
+
parseInt(java.lang.String what,
+ int otherwise)
+
+
+ Parse a String to an int, and provide an alternate value that
+ should be used when the number is invalid.
save(java.lang.String filename)
+
+
+ Intercepts any relative paths to make them absolute (relative
+ to the sketch folder) before passing to save() in PImage.
+
+
+
+static void
+
saveBytes(java.io.File file,
+ byte[] buffer)
+
+
+ Saves bytes to a specific File location specified by the user.
+
+
+
+static void
+
saveBytes(java.io.OutputStream output,
+ byte[] buffer)
+
+
+ Spews a buffer of bytes to an OutputStream.
+
+
+
+ void
+
saveBytes(java.lang.String filename,
+ byte[] buffer)
+
+
+ Saves bytes to a file to inside the sketch folder.
+
+
+
+ java.io.File
+
saveFile(java.lang.String where)
+
+
+ Identical to savePath(), but returns a File object.
+
+
+
+ void
+
saveFrame()
+
+
+ Grab an image of what's currently in the drawing area and save it
+ as a .tif or .tga file.
+
+
+
+ void
+
saveFrame(java.lang.String what)
+
+
+ Save the current frame as a .tif or .tga image.
+
+
+
+ java.lang.String
+
savePath(java.lang.String where)
+
+
+ Returns a path inside the applet folder to save to.
saveStream(java.io.File targetFile,
+ java.lang.String sourceLocation)
+
+
+ Identical to the other saveStream(), but writes to a File
+ object, for greater control over the file location.
+
+
+
+ void
+
saveStream(java.lang.String targetFilename,
+ java.lang.String sourceLocation)
+
+
+ Save the contents of a stream to a file in the sketch folder.
size(int iwidth,
+ int iheight,
+ java.lang.String irenderer,
+ java.lang.String ipath)
+
+
+ Creates a new PGraphics object and sets it to the specified size.
split(java.lang.String what,
+ char delim)
+
+
+ Split a string into pieces along a specific character.
+
+
+
+static java.lang.String[]
+
split(java.lang.String what,
+ java.lang.String delim)
+
+
+ Split a String on a specific delimiter.
+
+
+
+static java.lang.String[]
+
splitTokens(java.lang.String what)
+
+
+ Split the provided String at wherever whitespace occurs.
+
+
+
+static java.lang.String[]
+
splitTokens(java.lang.String what,
+ java.lang.String delim)
+
+
+ Splits a string into pieces, using any of the chars in the
+ String 'delim' as separator characters.
+public static final java.lang.String javaVersionName
+
+
Full name of the Java version (i.e. 1.5.0_11).
+ Prior to 0125, this was only the first three digits.
+
+
+
+
+
+
+
+javaVersion
+
+public static final float javaVersion
+
+
Version of Java that's in use, whether 1.1 or 1.3 or whatever,
+ stored as a float.
+
+ Note that because this is stored as a float, the values may
+ not be exactly 1.3 or 1.4. Instead, make sure you're
+ comparing against 1.3f or 1.4f, which will have the same amount
+ of error (i.e. 1.40000001). This could just be a double, but
+ since Processing only uses floats, it's safer for this to be a float
+ because there's no good way to specify a double with the preproc.
+
+
+
+
+
+
+
+platform
+
+public static int platform
+
+
Current platform in use, one of the
+ PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
+
+
+
+
+
+
+
+MENU_SHORTCUT
+
+public static final int MENU_SHORTCUT
+
+
Modifier flags for the shortcut key used to trigger menus.
+ (Cmd on Mac OS X, Ctrl on Linux and Windows)
+
The PGraphics renderer associated with this PApplet
+
+
+
+
+
+
+
+frame
+
+public java.awt.Frame frame
+
+
The frame containing this applet (if any)
+
+
+
+
+
+
+
+screen
+
+public java.awt.Dimension screen
+
+
The screen size when the applet was started.
+
+ Access this via screen.width and screen.height. To make an applet
+ run at full screen, use size(screen.width, screen.height).
+
+ If you have multiple displays, this will be the size of the main
+ display. Running full screen across multiple displays isn't
+ particularly supported, and requires more monkeying with the values.
+ This probably can't/won't be fixed until/unless I get a dual head
+ system.
+
+ Note that this won't update if you change the resolution
+ of your screen once the the applet is running.
+
+ This variable is not static, because future releases need to be better
+ at handling multiple displays.
+
Minimum dimensions for the window holding an applet.
+ This varies between platforms, Mac OS X 10.3 can do any height
+ but requires at least 128 pixels width. Windows XP has another
+ set of limitations. And for all I know, Linux probably lets you
+ make windows with negative sizes.
+
true if no size() command has been executed. This is used to wait until
+ a size has been set before placing in the window and showing it.
+
+
+
+
+
+
+
+pixels
+
+public int[] pixels
+
+
Pixel buffer from this applet's PGraphics.
+
+ When used with OpenGL or Java2D, this value will
+ be null until loadPixels() has been called.
+
+
+
+
+
+
+
+width
+
+public int width
+
+
width of this applet's associated PGraphics
+
+
+
+
+
+
+
+height
+
+public int height
+
+
height of this applet's associated PGraphics
+
+
+
+
+
+
+
+mouseX
+
+public int mouseX
+
+
current x position of the mouse
+
+
+
+
+
+
+
+mouseY
+
+public int mouseY
+
+
current y position of the mouse
+
+
+
+
+
+
+
+pmouseX
+
+public int pmouseX
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+
+pmouseY
+
+public int pmouseY
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+
+firstMouse
+
+public boolean firstMouse
+
+
Used to set pmouseX/Y to mouseX/Y the first time mouseX/Y are used,
+ otherwise pmouseX/Y are always zero, causing a nasty jump.
+
+ Just using (frameCount == 0) won't work since mouseXxxxx()
+ may not be called until a couple frames into things.
+
+
+
+
+
+
+
+mouseButton
+
+public int mouseButton
+
+
Last mouse button pressed, one of LEFT, CENTER, or RIGHT.
+
+ If running on Mac OS, a ctrl-click will be interpreted as
+ the righthand mouse button (unlike Java, which reports it as
+ the left mouse).
+
+
+
+
+
+
+
+mousePressed
+
+public boolean mousePressed
+
+
+
+
+
+
+
+mouseEvent
+
+public java.awt.event.MouseEvent mouseEvent
+
+
+
+
+
+
+
+key
+
+public char key
+
+
Last key pressed.
+
+ If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT,
+ this will be set to CODED (0xffff or 65535).
+
+
+
+
+
+
+
+keyCode
+
+public int keyCode
+
+
When "key" is set to CODED, this will contain a Java key code.
+
+ For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT.
+ Also available are ALT, CONTROL and SHIFT. A full set of constants
+ can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables.
+
+
+
+
+
+
+
+keyPressed
+
+public boolean keyPressed
+
+
true if the mouse is currently pressed.
+
+
+
+
+
+
+
+keyEvent
+
+public java.awt.event.KeyEvent keyEvent
+
+
the last KeyEvent object passed into a mouse function.
+
+
+
+
+
+
+
+focused
+
+public boolean focused
+
+
Gets set to true/false as the applet gains/loses focus.
+
+
+
+
+
+
+
+online
+
+public boolean online
+
+
true if the applet is online.
+
+ This can be used to test how the applet should behave
+ since online situations are different (no file writing, etc).
+
+
+
+
+
+
+
+frameRate
+
+public float frameRate
+
+
The current value of frames per second.
+
+ The initial value will be 10 fps, and will be updated with each
+ frame thereafter. The value is not instantaneous (since that
+ wouldn't be very useful since it would jump around so much),
+ but is instead averaged (integrated) over several frames.
+ As such, this value won't be valid until after 5-10 frames.
+
+
+
+
+
+
+
+frameCount
+
+public int frameCount
+
+
How many frames have been displayed since the applet started.
+
+ This value is read-only do not attempt to set it,
+ otherwise bad things will happen.
+
+ Inside setup(), frameCount is 0.
+ For the first iteration of draw(), frameCount will equal 1.
+
+
+
+
+
+
+
+finished
+
+public boolean finished
+
+
true if this applet has had it.
+
+
+
+
+
+
+
+ARGS_EDITOR_LOCATION
+
+public static final java.lang.String ARGS_EDITOR_LOCATION
+
+
Position of the upper-lefthand corner of the editor window
+ that launched this applet.
+
+public static final java.lang.String ARGS_EXTERNAL
+
+
Location for where to position the applet window on screen.
+
+ This is used by the editor to when saving the previous applet
+ location, or could be used by other classes to launch at a
+ specific position on-screen.
+
By trial and error, four image loading threads seem to work best when
+ loading images from online. This is consistent with the number of open
+ connections that web browsers will maintain. The variable is made public
+ (however no accessor has been added since it's esoteric) if you really
+ want to have control over the value used. For instance, when loading local
+ files, it might be better to only have a single thread (or two) loading
+ images so that you're disk isn't simply jumping around.
+
+
+
+
+
+
+
+selectedFile
+
+public java.io.File selectedFile
+
+
+
+
+
+
+
+ICON_IMAGE
+
+public static final byte[] ICON_IMAGE
+
+
GIF image of the Processing logo.
+
+
+
+
+
+
+
+
+
+
+
+Constructor Detail
+
+
+
+
+PApplet
+
+public PApplet()
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+init
+
+public void init()
+
+
+
Overrides:
init in class java.applet.Applet
+
+
+
+
+
+
+
+
+getSketchWidth
+
+public int getSketchWidth()
+
+
+
+
+
+
+
+
+
+
+
+getSketchHeight
+
+public int getSketchHeight()
+
+
+
+
+
+
+
+
+
+
+
+getSketchRenderer
+
+public java.lang.String getSketchRenderer()
+
+
+
+
+
+
+
+
+
+
+
+start
+
+public void start()
+
+
Called by the browser or applet viewer to inform this applet that it
+ should start its execution. It is called after the init method and
+ each time the applet is revisited in a Web page.
+
+ Called explicitly via the first call to PApplet.paint(), because
+ PAppletGL needs to have a usable screen before getting things rolling.
+
+
+
Overrides:
start in class java.applet.Applet
+
+
+
+
+
+
+
+
+stop
+
+public void stop()
+
+
Called by the browser or applet viewer to inform
+ this applet that it should stop its execution.
+
+ Unfortunately, there are no guarantees from the Java spec
+ when or if stop() will be called (i.e. on browser quit,
+ or when moving between web pages), and it's not always called.
+
+
+
Overrides:
stop in class java.applet.Applet
+
+
+
+
+
+
+
+
+destroy
+
+public void destroy()
+
+
Called by the browser or applet viewer to inform this applet
+ that it is being reclaimed and that it should destroy
+ any resources that it has allocated.
+
+ This also attempts to call PApplet.stop(), in case there
+ was an inadvertent override of the stop() function by a user.
+
+ destroy() supposedly gets called as the applet viewer
+ is shutting down the applet. stop() is called
+ first, and then destroy() to really get rid of things.
+ no guarantees on when they're run (on browser quit, or
+ when moving between pages), though.
+
Starts up and creates a two-dimensional drawing surface,
+ or resizes the current drawing surface.
+
+ This should be the first thing called inside of setup().
+
+ If using Java 1.3 or later, this will default to using
+ PGraphics2, the Java2D-based renderer. If using Java 1.1,
+ or if PGraphics2 is not available, then PGraphics will be used.
+ To set your own renderer, use the other version of the size()
+ method that takes a renderer as its last parameter.
+
+ If called once a renderer has already been set, this will
+ use the previous renderer and simply resize it.
+
+
+
+
+
+
+
+
+
+
+
+size
+
+public void size(int iwidth,
+ int iheight,
+ java.lang.String irenderer)
Creates a new PGraphics object and sets it to the specified size.
+
+ Note that you cannot change the renderer once outside of setup().
+ In most cases, you can call size() to give it a new size,
+ but you need to always ask for the same renderer, otherwise
+ you're gonna run into trouble.
+
+ The size() method should *only* be called from inside the setup() or
+ draw() methods, so that it is properly run on the main animation thread.
+ To change the size of a PApplet externally, use setSize(), which will
+ update the component size, and queue a resize of the renderer as well.
+
+
+
+
+
+
+
+
+
+
+
+createGraphics
+
+public PGraphicscreateGraphics(int iwidth,
+ int iheight,
+ java.lang.String irenderer)
+
+
Create an offscreen PGraphics object for drawing. This can be used
+ for bitmap or vector images drawing or rendering.
+
+
Do not use "new PGraphicsXxxx()", use this method. This method
+ ensures that internal variables are set up properly that tie the
+ new graphics context back to its parent PApplet.
+
The basic way to create bitmap images is to use the saveFrame()
+ function.
+
If you want to create a really large scene and write that,
+ first make sure that you've allocated a lot of memory in the Preferences.
+
If you want to create images that are larger than the screen,
+ you should create your own PGraphics object, draw to that, and use
+ save().
+ For now, it's best to use P3D in this scenario.
+ P2D is currently disabled, and the JAVA2D default will give mixed
+ results. An example of using P3D:
+
+
+ PGraphics big;
+
+ void setup() {
+ big = createGraphics(3000, 3000, P3D);
+
+ big.beginDraw();
+ big.background(128);
+ big.line(20, 1800, 1800, 900);
+ // etc..
+ big.endDraw();
+
+ // make sure the file is written to the sketch folder
+ big.save("big.tif");
+ }
+
+
+
It's important to always wrap drawing to createGraphics() with
+ beginDraw() and endDraw() (beginFrame() and endFrame() prior to
+ revision 0115). The reason is that the renderer needs to know when
+ drawing has stopped, so that it can update itself internally.
+ This also handles calling the defaults() method, for people familiar
+ with that.
+
It's not possible to use createGraphics() with the OPENGL renderer,
+ because it doesn't allow offscreen use.
+
With Processing 0115 and later, it's possible to write images in
+ formats other than the default .tga and .tiff. The exact formats and
+ background information can be found in the developer's reference for
+ PImage.save().
+
Create an offscreen graphics surface for drawing, in this case
+ for a renderer that writes to a file (such as PDF or DXF).
+
+
+
+
+
+
Parameters:
ipath - can be an absolute or relative path
+
+
+
+
+
+createImage
+
+public PImagecreateImage(int wide,
+ int high,
+ int format)
+
+
Preferred method of creating new PImage objects, ensures that a
+ reference to the parent PApplet is included, which makes save() work
+ without needing an absolute path.
+
If you override this or any function that takes a "MouseEvent e"
+ without calling its super.mouseXxxx() then mouseX, mouseY,
+ mousePressed, and mouseEvent will no longer be set.
+
+
+
Specified by:
mousePressed in interface java.awt.event.MouseListener
mouseMoved in interface java.awt.event.MouseMotionListener
+
+
+
+
+
+
+
+
+mousePressed
+
+public void mousePressed()
+
+
Mouse has been pressed, and should be considered "down"
+ until mouseReleased() is called. If you must, use
+ int button = mouseEvent.getButton();
+ to figure out which button was clicked. It will be one of:
+ MouseEvent.BUTTON1, MouseEvent.BUTTON2, MouseEvent.BUTTON3
+ Note, however, that this is completely inconsistent across
+ platforms.
+
+
+
+
+
+
+
+
+
+
+
+mouseReleased
+
+public void mouseReleased()
+
+
Mouse button has been released.
+
+
+
+
+
+
+
+
+
+
+
+mouseClicked
+
+public void mouseClicked()
+
+
When the mouse is clicked, mousePressed() will be called,
+ then mouseReleased(), then mouseClicked(). Note that
+ mousePressed is already false inside of mouseClicked().
+
+
+
+
+
+
+
+
+
+
+
+mouseDragged
+
+public void mouseDragged()
+
+
Mouse button is pressed and the mouse has been dragged.
+
+
+
+
+
+
+
+
+
+
+
+mouseMoved
+
+public void mouseMoved()
+
+
Mouse button is not pressed but the mouse has changed locations.
+
Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
+ 'keyCode', and 'keyEvent' variables to no longer work;
+ key events will no longer be queued until the end of draw();
+ and the keyPressed(), keyReleased() and keyTyped() methods
+ will no longer be called.
+
+
+
Specified by:
keyPressed in interface java.awt.event.KeyListener
keyReleased in interface java.awt.event.KeyListener
+
+
+
+
+
+
+
+
+keyTyped
+
+public void keyTyped(java.awt.event.KeyEvent e)
+
+
+
Specified by:
keyTyped in interface java.awt.event.KeyListener
+
+
+
+
+
+
+
+
+keyPressed
+
+public void keyPressed()
+
+
Called each time a single key on the keyboard is pressed.
+ Because of how operating systems handle key repeats, holding
+ down a key will cause multiple calls to keyPressed(), because
+ the OS repeat takes over.
+
+ Examples for key handling:
+ (Tested on Windows XP, please notify if different on other
+ platforms, I have a feeling Mac OS and Linux may do otherwise)
+
+ 1. Pressing 'a' on the keyboard:
+ keyPressed with key == 'a' and keyCode == 'A'
+ keyTyped with key == 'a' and keyCode == 0
+ keyReleased with key == 'a' and keyCode == 'A'
+
+ 2. Pressing 'A' on the keyboard:
+ keyPressed with key == 'A' and keyCode == 'A'
+ keyTyped with key == 'A' and keyCode == 0
+ keyReleased with key == 'A' and keyCode == 'A'
+
+ 3. Pressing 'shift', then 'a' on the keyboard (caps lock is off):
+ keyPressed with key == CODED and keyCode == SHIFT
+ keyPressed with key == 'A' and keyCode == 'A'
+ keyTyped with key == 'A' and keyCode == 0
+ keyReleased with key == 'A' and keyCode == 'A'
+ keyReleased with key == CODED and keyCode == SHIFT
+
+ 4. Holding down the 'a' key.
+ The following will happen several times,
+ depending on your machine's "key repeat rate" settings:
+ keyPressed with key == 'a' and keyCode == 'A'
+ keyTyped with key == 'a' and keyCode == 0
+ When you finally let go, you'll get:
+ keyReleased with key == 'a' and keyCode == 'A'
+
+ 5. Pressing and releasing the 'shift' key
+ keyPressed with key == CODED and keyCode == SHIFT
+ keyReleased with key == CODED and keyCode == SHIFT
+ (note there is no keyTyped)
+
+ 6. Pressing the tab key in an applet with Java 1.4 will
+ normally do nothing, but PApplet dynamically shuts
+ this behavior off if Java 1.4 is in use (tested 1.4.2_05 Windows).
+ Java 1.1 (Microsoft VM) passes the TAB key through normally.
+ Not tested on other platforms or for 1.3.
+
+
+
+
+
+
+
+
+
+
+
+
+keyReleased
+
+public void keyReleased()
+
+
See keyPressed().
+
+
+
+
+
+
+
+
+
+
+
+keyTyped
+
+public void keyTyped()
+
+
Only called for "regular" keys like letters,
+ see keyPressed() for full documentation.
+
focusLost in interface java.awt.event.FocusListener
+
+
+
+
+
+
+
+
+millis
+
+public int millis()
+
+
Get the number of milliseconds since the applet started.
+
+ This is a function, rather than a variable, because it may
+ change multiple times per frame.
+
+
+
+
+
+
+
+
+
+
+
+second
+
+public static int second()
+
+
Seconds position of the current time.
+
+
+
+
+
+
+
+
+
+
+
+minute
+
+public static int minute()
+
+
Minutes position of the current time.
+
+
+
+
+
+
+
+
+
+
+
+hour
+
+public static int hour()
+
+
Hour position of the current time in international format (0-23).
+
+ To convert this value to American time:
+
int yankeeHour = (hour() % 12);
+ if (yankeeHour == 0) yankeeHour = 12;
+
+
+
+
+
+
+
+
+
+
+
+day
+
+public static int day()
+
+
Get the current day of the month (1 through 31).
+
+ If you're looking for the day of the week (M-F or whatever)
+ or day of the year (1..365) then use java's Calendar.get()
+
+
+
+
+
+
+
+
+
+
+
+month
+
+public static int month()
+
+
Get the current month in range 1 through 12.
+
+
+
+
+
+
+
+
+
+
+
+year
+
+public static int year()
+
+
Get the current year.
+
+
+
+
+
+
+
+
+
+
+
+delay
+
+public void delay(int napTime)
+
+
The delay() function causes the program to halt for a specified time.
+ Delay times are specified in thousandths of a second. For example,
+ running delay(3000) will stop the program for three seconds and
+ delay(500) will stop the program for a half-second. Remember: the
+ display window is updated only at the end of draw(), so putting more
+ than one delay() inside draw() will simply add them together and the new
+ frame will be drawn when the total delay is over.
+
+ I'm not sure if this is even helpful anymore, as the screen isn't
+ updated before or after the delay, meaning which means it just
+ makes the app lock up temporarily.
+
+
+
+
+
+
+
+
+
+
+
+frameRate
+
+public void frameRate(float newRateTarget)
+
+
Set a target frameRate. This will cause delay() to be called
+ after each frame so that the sketch synchronizes to a particular speed.
+ Note that this only sets the maximum frame rate, it cannot be used to
+ make a slow sketch go faster. Sketches have no default frame rate
+ setting, and will attempt to use maximum processor power to achieve
+ maximum speed.
+
Get a param from the web page, or (eventually)
+ from a properties file.
+
+
+
+
+
+
+
+
+
+
+
+status
+
+public void status(java.lang.String what)
+
+
Show status in the status bar of a web browser, or in the
+ System.out console. Eventually this might show status in the
+ p5 environment itself, rather than relying on the console.
+
Launch a process using a platforms shell. This version uses an array
+ to make it easier to deal with spaces in the individual elements.
+ (This avoids the situation of trying to put single or double quotes
+ around different bits).
+
Same as above but with an exception. Also needs work.
+
+
+
+
+
+
+
+
+
+
+
+exit
+
+public void exit()
+
+
Call to safely exit the sketch when finished. For instance,
+ to render a single frame, save it, and quit.
+
+
+
+
+
+
+
+
+
+
+
+save
+
+public void save(java.lang.String filename)
+
+
Intercepts any relative paths to make them absolute (relative
+ to the sketch folder) before passing to save() in PImage.
+ (Changed in 0100)
+
+
+
+
+
+
+
+
+
+
+
+saveFrame
+
+public void saveFrame()
+
+
Grab an image of what's currently in the drawing area and save it
+ as a .tif or .tga file.
+
+ Best used just before endDraw() at the end of your draw().
+ This can only create .tif or .tga images, so if neither extension
+ is specified it defaults to writing a tiff and adds a .tif suffix.
+
+
+
+
+
+
+
+
+
+
+
+saveFrame
+
+public void saveFrame(java.lang.String what)
+
+
Save the current frame as a .tif or .tga image.
+
+ The String passed in can contain a series of # signs
+ that will be replaced with the screengrab number.
+
+ i.e. saveFrame("blah-####.tif");
+ // saves a numbered tiff image, replacing the
+ // #### signs with zeros and the frame number
Replace the cursor with the specified PImage. The x- and y-
+ coordinate of the center will be the center of the image.
+
+
+
+
+
+
+
+
+
+
+
+cursor
+
+public void cursor(PImage image,
+ int hotspotX,
+ int hotspotY)
+
+
Set a custom cursor to an image with a specific hotspot.
+ Only works with JDK 1.2 and later.
+ Currently seems to be broken on Java 1.4 for Mac OS X
+
+ Based on code contributed by Amit Pitaru, plus additional
+ code to handle Java versions via reflection by Jonathan Feinberg.
+ Reflection removed for release 0128 and later.
+
+
+
+
+
+
+
+
+
+
+
+cursor
+
+public void cursor()
+
+
Show the cursor after noCursor() was called.
+ Notice that the program remembers the last set cursor type
+
+
+
+
+
+
+
+
+
+
+
+noCursor
+
+public void noCursor()
+
+
Hide the cursor by creating a transparent image
+ and using it as a custom cursor.
+
Normalize a value to exist between 0 and 1 (inclusive).
+ Mathematically the opposite of lerp(), figures out what proportion
+ a particular value is relative to start and stop coordinates.
+
Convenience function to map a variable from one coordinate space
+ to another. Equivalent to unlerp() followed by lerp().
+
+
+
+
+
+
+
+
+
+
+
+random
+
+public final float random(float howbig)
+
+
Return a random number in the range [0, howbig).
+
+ The number returned will range from zero up to
+ (but not including) 'howbig'.
+
+
+
+
+
+
+
+
+
+
+
+random
+
+public final float random(float howsmall,
+ float howbig)
+
+
Return a random number in the range [howsmall, howbig).
+
+ The number returned will range from 'howsmall' up to
+ (but not including 'howbig'.
+
+ If howsmall is >= howbig, howsmall will be returned,
+ meaning that random(5, 5) will return 5 (useful)
+ and random(7, 4) will return 7 (not useful.. better idea?)
+
+
+
+
+
+
+
+
+
+
+
+randomSeed
+
+public final void randomSeed(long what)
+
+
+
+
+
+
+
+
+
+
+
+noise
+
+public float noise(float x)
+
+
Computes the Perlin noise function value at point x.
+
+
+
+
+
+
+
+
+
+
+
+noise
+
+public float noise(float x,
+ float y)
+
+
Computes the Perlin noise function value at the point x, y.
+
+
+
+
+
+
+
+
+
+
+
+noise
+
+public float noise(float x,
+ float y,
+ float z)
+
+
Computes the Perlin noise function value at x, y, z.
+
Load an image from the data folder or a local directory.
+ Supports .gif (including transparency), .tga, and .jpg images.
+ In Java 1.3 or later, .png images are
+
+ also supported.
+
+ Generally, loadImage() should only be used during setup, because
+ re-loading images inside draw() is likely to cause a significant
+ delay while memory is allocated and the thread blocks while waiting
+ for the image to load because loading is not asynchronous.
+
+ To load several images asynchronously, see more information in the
+ FAQ about writing your own threaded image loading method.
+
+ As of 0096, returns null if no image of that name is found,
+ rather than an error.
+
+ Release 0115 also provides support for reading TIFF and RLE-encoded
+ Targa (.tga) files written by Processing via save() and saveFrame().
+ Other TIFF and Targa files will probably not load, use a different
+ format (gif, jpg and png are safest bets) when creating images with
+ another application to use with Processing.
+
+ Also in release 0115, more image formats (BMP and others) can
+ be read when using Java 1.4 and later. Because many people still
+ use Java 1.1 and 1.3, these formats are not recommended for
+ work that will be posted on the web. To get a list of possible
+ image formats for use with Java 1.4 and later, use the following:
+ println(javax.imageio.ImageIO.getReaderFormatNames())
+
+ Images are loaded via a byte array that is passed to
+ Toolkit.createImage(). Unfortunately, we cannot use Applet.getImage()
+ because it takes a URL argument, which would be a pain in the a--
+ to make work consistently for online and local sketches.
+ Sometimes this causes problems, resulting in issues like
+ Bug 279
+ and
+ Bug 305.
+ In release 0115, everything was instead run through javax.imageio,
+ but that turned out to be very slow, see
+ Bug 392.
+ As a result, starting with 0116, the following happens:
+
+
TGA and TIFF images are loaded using the internal load methods.
+
JPG, GIF, and PNG images are loaded via loadBytes().
+
If the image still isn't loaded, it's passed to javax.imageio.
+
+ For releases 0116 and later, if you have problems such as those seen
+ in Bugs 279 and 305, use Applet.getImage() instead. You'll be stuck
+ with the limitations of getImage() (the headache of dealing with
+ online/offline use). Set up your own MediaTracker, and pass the resulting
+ java.awt.Image to the PImage constructor that takes an AWT image.
+
Create a .vlw font on the fly from either a font name that's
+ installed on the system, or from a .ttf or .otf that's inside
+ the data folder of this sketch.
+
+ Only works with Java 1.3 or later. Many .otf fonts don't seem
+ to be supported by Java, perhaps because they're CFF based?
+
+ Font names are inconsistent across platforms and Java versions.
+ On Mac OS X, Java 1.3 uses the font menu name of the font,
+ whereas Java 1.4 uses the PostScript name of the font. Java 1.4
+ on OS X will also accept the font menu name as well. On Windows,
+ it appears that only the menu names are used, no matter what
+ Java version is in use. Naming system unknown/untested for 1.5.
+
+ Use 'null' for the charset if you want to use any of the 65,536
+ unicode characters that exist in the font. Note that this can
+ produce an enormous file or may cause an OutOfMemoryError.
+
+
+
+
+
+
+
+
+
+
+
+selectInput
+
+public java.lang.String selectInput()
+
+
Open a platform-specific file chooser dialog to select a file for input.
+
+
+
+
+
+
+
Returns:
full path to the selected file, or null if no selection.
+ This method is useful if you want to use the facilities provided
+ by PApplet to easily open things from the data folder or from a URL,
+ but want an InputStream object so that you can use other Java
+ methods to take more control of how the stream is read.
+
+ If the requested item doesn't exist, null is returned.
+ (Prior to 0096, die() would be called, killing the applet)
+
+ For 0096+, the "data" folder is exported intact with subfolders,
+ and openStream() properly handles subdirectories from the data folder
+
+ If not online, this will also check to see if the user is asking
+ for a file whose name isn't properly capitalized. This helps prevent
+ issues when a sketch is exported to the web, where case sensitivity
+ matters, as opposed to Windows and the Mac OS default where
+ case sensitivity is preserved but ignored.
+
+ It is strongly recommended that libraries use this method to open
+ data files, so that the loading sequence is handled in the same way
+ as functions like loadBytes(), loadImage(), etc.
+
+ The filename passed in can be:
+
+
A URL, for instance openStream("http://processing.org/");
+
A file in the sketch's data folder
+
Another file to be opened locally (when running as an application)
+
Load data from a file and shove it into a String array.
+
+ Exceptions are handled internally, when an error, occurs, an
+ exception is printed to the console and 'null' is returned,
+ but the program continues running. This is a tradeoff between
+ 1) showing the user that there was a problem but 2) not requiring
+ that all i/o code is contained in try/catch blocks, for the sake
+ of new users (or people who are just trying to get things done
+ in a "scripting" fashion. If you want to handle exceptions,
+ use Java methods for I/O.
+
Similar to createInput() (formerly openStream), this creates a Java
+ OutputStream for a given filename or path. The file will be created in
+ the sketch folder, or in the same folder as an exported application.
+
+ If the path does not exist, intermediate folders will be created. If an
+ exception occurs, it will be printed to the console, and null will be
+ returned.
+
+ Future releases may also add support for handling HTTP POST via this
+ method (for better symmetry with createInput), however that's maybe a
+ little too clever (and then we'd have to add the same features to the
+ other file functions like createWriter). Who you callin' bloated?
+
Save the contents of a stream to a file in the sketch folder.
+ This is basically saveBytes(blah, loadBytes()), but done
+ more efficiently (and with less confusing syntax).
+
Identical to the other saveStream(), but writes to a File
+ object, for greater control over the file location.
+ Note that unlike other api methods, this will not automatically
+ compress or uncompress gzip files.
+
Saves bytes to a file to inside the sketch folder.
+ The filename can be a relative path, i.e. "poo/bytefun.txt"
+ would save to a file named "bytefun.txt" to a subfolder
+ called 'poo' inside the sketch folder. If the in-between
+ subfolders don't exist, they'll be created.
+
Prepend the sketch folder path to the filename (or path) that is
+ passed in. External libraries should use this function to save to
+ the sketch folder.
+
+ Note that when running as an applet inside a web browser,
+ the sketchPath will be set to null, because security restrictions
+ prevent applets from accessing that information.
+
+ This will also cause an error if the sketch is not inited properly,
+ meaning that init() was never called on the PApplet when hosted
+ my some other main() or by other code. For proper use of init(),
+ see the examples in the main description text for PApplet.
+
Returns a path inside the applet folder to save to. Like sketchPath(),
+ but creates any in-between folders so that things save properly.
+
+ All saveXxxx() functions use the path to the sketch folder, rather than
+ its data folder. Once exported, the data folder will be found inside the
+ jar file of the exported application or applet. In this case, it's not
+ possible to save data into the jar file, because it will often be running
+ from a server, or marked in-use if running from a local file system.
+ With this in mind, saving to the data path doesn't make sense anyway.
+ If you know you're running locally, and want to save to the data folder,
+ use saveXxxx("data/blah.dat").
+
Return a full path to an item in the data folder.
+
+ In this method, the data path is defined not as the applet's actual
+ data path, but a folder titled "data" in the sketch's working
+ directory. When running inside the PDE, this will be the sketch's
+ "data" folder. However, when exported (as application or applet),
+ sketch's data folder is exported as part of the applications jar file,
+ and it's not possible to read/write from the jar file in a generic way.
+ If you need to read data from the jar file, you should use createInput().
+
Takes a path and creates any in-between folders if they don't
+ already exist. Useful when trying to save to a subfolder that
+ may not actually exist.
+
+
+
+
+
+
+
+
+
+
+
+createPath
+
+public static void createPath(java.io.File file)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static byte[] sort(byte[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static byte[] sort(byte[] what,
+ int count)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static char[] sort(char[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static char[] sort(char[] what,
+ int count)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static int[] sort(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static int[] sort(int[] what,
+ int count)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static float[] sort(float[] what)
+
+
+
+
+
+
+
+
+
+
+
+sort
+
+public static float[] sort(float[] what,
+ int count)
Remove whitespace characters from the beginning and ending
+ of a String. Works like String.trim() but includes the
+ unicode nbsp character as well.
+
Split the provided String at wherever whitespace occurs.
+ Multiple whitespace (extra spaces or tabs or whatever)
+ between items will count as a single break.
+
+ The whitespace characters are "\t\n\r\f", which are the defaults
+ for java.util.StringTokenizer, plus the unicode non-breaking space
+ character, which is found commonly on files created by or used
+ in conjunction with Mac OS X (character 160, or 0x00A0 in hex).
+
Splits a string into pieces, using any of the chars in the
+ String 'delim' as separator characters. For instance,
+ in addition to white space, you might want to treat commas
+ as a separator. The delimeter characters won't appear in
+ the returned String array.
+
Split a string into pieces along a specific character.
+ Most commonly used to break up a String along a space or a tab
+ character.
+
+ This operates differently than the others, where the
+ single delimeter is the only breaking point, and consecutive
+ delimeters will produce an empty string (""). This way,
+ one can split on tab characters, but maintain the column
+ alignments (of say an excel file) where there are empty columns.
+
Split a String on a specific delimiter. Unlike Java's String.split()
+ method, this does not parse the delimiter as a regexp because it's more
+ confusing than necessary, and String.split() is always available for
+ those who want regexp.
+
Match a string with a regular expression, and returns the match as an
+ array. The first index is the matching expression, and array elements
+ [1] and higher represent each of the groups (sequences found in parens).
+
+ This uses multiline matching (Pattern.MULTILINE) and dotall mode
+ (Pattern.DOTALL) by default, so that ^ and $ match the beginning and
+ end of any lines found in the source, and the . operator will also
+ pick up newline characters.
+
Identical to match(), except that it returns an array of all matches in
+ the specified String, rather than just the first.
+
+
+
+
+
+
+
+
+
+
+
+parseBoolean
+
+public static final boolean parseBoolean(int what)
+
+
Convert an integer to a boolean. Because of how Java handles upgrading
+ numbers, this will also cover byte and char (as they will upgrade to
+ an int without any sort of explicit cast).
+
The preprocessor will convert boolean(what) to parseBoolean(what).
+
+
+
+
+
+
+
Returns:
false if 0, true if any other number
+
+
+
+
+
+parseBoolean
+
+public static final boolean parseBoolean(java.lang.String what)
+
+
Convert the string "true" or "false" to a boolean.
+
+
+
+
+
+
+
Returns:
true if 'what' is "true" or "TRUE", false otherwise
+
+
+
+
+
+parseBoolean
+
+public static final boolean[] parseBoolean(byte[] what)
+
+
Convert a byte array to a boolean array. Each element will be
+ evaluated identical to the integer case, where a byte equal
+ to zero will return false, and any other value will return true.
+
+
+
+
+
+
+
Returns:
array of boolean elements
+
+
+
+
+
+parseBoolean
+
+public static final boolean[] parseBoolean(int[] what)
+
+
Convert an int array to a boolean array. An int equal
+ to zero will return false, and any other value will return true.
+
+
+
+
+
+
+
Returns:
array of boolean elements
+
+
+
+
+
+parseBoolean
+
+public static final boolean[] parseBoolean(java.lang.String[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(boolean what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(char what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(int what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte parseByte(float what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(boolean[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(char[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final byte[] parseByte(float[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char parseChar(byte what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char parseChar(int what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char[] parseChar(byte[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseChar
+
+public static final char[] parseChar(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(boolean what)
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(byte what)
+
+
Note that parseInt() will un-sign a signed byte value.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(char what)
+
+
Note that parseInt('5') is unlike String in the sense that it
+ won't return 5, but the ascii value. This is because ((int) someChar)
+ returns the ascii value, and parseInt() is just longhand for the cast.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(float what)
+
+
Same as floor(), or an (int) cast.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(java.lang.String what)
+
+
Parse a String into an int value. Returns 0 if the value is bad.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int parseInt(java.lang.String what,
+ int otherwise)
+
+
Parse a String to an int, and provide an alternate value that
+ should be used when the number is invalid.
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static final int[] parseInt(boolean[] what)
Make an array of int elements from an array of String objects.
+ If the String can't be parsed as a number, it will be set to zero.
+
+ String s[] = { "1", "300", "44" };
+ int numbers[] = parseInt(s);
+
+ numbers will contain { 1, 300, 44 }
+
+
+
+
+
+
+
+
+
+
+
+parseInt
+
+public static int[] parseInt(java.lang.String[] what,
+ int missing)
+
+
Make an array of int elements from an array of String objects.
+ If the String can't be parsed as a number, its entry in the
+ array will be set to the value of the "missing" parameter.
+
+ String s[] = { "1", "300", "apple", "44" };
+ int numbers[] = parseInt(s, 9999);
+
+ numbers will contain { 1, 300, 9999, 44 }
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float parseFloat(int what)
+
+
Convert an int to a float value. Also handles bytes because of
+ Java's rules for upgrading values.
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float parseFloat(java.lang.String what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float parseFloat(java.lang.String what,
+ float otherwise)
+
+
+
+
+
+
+
+
+
+
+
+parseByte
+
+public static final float[] parseByte(byte[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float[] parseFloat(int[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float[] parseFloat(java.lang.String[] what)
+
+
+
+
+
+
+
+
+
+
+
+parseFloat
+
+public static final float[] parseFloat(java.lang.String[] what,
+ float missing)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(boolean x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(byte x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(char x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(int x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String str(float x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(boolean[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(byte[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(char[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(int[] x)
+
+
+
+
+
+
+
+
+
+
+
+str
+
+public static final java.lang.String[] str(float[] x)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String[] nf(int[] num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String nf(int num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String[] nfc(int[] num)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String nfc(int num)
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String nfs(int num,
+ int digits)
+
+
number format signed (or space)
+ Formats a number but leaves a blank space in the front
+ when it's positive so that it can be properly aligned with
+ numbers that have a negative sign in front of them.
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String[] nfs(int[] num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String nfp(int num,
+ int digits)
+
+
number format positive (or plus)
+ Formats a number, always placing a - or + sign
+ in the front when it's negative or positive.
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String[] nfp(int[] num,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String[] nf(float[] num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nf
+
+public static java.lang.String nf(float num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String[] nfc(float[] num,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfc
+
+public static java.lang.String nfc(float num,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String[] nfs(float[] num,
+ int left,
+ int right)
+
+
Number formatter that takes into account whether the number
+ has a sign (positive, negative, etc) in front of it.
+
+
+
+
+
+
+
+
+
+
+
+nfs
+
+public static java.lang.String nfs(float num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String[] nfp(float[] num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+nfp
+
+public static java.lang.String nfp(float num,
+ int left,
+ int right)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(byte what)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(char what)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(int what)
+
+
+
+
+
+
+
+
+
+
+
+hex
+
+public static final java.lang.String hex(int what,
+ int digits)
+
+
+
+
+
+
+
+
+
+
+
+unhex
+
+public static final int unhex(java.lang.String what)
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(byte what)
+
+
Returns a String that contains the binary value of a byte.
+ The returned value will always have 8 digits.
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(char what)
+
+
Returns a String that contains the binary value of a char.
+ The returned value will always have 16 digits because chars
+ are two bytes long.
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(int what)
+
+
Returns a String that contains the binary value of an int.
+ The length depends on the size of the number itself.
+ An int can be up to 32 binary digits, but that seems like
+ overkill for almost any situation, so this function just
+ auto-size. If you want a specific number of digits (like all 32)
+ use binary(int what, int digits) to specify how many digits.
+
+
+
+
+
+
+
+
+
+
+
+binary
+
+public static final java.lang.String binary(int what,
+ int digits)
+
+
Returns a String that contains the binary value of an int.
+ The digits parameter determines how many digits will be used.
+
+
+
+
+
+
+
+
+
+
+
+unbinary
+
+public static final int unbinary(java.lang.String what)
+
+
Unpack a binary String into an int.
+ i.e. unbinary("00001000") would return 8.
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int gray)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float fgray)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int gray,
+ int alpha)
+
+
As of 0116 this also takes color(#FF8800, alpha)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float fgray,
+ float falpha)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int x,
+ int y,
+ int z)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float x,
+ float y,
+ float z)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(int x,
+ int y,
+ int z,
+ int a)
+
+
+
+
+
+
+
+
+
+
+
+color
+
+public final int color(float x,
+ float y,
+ float z,
+ float a)
+
+
+
+
+
+
+
+
+
+
+
+setupExternalMessages
+
+public void setupExternalMessages()
+
+
Set this sketch to communicate its state back to the PDE.
+
+ This uses the stderr stream to write positions of the window
+ (so that it will be saved by the PDE for the next run) and
+ notify on quit. See more notes in the Worker class.
+
+
+
+
+
+
+
+
+
+
+
+setupFrameResizeListener
+
+public void setupFrameResizeListener()
+
+
Set up a listener that will fire proper component resize events
+ in cases where frame.setResizable(true) is called.
+
+
+
+
+
+
+
+
+
+
+
+main
+
+public static void main(java.lang.String[] args)
+
+
main() method for running this class from the command line.
+
+ The options shown here are not yet finalized and will be
+ changing over the next several releases.
+
+ The simplest way to turn and applet into an application is to
+ add the following code to your program:
+
+ This will properly launch your applet from a double-clickable
+ .jar or from the command line.
+
+ Parameters useful for launching or also used by the PDE:
+
+ --location=x,y upper-lefthand corner of where the applet
+ should appear on screen. if not used,
+ the default is to center on the main screen.
+
+ --present put the applet into full screen presentation
+ mode. requires java 1.4 or later.
+
+ --exclusive use full screen exclusive mode when presenting.
+ disables new windows or interaction with other
+ monitors, this is like a "game" mode.
+
+ --hide-stop use to hide the stop button in situations where
+ you don't want to allow users to exit. also
+ see the FAQ on information for capturing the ESC
+ key when running in presentation mode.
+
+ --stop-color=#xxxxxx color of the 'stop' text used to quit an
+ sketch when it's in present mode.
+
+ --bgcolor=#xxxxxx background color of the window.
+
+ --sketch-path location of where to save files from functions
+ like saveStrings() or saveFrame(). defaults to
+ the folder that the java application was
+ launched from, which means if this isn't set by
+ the pde, everything goes into the same folder
+ as processing.exe.
+
+ --display=n set what display should be used by this applet.
+ displays are numbered starting from 1.
+
+ Parameters used by Processing when running via the PDE
+
+ --external set when the applet is being used by the PDE
+
+ --editor-location=x,y position of the upper-lefthand corner of the
+ editor window, for placement of applet window
+
Begin recording raw shape data to a renderer of the specified type,
+ using the width and height of the main drawing surface.
+
+ If hashmarks (###) are found in the filename, they'll be replaced
+ by the current frame number (frameCount).
+
Begin recording raw shape data to the specified renderer.
+
+ This simply echoes to g.beginRaw(), but since is placed here (rather than
+ generated by preproc.pl) for clarity and so that it doesn't echo the
+ command should beginRecord() be in use.
+
+
+
+
+
+
+
+
+
+
+
+endRaw
+
+public void endRaw()
+
+
Stop recording raw shape data to the specified renderer.
+
+ This simply echoes to g.beginRaw(), but since is placed here (rather than
+ generated by preproc.pl) for clarity and so that it doesn't echo the
+ command should beginRecord() be in use.
+
+
+
+
+
+
+
+
+
+
+
+loadPixels
+
+public void loadPixels()
+
+
Override the g.pixels[] function to set the pixels[] array
+ that's part of the PApplet object. Allows the use of
+ pixels[] in the code, rather than g.pixels[].
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels()
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels(int x1,
+ int y1,
+ int x2,
+ int y2)
+ An attempt is made to keep the constants as short/non-verbose
+ as possible. For instance, the constant is TIFF instead of
+ FILE_TYPE_TIFF. We'll do this as long as we can get away with it.
+
MAX_FLOAT
+
+
+ Same as Float.MAX_VALUE, but included for parity with MIN_VALUE,
+ and to avoid teaching static methods on the first day.
+
+
+
+static int
+
MAX_INT
+
+
+ Largest possible (positive) integer value
+
+
+
+static float
+
MIN_FLOAT
+
+
+ Note that Float.MIN_VALUE is the smallest positive value
+ for a floating point number, not actually the minimum (negative) value
+ for a float.
+
+
+
+static int
+
MIN_INT
+
+
+ Smallest possible (negative) integer value
Note that Float.MIN_VALUE is the smallest positive value
+ for a floating point number, not actually the minimum (negative) value
+ for a float. This constant equals 0xFF7FFFFF, the smallest (farthest
+ negative) value a float can have before it hits NaN.
+
textMode(MODEL) is the default, meaning that characters
+ will be affected by transformations like any other shapes.
+
+ Changed value in 0093 to not interfere with LEFT, CENTER, and RIGHT.
+
textMode(SHAPE) draws text using the the glyph outlines of
+ individual characters rather than as textures. If the outlines are
+ not available, then textMode(SHAPE) will be ignored and textMode(MODEL)
+ will be used instead. For this reason, be sure to call textMode()
+ after calling textFont().
+
+ Currently, textMode(SHAPE) is only supported by OPENGL mode.
+ It also requires Java 1.2 or higher (OPENGL requires 1.4 anyway)
+
+Grayscale bitmap font class used by Processing.
+
+ Awful (and by that, I mean awesome) ascii (non)art for how this works:
+
+ |
+ | height is the full used height of the image
+ |
+ | ..XX.. }
+ | ..XX.. }
+ | ...... }
+ | XXXX.. } topExtent (top y is baseline - topExtent)
+ | ..XX.. }
+ | ..XX.. } dotted areas are where the image data
+ | ..XX.. } is actually located for the character
+ +---XXXXXX---- } (it extends to the right and down
+ | for power of two texture sizes)
+ ^^^^ leftExtent (amount to move over before drawing the image
+
+ ^^^^^^^^^^^^^^ setWidth (width displaced by char)
+
Name of the font as seen by Java when it was created.
+ If the font is available, the native version will be used.
+
+
+
+
+
+
+
+psname
+
+public java.lang.String psname
+
+
Postscript name of the font that this bitmap was created from.
+
+
+
+
+
+
+
+size
+
+public int size
+
+
"natural" size of the font (most often 48)
+
+
+
+
+
+
+
+smooth
+
+public boolean smooth
+
+
true if smoothing was enabled for this font, used for native impl
+
+
+
+
+
+
+
+mbox2
+
+public int mbox2
+
+
next power of 2 over the max image size (usually 64)
+
+
+
+
+
+
+
+twidth
+
+public int twidth
+
+
texture width, same as mbox2, but reserved for future use
+
+
+
+
+
+
+
+theight
+
+public int theight
+
+
texture height, same as mbox2, but reserved for future use
+
+
+
+
+
+
+
+value
+
+public int[] value
+
+
+
+
+
+
+
+height
+
+public int[] height
+
+
+
+
+
+
+
+width
+
+public int[] width
+
+
+
+
+
+
+
+setWidth
+
+public int[] setWidth
+
+
+
+
+
+
+
+topExtent
+
+public int[] topExtent
+
+
+
+
+
+
+
+leftExtent
+
+public int[] leftExtent
+
+
+
+
+
+
+
+ascent
+
+public int ascent
+
+
+
+
+
+
+
+descent
+
+public int descent
+
+
+
+
+
+
+
+DEFAULT_CHARSET
+
+public static char[] DEFAULT_CHARSET
+
+
The default Processing character set.
+
+ This is the union of the Mac Roman and Windows ANSI (CP1250)
+ character sets. ISO 8859-1 Latin 1 is Unicode characters 0x80 -> 0xFF,
+ and would seem a good standard, but in practice, most P5 users would
+ rather have characters that they expect from their platform's fonts.
+
+ This is more of an interim solution until a much better
+ font solution can be determined. (i.e. create fonts on
+ the fly from some sort of vector format).
+
+ This is used by the Create Font tool, or whatever anyone else dreams
+ up for messing with fonts themselves.
+
+ It is assumed that the calling class will handle closing
+ the stream when finished.
+
+
+
+
+
+
+
Throws:
+
java.io.IOException
+
+
+
+
+
+index
+
+public int index(char c)
+
+
Get index for the char (convert from unicode to bagel charset).
+
+
+
+
+
+
+
Returns:
index into arrays or -1 if not found
+
+
+
+
+
+kern
+
+public float kern(char a,
+ char b)
+
+
Currently un-implemented for .vlw fonts,
+ but honored for layout in case subclasses use it.
+
+
+
+
+
+
+
+
+
+
+
+ascent
+
+public float ascent()
+
+
Returns the ascent of this font from the baseline.
+ The value is based on a font of size 1.
+
+
+
+
+
+
+
+
+
+
+
+descent
+
+public float descent()
+
+
Returns how far this font descends from the baseline.
+ The value is based on a font size of 1.
+
+
+
+
+
+
+
+
+
+
+
+width
+
+public float width(char c)
+
+
Width of this character for a font of size 1.
+
+
+
+
+
+
+
+
+
+
+
+list
+
+public static java.lang.String[] list()
+
+
Get a list of the fonts installed on the system that can be used
+ by Java. Not all fonts can be used in Java, in fact it's mostly
+ only TrueType fonts. OpenType fonts with CFF data such as Adobe's
+ OpenType fonts seem to have trouble (even though they're sort of
+ TrueType fonts as well, or may have a .ttf extension). Regular
+ PostScript fonts seem to work OK, however.
+
+ Not recommended for use in applets, but this is implemented
+ in PFont because the Java methods to access this information
+ have changed between 1.1 and 1.4, and the 1.4 method is
+ typical of the sort of undergraduate-level over-abstraction
+ that the seems to have made its way into the Java API after 1.1.
+
Starting with Java 1.5, Apple broke the ability to specify most fonts.
+ This has been filed as bug #4769141 at bugreporter.apple.com. More info at
+ Bug 407.
+
+Main graphics and rendering context, as well as the base API implementation.
+
+
Subclassing and initializing PGraphics objects
+ Starting in release 0149, subclasses of PGraphics are handled differently.
+ The constructor for subclasses takes no parameters, instead a series of
+ functions are called by the hosting PApplet to specify its attributes.
+
+
setParent(PApplet) - is called to specify the parent PApplet.
+
setPrimary(boolean) - called with true if this PGraphics will be the
+ primary drawing surface used by the sketch, or false if not.
+
setPath(String) - called when the renderer needs a filename or output
+ path, such as with the PDF or DXF renderers.
+
setSize(int, int) - this is called last, at which point it's safe for
+ the renderer to complete its initialization routine.
+
+ The functions were broken out because of the growing number of parameters
+ such as these that might be used by a renderer, yet with the exception of
+ setSize(), it's not clear which will be necessary. So while the size could
+ be passed in to the constructor instead of a setSize() function, a function
+ would still be needed that would notify the renderer that it was time to
+ finish its initialization. Thus, setSize() simply does both.
+
+
Know your rights: public vs. private methods
+ Methods that are protected are often subclassed by other renderers, however
+ they are not set 'public' because they shouldn't be part of the user-facing
+ public API accessible from PApplet. That is, we don't want sketches calling
+ textModeCheck() or vertexTexture() directly.
+
+
Handling warnings and exceptions
+ Methods that are unavailable generally show a warning, unless their lack of
+ availability will soon cause another exception. For instance, if a method
+ like getMatrix() returns null because it is unavailable, an exception will
+ be thrown stating that the method is unavailable, rather than waiting for
+ the NullPointerException that will occur when the sketch tries to use that
+ method. As of release 0149, warnings will only be shown once, and exceptions
+ have been changed to warnings where possible.
+
+
Using xxxxImpl() for subclassing smoothness
+ The xxxImpl() methods are generally renderer-specific handling for some
+ subset if tasks for a particular function (vague enough for you?) For
+ instance, imageImpl() handles drawing an image whose x/y/w/h and u/v coords
+ have been specified, and screen placement (independent of imageMode) has
+ been determined. There's no point in all renderers implementing the
+ if (imageMode == BLAH) placement/sizing logic, so that's handled
+ by PGraphics, which then calls imageImpl() once all that is figured out.
+
+
His brother PImage
+ PGraphics subclasses PImage so that it can be drawn and manipulated in a
+ similar fashion. As such, many methods are inherited from PGraphics,
+ though many are unavailable: for instance, resize() is not likely to be
+ implemented; the same goes for mask(), depending on the situation.
+
+
What's in PGraphics, what ain't
+ For the benefit of subclasses, as much as possible has been placed inside
+ PGraphics. For instance, bezier interpolation code and implementations of
+ the strokeCap() method (that simply sets the strokeCap variable) are
+ handled here. Features that will vary widely between renderers are located
+ inside the subclasses themselves. For instance, all matrix handling code
+ is per-renderer: Java 2D uses its own AffineTransform, P2D uses a PMatrix2D,
+ and PGraphics3D needs to keep continually update forward and reverse
+ transformations. A proper (future) OpenGL implementation will have all its
+ matrix madness handled by the card. Lighting also falls under this
+ category, however the base material property settings (emissive, specular,
+ et al.) are handled in PGraphics because they use the standard colorMode()
+ logic. Subclasses should override methods like emissiveFromCalc(), which
+ is a point where a valid color has been defined internally, and can be
+ applied in some manner based on the calcXxxx values.
+
+
What's in the PGraphics documentation, what ain't
+ Some things are noted here, some things are not. For public API, always
+ refer to the reference
+ on Processing.org for proper explanations. No attempt has been made to
+ keep the javadoc up to date or complete. It's an enormous task for
+ which we simply do not have the time. That is, it's not something that
+ to be done once—it's a matter of keeping the multiple references
+ synchronized (to say nothing of the translation issues), while targeting
+ them for their separate audiences. Ouch.
+
textureImage
+
+
+ Current image being used as a texture
+
+
+
+ int
+
textureMode
+
+
+ Sets whether texture coordinates passed to
+ vertex() calls will be based on coordinates that are
+ based on the IMAGE or NORMALIZED.
+
+
+
+ float
+
textureU
+
+
+ Current horizontal coordinate for texture, will always
+ be between 0 and 1, even if using textureMode(IMAGE).
+
+
+
+ float
+
textureV
+
+
+ Current vertical coordinate for texture, see above.
arc(float a,
+ float b,
+ float c,
+ float d,
+ float start,
+ float stop)
+
+
+ Identical parameters and placement to ellipse,
+ but draws only an arc of that ellipse.
+
+
+
+ void
+
background(float gray)
+
+
+ Set the background to a grayscale value, based on the
+ current colorMode.
+
+
+
+ void
+
background(float gray,
+ float alpha)
+
+
+ See notes about alpha in background(x, y, z, a).
+
+
+
+ void
+
background(float x,
+ float y,
+ float z)
+
+
+ Set the background to an r, g, b or h, s, b value,
+ based on the current colorMode.
+
+
+
+ void
+
background(float x,
+ float y,
+ float z,
+ float a)
+
+
+ Clear the background with a color that includes an alpha value.
+
+
+
+ void
+
background(int rgb)
+
+
+ Set the background to a gray or ARGB color.
+
+
+
+ void
+
background(int rgb,
+ float alpha)
+
+
+ See notes about alpha in background(x, y, z, a).
+
+
+
+ void
+
background(PImage image)
+
+
+ Takes an RGB or ARGB image and sets it as the background.
scale(float sx,
+ float sy)
+
+
+ Scale in X and Y.
+
+
+
+ void
+
scale(float x,
+ float y,
+ float z)
+
+
+ Scale in X, Y, and Z.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenX(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenZ(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ void
+
setMatrix(PMatrix source)
+
+
+ Set the current transformation matrix to the contents of another.
+
+
+
+ void
+
setMatrix(PMatrix2D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setMatrix(PMatrix3D source)
+
+
+ Set the current transformation to the contents of the specified source.
textFont(PFont which,
+ float size)
+
+
+ Useful function to set the font and size at the same time.
+
+
+
+ void
+
textLeading(float leading)
+
+
+ Set the text leading to a specific value.
+
+
+
+ void
+
textMode(int mode)
+
+
+ Sets the text rendering/placement to be either SCREEN (direct
+ to the screen, exact coordinates, only use the font's original size)
+ or MODEL (the default, where text is manipulated by translate() and
+ can have a textSize).
+
+
+
+ void
+
textSize(float size)
+
+
+ Sets the text size, also resets the value for the leading.
+
+
+
+ void
+
texture(PImage image)
+
+
+ Set texture image for current shape.
+
+
+
+ void
+
textureMode(int mode)
+
+
+ Set texture mode to either to use coordinates based on the IMAGE
+ (more intuitive for new users) or NORMALIZED (better for advanced chaps)
Max value for green (or saturation) set by colorMode
+
+
+
+
+
+
+
+colorModeZ
+
+public float colorModeZ
+
+
Max value for blue (or value) set by colorMode
+
+
+
+
+
+
+
+colorModeA
+
+public float colorModeA
+
+
Max value for alpha set by colorMode
+
+
+
+
+
+
+
+tint
+
+public boolean tint
+
+
True if tint() is enabled (read-only).
+
+ Using tint/tintColor seems a better option for naming than
+ tintEnabled/tint because the latter seems ugly, even though
+ g.tint as the actual color seems a little more intuitive,
+ it's just that g.tintEnabled is even more unintuitive.
+ Same goes for fill and stroke, et al.
+
+
+
+
+
+
+
+tintColor
+
+public int tintColor
+
+
tint that was last set (read-only)
+
+
+
+
+
+
+
+fill
+
+public boolean fill
+
+
true if fill() is enabled, (read-only)
+
+
+
+
+
+
+
+fillColor
+
+public int fillColor
+
+
fill that was last set (read-only)
+
+
+
+
+
+
+
+stroke
+
+public boolean stroke
+
+
true if stroke() is enabled, (read-only)
+
+
+
+
+
+
+
+strokeColor
+
+public int strokeColor
+
+
stroke that was last set (read-only)
+
+
+
+
+
+
+
+strokeWeight
+
+public float strokeWeight
+
+
Last value set by strokeWeight() (read-only). This has a default
+ setting, rather than fighting with renderers about whether that
+ renderer supports thick lines.
+
+
+
+
+
+
+
+strokeJoin
+
+public int strokeJoin
+
+
Set by strokeJoin() (read-only). This has a default setting
+ so that strokeJoin() need not be called by defaults,
+ because subclasses may not implement it (i.e. PGraphicsGL)
+
+
+
+
+
+
+
+strokeCap
+
+public int strokeCap
+
+
Set by strokeCap() (read-only). This has a default setting
+ so that strokeCap() need not be called by defaults,
+ because subclasses may not implement it (i.e. PGraphicsGL)
+
Last background color that was set, zero if an image
+
+
+
+
+
+
+
+image
+
+public java.awt.Image image
+
+
Java AWT Image object associated with this renderer. For P2D and P3D,
+ this will be associated with their MemoryImageSource. For PGraphicsJava2D,
+ it will be the offscreen drawing buffer.
+
+
+
+
+
+
+
+bezierDetail
+
+public int bezierDetail
+
+
+
+
+
+
+
+curveTightness
+
+public float curveTightness
+
+
+
+
+
+
+
+edge
+
+public boolean edge
+
+
+
+
+
+
+
+normalX
+
+public float normalX
+
+
Current normal vector.
+
+
+
+
+
+
+
+normalY
+
+public float normalY
+
+
Current normal vector.
+
+
+
+
+
+
+
+normalZ
+
+public float normalZ
+
+
Current normal vector.
+
+
+
+
+
+
+
+textureMode
+
+public int textureMode
+
+
Sets whether texture coordinates passed to
+ vertex() calls will be based on coordinates that are
+ based on the IMAGE or NORMALIZED.
+
+
+
+
+
+
+
+textureU
+
+public float textureU
+
+
Current horizontal coordinate for texture, will always
+ be between 0 and 1, even if using textureMode(IMAGE).
+
+
+
+
+
+
+
+textureV
+
+public float textureV
+
+
Current vertical coordinate for texture, see above.
+
Constructor for the PGraphics object. Use this to ensure that
+ the defaults get set properly. In a subclass, use this(w, h)
+ as the first line of a subclass' constructor to properly set
+ the internal fields and defaults.
+
Set (or unset) this as the main drawing surface. Meaning that it can
+ safely be set to opaque (and given a default gray background), or anything
+ else that goes along with that.
+
+
+
+
+
+
+
+
+
+
+
+setPath
+
+public void setPath(java.lang.String path)
+
+
+
+
+
+
+
+
+
+
+
+setSize
+
+public void setSize(int w,
+ int h)
+
+
The final step in setting up a renderer, set its size of this renderer.
+ This was formerly handled by the constructor, but instead it's been broken
+ out so that setParent/setPrimary/setPath can be handled differently.
+
+ Important that this is ignored by preproc.pl because otherwise it will
+ override setSize() in PApplet/Applet/Component, which will 1) not call
+ super.setSize(), and 2) will cause the renderer to be resized from the
+ event thread (EDT), causing a nasty crash as it collides with the
+ animation thread.
+
+
+
+
+
+
+
+
+
+
+
+dispose
+
+public void dispose()
+
+
Handle any takedown for this graphics context.
+
+ This is called when a sketch is shut down and this renderer was
+ specified using the size() command, or inside endRecord() and
+ endRaw(), in order to shut things off.
+
+
+
+
+
+
+
+
+
+
+
+canDraw
+
+public boolean canDraw()
+
+
Some renderers have requirements re: when they are ready to draw.
+
+
+
+
+
+
+
+
+
+
+
+beginDraw
+
+public void beginDraw()
+
+
Prepares the PGraphics for drawing.
+
+ When creating your own PGraphics, you should call this before
+ drawing anything.
+
+
+
+
+
+
+
+
+
+
+
+endDraw
+
+public void endDraw()
+
+
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
+
+
+
+
+
+
+
+
+
+
+flush
+
+public void flush()
+
+
+
+
+
+
+
+
+
+
+
+hint
+
+public void hint(int which)
+
+
Enable a hint option.
+
+ For the most part, hints are temporary api quirks,
+ for which a proper api hasn't been properly worked out.
+ for instance SMOOTH_IMAGES existed because smooth()
+ wasn't yet implemented, but it will soon go away.
+
+ They also exist for obscure features in the graphics
+ engine, like enabling/disabling single pixel lines
+ that ignore the zbuffer, the way they do in alphabot.
+
+ Current hint options:
+
+
DISABLE_DEPTH_TEST -
+ turns off the z-buffer in the P3D or OPENGL renderers.
+
+
+
+
+
+
+
+
+
+
+
+
+beginShape
+
+public void beginShape()
+
+
Start a new shape of type POLYGON
+
+
+
+
+
+
+
+
+
+
+
+beginShape
+
+public void beginShape(int kind)
+
+
Start a new shape.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
+
+
+
+
+
+
+
+
+
+
+edge
+
+public void edge(boolean edge)
+
+
Sets whether the upcoming vertex is part of an edge.
+ Equivalent to glEdgeFlag(), for people familiar with OpenGL.
+
Sets the current normal vector. Only applies with 3D rendering
+ and inside a beginShape/endShape block.
+
+ This is for drawing three dimensional shapes and surfaces,
+ allowing you to specify a vector perpendicular to the surface
+ of the shape, which determines how lighting affects it.
+
+ For the most part, PGraphics3D will attempt to automatically
+ assign normals to shapes, but since that's imperfect,
+ this is a better option when you want more control.
+
+ For people familiar with OpenGL, this function is basically
+ identical to glNormal3f().
+
+
+
+
+
+
+
+
+
+
+
+textureMode
+
+public void textureMode(int mode)
+
+
Set texture mode to either to use coordinates based on the IMAGE
+ (more intuitive for new users) or NORMALIZED (better for advanced chaps)
+
Identical parameters and placement to ellipse,
+ but draws only an arc of that ellipse.
+
+ start and stop are always radians because angleMode() was goofy.
+ ellipseMode() sets the placement.
+
+ also tries to be smart about start < stop.
+
+
+
+
+
+
+
+
+
+
+
+box
+
+public void box(float size)
+
+
+
+
+
+
+
+
+
+
+
+box
+
+public void box(float w,
+ float h,
+ float d)
+
+
+
+
+
+
+
+
+
+
+
+sphereDetail
+
+public void sphereDetail(int res)
+
+
+
+
+
+
+
+
+
+
+
+sphereDetail
+
+public void sphereDetail(int ures,
+ int vres)
+
+
Set the detail level for approximating a sphere. The ures and vres params
+ control the horizontal and vertical resolution.
+
+ Code for sphereDetail() submitted by toxi [031031].
+ Code for enhanced u/v version from davbol [080801].
+
+
+
+
+
+
+
+
+
+
+
+sphere
+
+public void sphere(float r)
+
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Evalutes quadratic bezier at point t for points a, b, c, d.
+ t varies between 0 and 1, and a and d are the on curve points,
+ b and c are the control points. this can be done once with the
+ x coordinates and a second time with the y coordinates to get
+ the location of a bezier curve at t.
+
+ For instance, to convert the following example:
+ stroke(255, 102, 0);
+ line(85, 20, 10, 10);
+ line(90, 90, 15, 80);
+ stroke(0, 0, 0);
+ bezier(85, 20, 10, 10, 90, 90, 15, 80);
+
+ // draw it in gray, using 10 steps instead of the default 20
+ // this is a slower way to do it, but useful if you need
+ // to do things with the coordinates at each step
+ stroke(128);
+ beginShape(LINE_STRIP);
+ for (int i = 0; i <= 10; i++) {
+ float t = i / 10.0f;
+ float x = bezierPoint(85, 10, 90, 15, t);
+ float y = bezierPoint(20, 10, 90, 80, t);
+ vertex(x, y);
+ }
+ endShape();
Draw a cubic bezier curve. The first and last points are
+ the on-curve points. The middle two are the 'control' points,
+ or 'handles' in an application like Illustrator.
+
+ As of 0070, this function no longer doubles the first and
+ last points. The curves are a bit more boring, but it's more
+ mathematically correct, and properly mirrored in curvePoint().
+
+public void image(PImage image,
+ float a,
+ float b,
+ float c,
+ float d,
+ int u1,
+ int v1,
+ int u2,
+ int v2)
+
+
Draw an image(), also specifying u/v coordinates.
+ In this method, the u, v coordinates are always based on image space
+ location, regardless of the current textureMode().
+
+
+
+
+
+
+
+
+
+
+
+shapeMode
+
+public void shapeMode(int mode)
+
+
Set the orientation for the shape() command (like imageMode() or rectMode()).
+
Sets the alignment of the text to one of LEFT, CENTER, or RIGHT.
+ This will also reset the vertical text alignment to BASELINE.
+
+
+
+
+
+
+
+
+
+
+
+textAlign
+
+public void textAlign(int alignX,
+ int alignY)
+
+
Sets the horizontal and vertical alignment of the text. The horizontal
+ alignment can be one of LEFT, CENTER, or RIGHT. The vertical alignment
+ can be TOP, BOTTOM, CENTER, or the BASELINE (the default).
+
+
+
+
+
+
+
+
+
+
+
+textAscent
+
+public float textAscent()
+
+
Returns the ascent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
+
+
+
+
+
+
+
+
+
+
+textDescent
+
+public float textDescent()
+
+
Returns the descent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Sets the current font. The font's size will be the "natural"
+ size of this font (the size that was set when using "Create Font").
+ The leading will also be reset.
+
Useful function to set the font and size at the same time.
+
+
+
+
+
+
+
+
+
+
+
+textLeading
+
+public void textLeading(float leading)
+
+
Set the text leading to a specific value. If using a custom
+ value for the text leading, you'll have to call textLeading()
+ again after any calls to textSize().
+
+
+
+
+
+
+
+
+
+
+
+textMode
+
+public void textMode(int mode)
+
+
Sets the text rendering/placement to be either SCREEN (direct
+ to the screen, exact coordinates, only use the font's original size)
+ or MODEL (the default, where text is manipulated by translate() and
+ can have a textSize). The text size cannot be set when using
+ textMode(SCREEN), because it uses the pixels directly from the font.
+
+
+
+
+
+
+
+
+
+
+
+textSize
+
+public void textSize(float size)
+
+
Sets the text size, also resets the value for the leading.
+
+
+
+
+
+
+
+
+
+
+
+textWidth
+
+public float textWidth(char c)
+
+
+
+
+
+
+
+
+
+
+
+textWidth
+
+public float textWidth(java.lang.String str)
+
+
Return the width of a line of text. If the text has multiple
+ lines, this returns the length of the longest line.
+
+
+
+
+
+
+
+
+
+
+
+text
+
+public void text(char c)
+
+
Write text where we just left off.
+
+
+
+
+
+
+
+
+
+
+
+text
+
+public void text(char c,
+ float x,
+ float y)
+
+
Draw a single character on screen.
+ Extremely slow when used with textMode(SCREEN) and Java 2D,
+ because loadPixels has to be called first and updatePixels last.
+
Draw a chunk of text.
+ Newlines that are \n (Unix newline or linefeed char, ascii 10)
+ are honored, but \r (carriage return, Windows and Mac OS) are
+ ignored.
+
+
+
+
+
+
+
+
+
+
+
+text
+
+public void text(char[] chars,
+ int start,
+ int stop,
+ float x,
+ float y)
+
+
Method to draw text from an array of chars. This method will usually be
+ more efficient than drawing from a String object, because the String will
+ not be converted to a char array before drawing.
+
Draw text in a box that is constrained to a particular size.
+ The current rectMode() determines what the coordinates mean
+ (whether x1/y1/x2/y2 or x/y/w/h).
+
+ Note that the x,y coords of the start of the box
+ will align with the *ascent* of the text, not the baseline,
+ as is the case for the other text() functions.
+
+ Newlines that are \n (Unix newline or linefeed char, ascii 10)
+ are honored, and \r (carriage return, Windows and Mac OS) are
+ ignored.
+
This does a basic number formatting, to avoid the
+ generally ugly appearance of printing floats.
+ Users who want more control should use their own nf() cmmand,
+ or if they want the long, ugly version of float,
+ use String.valueOf() to convert the float to a String first.
+
Two dimensional rotation.
+
+ Same as rotateZ (this is identical to a 3D rotation along the z-axis)
+ but included for clarity. It'd be weird for people drawing 2D graphics
+ to be using rotateZ. And they might kick our a-- for the confusion.
+
+ Additional background.
+
+
+
+
+
+
+
+
+
+
+
+rotateX
+
+public void rotateX(float angle)
+
+
Rotate around the X axis.
+
+
+
+
+
+
+
+
+
+
+
+rotateY
+
+public void rotateY(float angle)
+
+
Rotate around the Y axis.
+
+
+
+
+
+
+
+
+
+
+
+rotateZ
+
+public void rotateZ(float angle)
+
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Rotate about a vector in space. Same as the glRotatef() function.
+
+
+
+
+
+
+
+
+
+
+
+scale
+
+public void scale(float s)
+
+
Scale in all dimensions.
+
+
+
+
+
+
+
+
+
+
+
+scale
+
+public void scale(float sx,
+ float sy)
+
+
Scale in X and Y. Equivalent to scale(sx, sy, 1).
+
+ Not recommended for use in 3D, because the z-dimension is just
+ scaled by 1, since there's no way to know what else to scale it by.
+
+
+
+
+
+
+
+
+
+
+
+scale
+
+public void scale(float x,
+ float y,
+ float z)
+
+
Scale in X, Y, and Z.
+
+
+
+
+
+
+
+
+
+
+
+resetMatrix
+
+public void resetMatrix()
+
+
Set the current transformation matrix to identity.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenY
+
+public float screenY(float x,
+ float y)
+
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenX
+
+public float screenX(float x,
+ float y,
+ float z)
+
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenY
+
+public float screenY(float x,
+ float y,
+ float z)
+
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+
+
+
+
+
+
+
+
+screenZ
+
+public float screenZ(float x,
+ float y,
+ float z)
+
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns its z value.
+ This value can be used to determine if an (x, y, z) coordinate
+ is in front or in back of another (x, y, z) coordinate.
+ The units are based on how the zbuffer is set up, and don't
+ relate to anything "real". They're only useful for in
+ comparison to another value obtained from screenZ(),
+ or directly out of the zbuffer[].
+
+
+
+
+
+
+
+
+
+
+
+modelX
+
+public float modelX(float x,
+ float y,
+ float z)
+
+
Returns the model space x value for an x, y, z coordinate.
+
+ This will give you a coordinate after it has been transformed
+ by translate(), rotate(), and camera(), but not yet transformed
+ by the projection matrix. For instance, his can be useful for
+ figuring out how points in 3D space relate to the edge
+ coordinates of a shape.
+
+
+
+
+
+
+
+
+
+
+
+modelY
+
+public float modelY(float x,
+ float y,
+ float z)
+
+
Returns the model space y value for an x, y, z coordinate.
+
+
+
+
+
+
+
+
+
+
+
+modelZ
+
+public float modelZ(float x,
+ float y,
+ float z)
+
+
Returns the model space z value for an x, y, z coordinate.
+
+public void lightSpecular(float x,
+ float y,
+ float z)
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(int rgb)
+
+
Set the background to a gray or ARGB color.
+
+ For the main drawing surface, the alpha value will be ignored. However,
+ alpha can be used on PGraphics objects from createGraphics(). This is
+ the only way to set all the pixels partially transparent, for instance.
+
+ Note that background() should be called before any transformations occur,
+ because some implementations may require the current transformation matrix
+ to be identity before drawing.
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(int rgb,
+ float alpha)
+
+
See notes about alpha in background(x, y, z, a).
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(float gray)
+
+
Set the background to a grayscale value, based on the
+ current colorMode.
+
See notes about alpha in background(x, y, z, a).
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(float x,
+ float y,
+ float z)
+
+
Set the background to an r, g, b or h, s, b value,
+ based on the current colorMode.
+
+
+
+
+
+
+
+
+
+
+
+background
+
+public void background(float x,
+ float y,
+ float z,
+ float a)
+
+
Clear the background with a color that includes an alpha value. This can
+ only be used with objects created by createGraphics(), because the main
+ drawing surface cannot be set transparent.
+
+ It might be tempting to use this function to partially clear the screen
+ on each frame, however that's not how this function works. When calling
+ background(), the pixels will be replaced with pixels that have that level
+ of transparency. To do a semi-transparent overlay, use fill() with alpha
+ and draw a rectangle.
+
Takes an RGB or ARGB image and sets it as the background.
+ The width and height of the image must be the same size as the sketch.
+ Use image.resize(width, height) to make short work of such a task.
+
+ Note that even if the image is set as RGB, the high 8 bits of each pixel
+ should be set opaque (0xFF000000), because the image data will be copied
+ directly to the screen, and non-opaque background images may have strange
+ behavior. Using image.filter(OPAQUE) will handle this easily.
+
+ When using 3D, this will also clear the zbuffer (if it exists).
+
+
+
+
+
+
+
+
+
+
+
+colorMode
+
+public void colorMode(int mode)
+
+
Callback to handle clearing the background when begin/endRaw is in use.
+ Handled as separate function for OpenGL (or other) subclasses that
+ override backgroundImpl() but still needs this to work properly.
+
Show an renderer-related exception that halts the program. Currently just
+ wraps the message as a RuntimeException and throws it, but might do
+ something more specific might be used in the future.
+
+
+
+
+
+
+
+
+
+
+
+displayable
+
+public boolean displayable()
+
+
Return true if this renderer should be drawn to the screen. Defaults to
+ returning true, since nearly all renderers are on-screen beasts. But can
+ be overridden for subclasses like PDF so that a window doesn't open up.
+
+ A better name? showFrame, displayable, isVisible, visible, shouldDisplay,
+ what to call this?
+
+
+
+
+
+
+
+
+
+
+
+is2D
+
+public boolean is2D()
+
+
Return true if this renderer supports 2D drawing. Defaults to true.
+
+
+
+
+
+
+
+
+
+
+
+is3D
+
+public boolean is3D()
+
+
Return true if this renderer supports 2D drawing. Defaults to true.
+
+Subclass of PGraphics that handles fast 2D rendering using a
+ MemoryImageSource. The renderer found in this class is not as accurate as
+ PGraphicsJava2D, but offers certain speed tradeoffs, particular when
+ messing with the pixels array, or displaying image or video data.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from class processing.core.PGraphics
scale(float sx,
+ float sy)
+
+
+ Scale in X and Y.
+
+
+
+ void
+
scale(float x,
+ float y,
+ float z)
+
+
+ Scale in X, Y, and Z.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ void
+
sphere(float r)
+
+
+ Draw a sphere with radius r centered at coordinate 0, 0, 0.
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Set the detail level for approximating a sphere. The ures and vres params
+ control the horizontal and vertical resolution.
+
+ Code for sphereDetail() submitted by toxi [031031].
+ Code for enhanced u/v version from davbol [080801].
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Two dimensional rotation.
+
+ Same as rotateZ (this is identical to a 3D rotation along the z-axis)
+ but included for clarity. It'd be weird for people drawing 2D graphics
+ to be using rotateZ. And they might kick our a-- for the confusion.
+
+ Additional background.
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Scale in X and Y. Equivalent to scale(sx, sy, 1).
+
+ Not recommended for use in 3D, because the z-dimension is just
+ scaled by 1, since there's no way to know what else to scale it by.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+Subclass of PGraphics that handles 3D rendering.
+ It can render 3D inside a browser window and requires no plug-ins.
+
+ The renderer is mostly set up based on the structure of the OpenGL API,
+ if you have questions about specifics that aren't covered here,
+ look for reference on the OpenGL implementation of a similar feature.
+
+ Lighting and camera implementation by Simon Greenwold.
+
flush()
+
+
+ Emit any sorted geometry that's been collected on this frame.
+
+
+
+ void
+
frustum(float left,
+ float right,
+ float bottom,
+ float top,
+ float znear,
+ float zfar)
+
+
+ Same as glFrustum(), except that it wipes out (rather than
+ multiplies against) the current perspective matrix.
ortho()
+
+
+ Calls ortho() with the proper parameters for Processing's
+ standard orthographic projection.
+
+
+
+ void
+
ortho(float left,
+ float right,
+ float bottom,
+ float top,
+ float near,
+ float far)
+
+
+ Similar to gluOrtho(), but wipes out the current projection matrix.
+
+
+
+ void
+
perspective()
+
+
+ Calls perspective() with Processing's standard coordinate projection.
+
+
+
+ void
+
perspective(float fov,
+ float aspect,
+ float zNear,
+ float zFar)
+
+
+ Similar to gluPerspective().
popMatrix()
+
+
+ Replace the current transformation matrix with the top of the stack.
+
+
+
+ void
+
printCamera()
+
+
+ Print the current camera matrix.
+
+
+
+ void
+
printMatrix()
+
+
+ Print the current model (or "transformation") matrix.
+
+
+
+ void
+
printProjection()
+
+
+ Print the current projection matrix.
+
+
+
+ void
+
pushMatrix()
+
+
+ Push a copy of the current transformation matrix onto the stack.
+
+
+
+ void
+
resetMatrix()
+
+
+ Set the current transformation matrix to identity.
+
+
+
+ void
+
rotate(float angle)
+
+
+ Two dimensional rotation.
+
+
+
+ void
+
rotate(float angle,
+ float v0,
+ float v1,
+ float v2)
+
+
+ Rotate around an arbitrary vector, similar to glRotate(),
+ except that it takes radians (instead of degrees).
+
+
+
+ void
+
rotateX(float angle)
+
+
+ Rotate around the X axis.
+
+
+
+ void
+
rotateY(float angle)
+
+
+ Rotate around the Y axis.
+
+
+
+ void
+
rotateZ(float angle)
+
+
+ Rotate around the Z axis.
scale(float sx,
+ float sy)
+
+
+ Same as scale(sx, sy, 1).
+
+
+
+ void
+
scale(float x,
+ float y,
+ float z)
+
+
+ Scale in three dimensions.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenX(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenZ(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ void
+
setMatrix(PMatrix2D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setMatrix(PMatrix3D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setSize(int iwidth,
+ int iheight)
+
+
+ Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+
+
+ void
+
smooth()
+
+
+ If true in PImage, use bilinear interpolation for copy()
+ operations.
+
+
+
+ void
+
sphere(float r)
+
+
+ Draw a sphere with radius r centered at coordinate 0, 0, 0.
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+ Note that this will nuke any cameraMode() settings.
+
See notes in PGraphics.
+ If z-sorting has been turned on, then the triangles will
+ all be quicksorted here (to make alpha work more properly)
+ and then blit to the screen.
+
+ For the most part, hints are temporary api quirks,
+ for which a proper api hasn't been properly worked out.
+ for instance SMOOTH_IMAGES existed because smooth()
+ wasn't yet implemented, but it will soon go away.
+
+ They also exist for obscure features in the graphics
+ engine, like enabling/disabling single pixel lines
+ that ignore the zbuffer, the way they do in alphabot.
+
+ Current hint options:
+
+
DISABLE_DEPTH_TEST -
+ turns off the z-buffer in the P3D or OPENGL renderers.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Two dimensional rotation. Same as rotateZ (this is identical
+ to a 3D rotation along the z-axis) but included for clarity --
+ it'd be weird for people drawing 2D graphics to be using rotateZ.
+ And they might kick our a-- for the confusion.
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Apply a 4x4 transformation matrix. Same as glMultMatrix().
+ This call will be slow because it will try to calculate the
+ inverse of the transform. So avoid it whenever possible.
+
Set matrix mode to the camera matrix (instead of the current
+ transformation matrix). This means applyMatrix, resetMatrix, etc.
+ will affect the camera.
+
+ Note that the camera matrix is *not* the perspective matrix,
+ it is in front of the modelview matrix (hence the name "model"
+ and "view" for that matrix).
+
+ beginCamera() specifies that all coordinate transforms until endCamera()
+ should be pre-applied in inverse to the camera transform matrix.
+ Note that this is only challenging when a user specifies an arbitrary
+ matrix with applyMatrix(). Then that matrix will need to be inverted,
+ which may not be possible. But take heart, if a user is applying a
+ non-invertible matrix to the camera transform, then he is clearly
+ up to no good, and we can wash our hands of those bad intentions.
+
+ begin/endCamera clauses do not automatically reset the camera transform
+ matrix. That's because we set up a nice default camera transform int
+ setup(), and we expect it to hold through draw(). So we don't reset
+ the camera transform matrix at the top of draw(). That means that an
+ innocuous-looking clause like
+
+ at the top of draw(), will result in a runaway camera that shoots
+ infinitely out of the screen over time. In order to prevent this,
+ it is necessary to call some function that does a hard reset of the
+ camera transform matrix inside of begin/endCamera. Two options are
+
+ camera(); // sets up the nice default camera transform
+ resetMatrix(); // sets up the identity camera transform
+
+ So to rotate a camera a constant amount, you might try
+
Record the current settings into the camera matrix, and set
+ the matrix mode back to the current transformation matrix.
+
+ Note that this will destroy any settings to scale(), translate(),
+ or whatever, because the final camera matrix will be copied
+ (not multiplied) into the modelview.
+
+ Camera behavior can be split into two separate components, camera
+ transformation, and projection. The transformation corresponds to the
+ physical location, orientation, and scale of the camera. In a physical
+ camera metaphor, this is what can manipulated by handling the camera
+ body (with the exception of scale, which doesn't really have a physcial
+ analog). The projection corresponds to what can be changed by
+ manipulating the lens.
+
+ We maintain separate matrices to represent the camera transform and
+ projection. An important distinction between the two is that the camera
+ transform should be invertible, where the projection matrix should not,
+ since it serves to map three dimensions to two. It is possible to bake
+ the two matrices into a single one just by multiplying them together,
+ but it isn't a good idea, since lighting, z-ordering, and z-buffering
+ all demand a true camera z coordinate after modelview and camera
+ transforms have been applied but before projection. If the camera
+ transform and projection are combined there is no way to recover a
+ good camera-space z-coordinate from a model coordinate.
+
+ Fortunately, there are no functions that manipulate both camera
+ transformation and projection.
+
+ camera() sets the camera position, orientation, and center of the scene.
+ It replaces the camera transform with a new one. This is different from
+ gluLookAt(), but I think the only reason that GLU's lookat doesn't fully
+ replace the camera matrix with the new one, but instead multiplies it,
+ is that GL doesn't enforce the separation of camera transform and
+ projection, so it wouldn't be safe (you'd probably stomp your projection).
+
+ The transformation functions are the same ones used to manipulate the
+ modelview matrix (scale, translate, rotate, etc.). But they are bracketed
+ with beginCamera(), endCamera() to indicate that they should apply
+ (in inverse), to the camera transformation matrix.
+
+ This differs considerably from camera transformation in OpenGL.
+ OpenGL only lets you say, apply everything from here out to the
+ projection or modelview matrix. This makes it very hard to treat camera
+ manipulation as if it were a physical camera. Imagine that you want to
+ move your camera 100 units forward. In OpenGL, you need to apply the
+ inverse of that transformation or else you'll move your scene 100 units
+ forward--whether or not you've specified modelview or projection matrix.
+ Remember they're just multiplied by model coods one after another.
+ So in order to treat a camera like a physical camera, it is necessary
+ to pre-apply inverse transforms to a matrix that will be applied to model
+ coordinates. OpenGL provides nothing of this sort, but Processing does!
+ This is the camera transform matrix.
+
+ do not need to be called from with beginCamera();/endCamera();
+ That's because they always apply to the camera transformation,
+ and they always totally replace it. That means that any coordinate
+ transforms done before camera(); in draw() will be wiped out.
+ It also means that camera() always operates in untransformed world
+ coordinates. Therefore it is always redundant to call resetMatrix();
+ before camera(); This isn't technically true of gluLookat, but it's
+ pretty much how it's used.
+
+ Now, beginCamera(); and endCamera(); are useful if you want to move
+ the camera around using transforms like translate(), etc. They will
+ wipe out any coordinate system transforms that occur before them in
+ draw(), but they will not automatically wipe out the camera transform.
+ This means that they should be at the top of draw(). It also means
+ that the following:
+
+ will result in a camera that spins without stopping. If you want to
+ just rotate a small constant amount, try this:
+
+ beginCamera();
+ camera(); // sets up the default view
+ rotateY(PI/8);
+ endCamera();
+
+ That will rotate a little off of the default view. Note that this
+ is entirely equivalent to
+
+ camera(); // sets up the default view
+ beginCamera();
+ rotateY(PI/8);
+ endCamera();
+
+ because camera() doesn't care whether or not it's inside a
+ begin/end clause. Basically it's safe to use camera() or
+ camera(ex, ey, ez, cx, cy, cz, ux, uy, uz) as naked calls because
+ they do all the matrix resetting automatically.
+
Calls perspective() with Processing's standard coordinate projection.
+
+ Projection functions:
+
+
frustrum()
+
ortho()
+
perspective()
+
+ Each of these three functions completely replaces the projection
+ matrix with a new one. They can be called inside setup(), and their
+ effects will be felt inside draw(). At the top of draw(), the projection
+ matrix is not reset. Therefore the last projection function to be
+ called always dominates. On resize, the default projection is always
+ established, which has perspective.
+
+ This behavior is pretty much familiar from OpenGL, except where
+ functions replace matrices, rather than multiplying against the
+ previous.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns its z value.
+ This value can be used to determine if an (x, y, z) coordinate
+ is in front or in back of another (x, y, z) coordinate.
+ The units are based on how the zbuffer is set up, and don't
+ relate to anything "real". They're only useful for in
+ comparison to another value obtained from screenZ(),
+ or directly out of the zbuffer[].
+
Returns the model space x value for an x, y, z coordinate.
+
+ This will give you a coordinate after it has been transformed
+ by translate(), rotate(), and camera(), but not yet transformed
+ by the projection matrix. For instance, his can be useful for
+ figuring out how points in 3D space relate to the edge
+ coordinates of a shape.
+
+ The Lighting Skinny:
+
+ The way lighting works is complicated enough that it's worth
+ producing a document to describe it. Lighting calculations proceed
+ pretty much exactly as described in the OpenGL red book.
+
+ Light-affecting material properties:
+
+ AMBIENT COLOR
+ - multiplies by light's ambient component
+ - for believability this should match diffuse color
+
+ DIFFUSE COLOR
+ - multiplies by light's diffuse component
+
+ SPECULAR COLOR
+ - multiplies by light's specular component
+ - usually less colored than diffuse/ambient
+
+ SHININESS
+ - the concentration of specular effect
+ - this should be set pretty high (20-50) to see really
+ noticeable specularity
+
+ EMISSIVE COLOR
+ - constant additive color effect
+
+ Light types:
+
+ AMBIENT
+ - one color
+ - no specular color
+ - no direction
+ - may have falloff (constant, linear, and quadratic)
+ - may have position (which matters in non-constant falloff case)
+ - multiplies by a material's ambient reflection
+
+ DIRECTIONAL
+ - has diffuse color
+ - has specular color
+ - has direction
+ - no position
+ - no falloff
+ - multiplies by a material's diffuse and specular reflections
+
+ POINT
+ - has diffuse color
+ - has specular color
+ - has position
+ - no direction
+ - may have falloff (constant, linear, and quadratic)
+ - multiplies by a material's diffuse and specular reflections
+
+ SPOT
+ - has diffuse color
+ - has specular color
+ - has position
+ - has direction
+ - has cone angle (set to half the total cone angle)
+ - has concentration value
+ - may have falloff (constant, linear, and quadratic)
+ - multiplies by a material's diffuse and specular reflections
+
+ Normal modes:
+
+ All of the primitives (rect, box, sphere, etc.) have their normals
+ set nicely. During beginShape/endShape normals can be set by the user.
+
+ AUTO-NORMAL
+ - if no normal is set during the shape, we are in auto-normal mode
+ - auto-normal calculates one normal per triangle (face-normal mode)
+
+ SHAPE-NORMAL
+ - if one normal is set during the shape, it will be used for
+ all vertices
+
+ VERTEX-NORMAL
+ - if multiple normals are set, each normal applies to
+ subsequent vertices
+ - (except for the first one, which applies to previous
+ and subsequent vertices)
+
+ Efficiency consequences:
+
+ There is a major efficiency consequence of position-dependent
+ lighting calculations per vertex. (See below for determining
+ whether lighting is vertex position-dependent.) If there is no
+ position dependency then the only factors that affect the lighting
+ contribution per vertex are its colors and its normal.
+ There is a major efficiency win if
+
+ 1) lighting is not position dependent
+ 2) we are in AUTO-NORMAL or SHAPE-NORMAL mode
+
+ because then we can calculate one lighting contribution per shape
+ (SHAPE-NORMAL) or per triangle (AUTO-NORMAL) and simply multiply it
+ into the vertex colors. The converse is our worst-case performance when
+
+ 1) lighting is position dependent
+ 2) we are in AUTO-NORMAL mode
+
+ because then we must calculate lighting per-face * per-vertex.
+ Each vertex has a different lighting contribution per face in
+ which it appears. Yuck.
+
+ Determining vertex position dependency:
+
+ If any of the following factors are TRUE then lighting is
+ vertex position dependent:
+
+ 1) Any lights uses non-constant falloff
+ 2) There are any point or spot lights
+ 3) There is a light with specular color AND there is a
+ material with specular color
+
+ So worth noting is that default lighting (a no-falloff ambient
+ and a directional without specularity) is not position-dependent.
+ We should capitalize.
+
+ Simon Greenwold, April 2005
+
Add an ambient light based on the current color mode.
+ This version includes an (x, y, z) position for situations
+ where the falloff distance is used.
+
+Subclass for PGraphics that implements the graphics API using Java2D.
+
+
Pixel operations too slow? As of release 0085 (the first beta),
+ the default renderer uses Java2D. It's more accurate than the renderer
+ used in alpha releases of Processing (it handles stroke caps and joins,
+ and has better polygon tessellation), but it's super slow for handling
+ pixels. At least until we get a chance to get the old 2D renderer
+ (now called P2D) working in a similar fashion, you can use
+ size(w, h, P3D) instead of size(w, h) which will
+ be faster for general pixel flipping madness.
+
+
To get access to the Java 2D "Graphics2D" object for the default
+ renderer, use:
+
Graphics2D g2 = ((PGraphicsJava2D)g).g2;
+ This will let you do Java 2D stuff directly, but is not supported in
+ any way shape or form. Which just means "have fun, but don't complain
+ if it breaks."
breakShape()
+
+
+ This feature is in testing, do not use or rely upon its implementation
+
+
+
+ boolean
+
canDraw()
+
+
+ Some renderers have requirements re: when they are ready to draw.
+
+
+
+ void
+
copy(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
+ Copy things from one area of this image
+ to another area in the same image.
getImpl(int x,
+ int y,
+ int w,
+ int h)
+
+
+ Internal function to actually handle getting a block of pixels that
+ has already been properly cropped to a valid region.
scale(float sx,
+ float sy)
+
+
+ Scale in X and Y.
+
+
+
+ void
+
scale(float sx,
+ float sy,
+ float sz)
+
+
+ Scale in X, Y, and Z.
+
+
+
+ float
+
screenX(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenX(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenY(float x,
+ float y)
+
+
+ Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
+
+
+ float
+
screenY(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ float
+
screenZ(float x,
+ float y,
+ float z)
+
+
+ Maps a three dimensional point to its placement on-screen.
+
+
+
+ void
+
set(int x,
+ int y,
+ int argb)
+
+
+ Set a single pixel to the specified color.
+
+
+
+ void
+
setMatrix(PMatrix2D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setMatrix(PMatrix3D source)
+
+
+ Set the current transformation to the contents of the specified source.
+
+
+
+ void
+
setSize(int iwidth,
+ int iheight)
+
+
+ Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+
+
+ void
+
smooth()
+
+
+ If true in PImage, use bilinear interpolation for copy()
+ operations.
+
+
+
+ void
+
sphere(float r)
+
+
+ Draw a sphere with radius r centered at coordinate 0, 0, 0.
Called in response to a resize event, handles setting the
+ new width and height internally, as well as re-allocating
+ the pixel buffer for the new size.
+
+ Note that this will nuke any cameraMode() settings.
+
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Draw a sphere with radius r centered at coordinate 0, 0, 0.
+
+ Implementation notes:
+
+ cache all the points of the sphere in a static array
+ top and bottom are just a bunch of triangles that land
+ in the center point
+
+ sphere is a series of concentric circles who radii vary
+ along the shape, based on, er.. cos or something
+
+ [toxi 031031] new sphere code. removed all multiplies with
+ radius, as scale() will take care of that anyway
+
+ [toxi 031223] updated sphere code (removed modulos)
+ and introduced sphereAt(x,y,z,r)
+ to avoid additional translate()'s on the user/sketch side
+
+ [davbol 080801] now using separate sphereDetailU/V
+
Returns the ascent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Returns the descent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Two dimensional rotation.
+
+ Same as rotateZ (this is identical to a 3D rotation along the z-axis)
+ but included for clarity. It'd be weird for people drawing 2D graphics
+ to be using rotateZ. And they might kick our a-- for the confusion.
+
+ Additional background.
+
Rotate around the Z axis.
+
+ The functions rotate() and rotateZ() are identical, it's just that it make
+ sense to have rotate() and then rotateX() and rotateY() when using 3D;
+ nor does it make sense to use a function called rotateZ() if you're only
+ doing things in 2D. so we just decided to have them both be the same.
+
Scale in X and Y. Equivalent to scale(sx, sy, 1).
+
+ Not recommended for use in 3D, because the z-dimension is just
+ scaled by 1, since there's no way to know what else to scale it by.
+
Given an x and y coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Given an x and y coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the x position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns the y position of where
+ that point would be placed on screen, once affected by translate(),
+ scale(), or any other transformations.
+
Maps a three dimensional point to its placement on-screen.
+
+ Given an (x, y, z) coordinate, returns its z value.
+ This value can be used to determine if an (x, y, z) coordinate
+ is in front or in back of another (x, y, z) coordinate.
+ The units are based on how the zbuffer is set up, and don't
+ relate to anything "real". They're only useful for in
+ comparison to another value obtained from screenZ(),
+ or directly out of the zbuffer[].
+
Actual implementation of clearing the background, now that the
+ internal variables for background color have been set. Called by the
+ backgroundFromCalc() method, which is what all the other background()
+ methods call once the work is done.
+
Call this when you want to mess with the pixels[] array.
+
+ For subclasses where the pixels[] buffer isn't set by default,
+ this should copy all data into the pixels[] array
+
Returns an ARGB "color" type (a packed 32 bit int with the color.
+ If the coordinate is outside the image, zero is returned
+ (black, but completely transparent).
+
+ If the image is in RGB format (i.e. on a PVideo object),
+ the value will get its high bits set, just to avoid cases where
+ they haven't been set already.
+
+ If the image is in ALPHA format, this returns a white with its
+ alpha value set.
+
+ This function is included primarily for beginners. It is quite
+ slow because it has to check to see if the x, y that was provided
+ is inside the bounds, and then has to check to see what image
+ type it is. If you want things to be more efficient, access the
+ pixels[] array directly.
+
Internal function to actually handle getting a block of pixels that
+ has already been properly cropped to a valid region. That is, x/y/w/h
+ are guaranteed to be inside the image space, so the implementation can
+ use the fastest possible pixel copying method.
+
Set alpha channel for an image. Black colors in the source
+ image will make the destination image completely transparent,
+ and white will make things fully opaque. Gray values will
+ be in-between steps.
+
+ Strictly speaking the "blue" value from the source image is
+ used as the alpha color. For a fully grayscale image, this
+ is correct, but for a color image it's not 100% accurate.
+ For a more accurate conversion, first use filter(GRAY)
+ which will make the image into a "correct" grayscake by
+ performing a proper luminance-based conversion.
+
PImage()
+
+
+ Create an empty image object, set its format to RGB.
+
+
+
PImage(java.awt.Image img)
+
+
+ Construct a new PImage from a java.awt.Image.
+
+
+
PImage(int width,
+ int height)
+
+
+ Create a new RGB (alpha ignored) image of a specific size.
+
+
+
PImage(int width,
+ int height,
+ int format)
+
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
blend(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ int mode)
+
+
+ Blends one area of this image to another area.
+
+
+
+ void
+
blend(PImage src,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ int mode)
+
+
+ Copies area of one image into another PImage object.
+
+
+
+static int
+
blendColor(int c1,
+ int c2,
+ int mode)
+
+
+ Blend two colors based on a particular mode.
+
+
+
+ java.lang.Object
+
clone()
+
+
+ Duplicate an image, returns new PImage object.
+
+
+
+ void
+
copy(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
+ Copy things from one area of this image
+ to another area in the same image.
+
+
+
+ void
+
copy(PImage src,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
+ Copies area of one image into another PImage object.
+
+
+
+ void
+
filter(int kind)
+
+
+ Method to apply a variety of basic filters to this image.
+
+
+
+ void
+
filter(int kind,
+ float param)
+
+
+ Method to apply a variety of basic filters to this image.
get(int x,
+ int y,
+ int w,
+ int h)
+
+
+ Grab a subsection of a PImage, and copy it into a fresh PImage.
+
+
+
+ java.lang.Object
+
getCache(java.lang.Object parent)
+
+
+ Get cache storage data for the specified renderer.
+
+
+
+ java.awt.Image
+
getImage()
+
+
+ Returns a BufferedImage from this PImage.
+
+
+
+ void
+
init(int width,
+ int height,
+ int format)
+
+
+ Function to be used by subclasses of PImage to init later than
+ at the constructor, or re-init later when things changes.
loadPixels()
+
+
+ Call this when you want to mess with the pixels[] array.
+
+
+
+ void
+
mask(int[] alpha)
+
+
+ Set alpha channel for an image.
+
+
+
+ void
+
mask(PImage alpha)
+
+
+ Set alpha channel for an image using another image as the source.
+
+
+
+ void
+
removeCache(java.lang.Object parent)
+
+
+ Remove information associated with this renderer from the cache, if any.
+
+
+
+ void
+
resize(int wide,
+ int high)
+
+
+ Resize this image to a new width and height.
+
+
+
+ void
+
save(java.lang.String path)
+
+
+ Save this image to disk.
+
+
+
+ void
+
set(int x,
+ int y,
+ int c)
+
+
+ Set a single pixel to the specified color.
+
+
+
+ void
+
set(int x,
+ int y,
+ PImage src)
+
+
+ Efficient method of drawing an image's pixels directly to this surface.
+
+
+
+ void
+
setCache(java.lang.Object parent,
+ java.lang.Object storage)
+
+
+ Store data of some kind for a renderer that requires extra metadata of
+ some kind.
Format for this image, one of RGB, ARGB or ALPHA.
+ note that RGB images still require 0xff in the high byte
+ because of how they'll be manipulated by other functions
+
Path to parent object that will be used with save().
+ This prevents users from needing savePath() to use PImage.save().
+
+
+
+
+
+
+
+
+
+
+
+Constructor Detail
+
+
+
+
+PImage
+
+public PImage()
+
+
Create an empty image object, set its format to RGB.
+ The pixel array is not allocated.
+
+
+
+
+
+PImage
+
+public PImage(int width,
+ int height)
+
+
Create a new RGB (alpha ignored) image of a specific size.
+ All pixels are set to zero, meaning black, but since the
+ alpha is zero, it will be transparent.
+
+
+
+
+
+PImage
+
+public PImage(int width,
+ int height,
+ int format)
+
+
+
+
+
+PImage
+
+public PImage(java.awt.Image img)
+
+
Construct a new PImage from a java.awt.Image. This constructor assumes
+ that you've done the work of making sure a MediaTracker has been used
+ to fully download the data and that the img is valid.
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+init
+
+public void init(int width,
+ int height,
+ int format)
+
+
Function to be used by subclasses of PImage to init later than
+ at the constructor, or re-init later when things changes.
+ Used by Capture and Movie classes (and perhaps others),
+ because the width/height will not be known when super() is called.
+ (Leave this public so that other libraries can do the same.)
+
Store data of some kind for a renderer that requires extra metadata of
+ some kind. Usually this is a renderer-specific representation of the
+ image data, for instance a BufferedImage with tint() settings applied for
+ PGraphicsJava2D, or resized image data and OpenGL texture indices for
+ PGraphicsOpenGL.
+
Get cache storage data for the specified renderer. Because each renderer
+ will cache data in different formats, it's necessary to store cache data
+ keyed by the renderer object. Otherwise, attempting to draw the same
+ image to both a PGraphicsJava2D and a PGraphicsOpenGL will cause errors.
+
+
+
+
+
+
Parameters:
parent - The PGraphics object (or any object, really) associated
+
Returns:
data stored for the specified parent
+
+
+
+
+
+removeCache
+
+public void removeCache(java.lang.Object parent)
+
+
Remove information associated with this renderer from the cache, if any.
+
+
+
+
+
+
Parameters:
parent - The PGraphics object whose cache data should be removed
+
+
+
+
+
+isModified
+
+public boolean isModified()
+
+
+
+
+
+
+
+
+
+
+
+setModified
+
+public void setModified()
+
+
+
+
+
+
+
+
+
+
+
+setModified
+
+public void setModified(boolean m)
+
+
+
+
+
+
+
+
+
+
+
+loadPixels
+
+public void loadPixels()
+
+
Call this when you want to mess with the pixels[] array.
+
+ For subclasses where the pixels[] buffer isn't set by default,
+ this should copy all data into the pixels[] array
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels()
+
+
Call this when finished messing with the pixels[] array.
+
+ Mark all pixels as needing update.
+
+
+
+
+
+
+
+
+
+
+
+updatePixels
+
+public void updatePixels(int x,
+ int y,
+ int w,
+ int h)
+
+
Mark the pixels in this region as needing an update.
+
+ This is not currently used by any of the renderers, however the api
+ is structured this way in the hope of being able to use this to
+ speed things up in the future.
+
Duplicate an image, returns new PImage object.
+ The pixels[] array for the new object will be unique
+ and recopied from the source image. This is implemented as an
+ override of Object.clone(). We recommend using get() instead,
+ because it prevents you from needing to catch the
+ CloneNotSupportedException, and from doing a cast from the result.
+
+
+
Overrides:
clone in class java.lang.Object
+
+
+
+
Throws:
+
java.lang.CloneNotSupportedException
+
+
+
+
+
+resize
+
+public void resize(int wide,
+ int high)
+
+
Resize this image to a new width and height.
+ Use 0 for wide or high to make that dimension scale proportionally.
+
+
+
+
+
+
+
+
+
+
+
+get
+
+public int get(int x,
+ int y)
+
+
Returns an ARGB "color" type (a packed 32 bit int with the color.
+ If the coordinate is outside the image, zero is returned
+ (black, but completely transparent).
+
+ If the image is in RGB format (i.e. on a PVideo object),
+ the value will get its high bits set, just to avoid cases where
+ they haven't been set already.
+
+ If the image is in ALPHA format, this returns a white with its
+ alpha value set.
+
+ This function is included primarily for beginners. It is quite
+ slow because it has to check to see if the x, y that was provided
+ is inside the bounds, and then has to check to see what image
+ type it is. If you want things to be more efficient, access the
+ pixels[] array directly.
+
+
+
+
+
+
+
+
+
+
+
+get
+
+public PImageget(int x,
+ int y,
+ int w,
+ int h)
+
+
Grab a subsection of a PImage, and copy it into a fresh PImage.
+ As of release 0149, no longer honors imageMode() for the coordinates.
+
Efficient method of drawing an image's pixels directly to this surface.
+ No variations are employed, meaning that any scale, tint, or imageMode
+ settings will be ignored.
+
+
+
+
+
+
+
+
+
+
+
+mask
+
+public void mask(int[] alpha)
+
+
Set alpha channel for an image. Black colors in the source
+ image will make the destination image completely transparent,
+ and white will make things fully opaque. Gray values will
+ be in-between steps.
+
+ Strictly speaking the "blue" value from the source image is
+ used as the alpha color. For a fully grayscale image, this
+ is correct, but for a color image it's not 100% accurate.
+ For a more accurate conversion, first use filter(GRAY)
+ which will make the image into a "correct" grayscake by
+ performing a proper luminance-based conversion.
+
Set alpha channel for an image using another image as the source.
+
+
+
+
+
+
+
+
+
+
+
+filter
+
+public void filter(int kind)
+
+
Method to apply a variety of basic filters to this image.
+
+
+
filter(BLUR) provides a basic blur.
+
filter(GRAY) converts the image to grayscale based on luminance.
+
filter(INVERT) will invert the color components in the image.
+
filter(OPAQUE) set all the high bits in the image to opaque
+
filter(THRESHOLD) converts the image to black and white.
+
filter(DILATE) grow white/light areas
+
filter(ERODE) shrink white/light areas
+
+ Luminance conversion code contributed by
+ toxi
+
+ Gaussian blur code contributed by
+ Mario Klingemann
+
+
+
+
+
+
+
+
+
+
+
+filter
+
+public void filter(int kind,
+ float param)
+
+
Method to apply a variety of basic filters to this image.
+ These filters all take a parameter.
+
+
+
filter(BLUR, int radius) performs a gaussian blur of the
+ specified radius.
+
filter(POSTERIZE, int levels) will posterize the image to
+ between 2 and 255 levels.
+
filter(THRESHOLD, float center) allows you to set the
+ center point for the threshold. It takes a value from 0 to 1.0.
+
+ Gaussian blur code contributed by
+ Mario Klingemann
+ and later updated by toxi for better speed.
+
+
+
+
+
+
+
+
+
+
+
+copy
+
+public void copy(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
Copy things from one area of this image
+ to another area in the same image.
+
+
+
+
+
+
+
+
+
+
+
+copy
+
+public void copy(PImage src,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh)
+
+
Copies area of one image into another PImage object.
+
+
+
+
+
+
+
+
+
+
+
+blendColor
+
+public static int blendColor(int c1,
+ int c2,
+ int mode)
+
+
Blend two colors based on a particular mode.
+
+
REPLACE - destination colour equals colour of source pixel: C = A.
+ Sometimes called "Normal" or "Copy" in other software.
+
+
BLEND - linear interpolation of colours:
+ C = A*factor + B
+
+
ADD - additive blending with white clip:
+ C = min(A*factor + B, 255).
+ Clipped to 0..255, Photoshop calls this "Linear Burn",
+ and Director calls it "Add Pin".
+
+
SUBTRACT - substractive blend with black clip:
+ C = max(B - A*factor, 0).
+ Clipped to 0..255, Photoshop calls this "Linear Dodge",
+ and Director calls it "Subtract Pin".
+
+
DARKEST - only the darkest colour succeeds:
+ C = min(A*factor, B).
+ Illustrator calls this "Darken".
+
+
LIGHTEST - only the lightest colour succeeds:
+ C = max(A*factor, B).
+ Illustrator calls this "Lighten".
+
+
DIFFERENCE - subtract colors from underlying image.
+
+
EXCLUSION - similar to DIFFERENCE, but less extreme.
+
+
MULTIPLY - Multiply the colors, result will always be darker.
+
+
SCREEN - Opposite multiply, uses inverse values of the colors.
+
+
OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values,
+ and screens light values.
+
+
HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
+
+
SOFT_LIGHT - Mix of DARKEST and LIGHTEST.
+ Works like OVERLAY, but not as harsh.
+
+
DODGE - Lightens light tones and increases contrast, ignores darks.
+ Called "Color Dodge" in Illustrator and Photoshop.
+
+
BURN - Darker areas are applied, increasing contrast, ignores lights.
+ Called "Color Burn" in Illustrator and Photoshop.
+
+
A useful reference for blending modes and their algorithms can be
+ found in the SVG
+ specification.
+
It is important to note that Processing uses "fast" code, not
+ necessarily "correct" code. No biggie, most software does. A nitpicker
+ can find numerous "off by 1 division" problems in the blend code where
+ >>8 or >>7 is used when strictly speaking
+ /255.0 or /127.0 should have been used.
+
For instance, exclusion (not intended for real-time use) reads
+ r1 + r2 - ((2 * r1 * r2) / 255) because 255 == 1.0
+ not 256 == 1.0. In other words, (255*255)>>8 is not
+ the same as (255*255)/255. But for real-time use the shifts
+ are preferrable, and the difference is insignificant for applications
+ built with Processing.
+
+
+
+
+
+
+
+
+
+
+
+blend
+
+public void blend(int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ int mode)
+ As of revision 0100, this function requires an absolute path,
+ in order to avoid confusion. To save inside the sketch folder,
+ use the function savePath() from PApplet, or use saveFrame() instead.
+ As of revision 0116, savePath() is not needed if this object has been
+ created (as recommended) via createImage() or createGraphics() or
+ one of its neighbors.
+
+ As of revision 0115, when using Java 1.4 and later, you can write
+ to several formats besides tga and tiff. If Java 1.4 is installed
+ and the extension used is supported (usually png, jpg, jpeg, bmp,
+ and tiff), then those methods will be used to write the image.
+ To get a list of the supported formats for writing, use:
+ println(javax.imageio.ImageIO.getReaderFormatNames())
+
+ To use the original built-in image writers, use .tga or .tif as the
+ extension, or don't include an extension. When no extension is used,
+ the extension .tif will be added to the file name.
+
+ The ImageIO API claims to support wbmp files, however they probably
+ require a black and white image. Basic testing produced a zero-length
+ file with no error.
+
Multiply a two element vector against this matrix.
+ If out is null or not length four, a new float array will be returned.
+ The values for vec and out can be the same (though that's less efficient).
+
+In-progress class to handle shape data, currently to be considered of
+ alpha or beta quality. Major structural work may be performed on this class
+ after the release of Processing 1.0. Such changes may include:
+
+
+
addition of proper accessors to read shape vertex and coloring data
+ (this is the second most important part of having a PShape class after all).
+
a means of creating PShape objects ala beginShape() and endShape().
+
load(), update(), and cache methods ala PImage, so that shapes can
+ have renderer-specific optimizations, such as vertex arrays in OpenGL.
+
splitting this class into multiple classes to handle different
+ varieties of shape data (primitives vs collections of vertices vs paths)
+
change of package declaration, for instance moving the code into
+ package processing.shape (if the code grows too much).
+
+
+
For the time being, this class and its shape() and loadShape() friends in
+ PApplet exist as placeholders for more exciting things to come. If you'd
+ like to work with this class, make a subclass (see how PShapeSVG works)
+ and you can play with its internal methods all you like.
+
+
Library developers are encouraged to create PShape objects when loading
+ shape data, so that they can eventually hook into the bounty that will be
+ the PShape interface, and the ease of loadShape() and shape().
findChild(java.lang.String target)
+
+
+ Same as getChild(name), except that it first walks all the way up the
+ hierarchy to the farthest parent, so that children can be found anywhere.
Overrides this shape's style information and uses PGraphics styles and
+ colors. Identical to ignoreStyles(true). Also disables styles for all
+ child shapes.
+
+
+
+
+
+
+
+
+
+
+
+enableStyle
+
+public void enableStyle()
+
+
Re-enables style information (fill and stroke) set in the shape.
+
+
+
+
+
+
+
+
+
+
+
+getWidth
+
+public float getWidth()
+
+
Get the width of the drawing area (not necessarily the shape boundary).
+
+
+
+
+
+
+
+
+
+
+
+getHeight
+
+public float getHeight()
+
+
Get the height of the drawing area (not necessarily the shape boundary).
+
+SVG stands for Scalable Vector Graphics, a portable graphics format. It is
+ a vector format so it allows for infinite resolution and relatively small
+ file sizes. Most modern media software can view SVG files, including Adobe
+ products, Firefox, etc. Illustrator and Inkscape can edit SVG files.
+
+ We have no intention of turning this into a full-featured SVG library.
+ The goal of this project is a basic shape importer that is small enough
+ to be included with applets, meaning that its download size should be
+ in the neighborhood of 25-30k. Starting with release 0149, this library
+ has been incorporated into the core via the loadShape() command, because
+ vector shape data is just as important as the image data from loadImage().
+
+ For more sophisticated import/export, consider the
+ Batik
+ library from the Apache Software Foundation. Future improvements to this
+ library may focus on this properly supporting a specific subset of SVG,
+ for instance the simpler SVG profiles known as
+ SVG Tiny or Basic,
+ although we still would not support the interactivity options.
+
+
+
+ A minimal example program using SVG:
+ (assuming a working moo.svg is in your data folder)
+
+
+
+ This code is based on the Candy library written by Michael Chang, which was
+ later revised and expanded for use as a Processing core library by Ben Fry.
+ Thanks to Ricard Marxer Pinon for help with better Inkscape support in 0154.
+
+
+
+ Late October 2008 revisions from ricardmp, incorporated by fry (0154)
+
Get a particular element based on its SVG ID. When editing SVG by hand,
+ this is the id="" tag on any SVG element. When editing from Illustrator,
+ these IDs can be edited by expanding the layers palette. The names used
+ in the layers palette, both for the layers or the shapes and groups
+ beneath them can be used here.
+
+ // This code grabs "Layer 3" and the shapes beneath it.
+ SVG layer3 = svg.getChild("Layer 3");
+
+Smoothed triangle renderer for P3D.
+
+ Based off of the PPolygon class in old versions of Processing.
+ Name and location of this class will change in a future release.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from interface processing.core.PConstants
Pass camera-space coordinates for the triangle.
+ Needed to render if hint(ENABLE_ACCURATE_TEXTURES) enabled.
+ Generally this will not need to be called manually,
+ currently called from PGraphics3D.render_triangles()
+
Pass camera-space coordinates for the triangle.
+ Needed to render if hint(ENABLE_ACCURATE_TEXTURES) enabled.
+ Generally this will not need to be called manually,
+ currently called from PGraphics3D.render_triangles()
+
Set the power of two used for linear interpolation of texture coordinates.
+ A true texture coordinate is computed every 2^pwr pixels along a scanline.
+
+A class to describe a two or three dimensional vector.
+
+ The result of all functions are applied to the vector itself, with the
+ exception of cross(), which returns a new PVector (or writes to a specified
+ 'target' PVector). That is, add() will add the contents of one vector to
+ this one. Using add() with additional parameters allows you to put the
+ result into a new PVector. Functions that act on multiple vectors also
+ include static versions. Because creating new objects can be computationally
+ expensive, most functions include an optional 'target' PVector, so that a
+ new PVector object is not created with each operation.
+
+ Initially based on the Vector3D class by Dan Shiffman.
+
div(PVector v1,
+ PVector v2)
+
+
+ Multiply each element of one vector by the individual elements of another
+ vector, and return the result as a new PVector.
div(PVector v1,
+ PVector v2,
+ PVector target)
+
+
+ Divide each element of one vector by the individual elements of another
+ vector, and write the result into a target vector.
mult(PVector v1,
+ PVector v2)
+
+
+ Multiply each element of one vector by the individual elements of another
+ vector, and return the result as a new PVector.
mult(PVector v1,
+ PVector v2,
+ PVector target)
+
+
+ Multiply each element of one vector by the individual elements of another
+ vector, and write the result into a target vector.
+
+
+
+ void
+
normalize()
+
+
+ Normalize the vector to length 1 (make it a unit vector)
Calculate the angle between two vectors, using the dot product
+
+
+
Parameters:
v1 - a vector
v2 - another vector
+
Returns:
the angle between the vectors
+
+
+
+
+
+toString
+
+public java.lang.String toString()
+
+
+
Overrides:
toString in class java.lang.Object
+
+
+
+
+
+
+
+
+array
+
+public float[] array()
+
+
Return a representation of this vector as a float array. This is only for
+ temporary use. If used in any other fashion, the contents should be copied
+ by using the get() command to copy into your own array.
+
+A simple library to write DXF files with Processing.
+ Because this is used with beginRaw() and endRaw(), only individual
+ triangles and (discontinuous) line segments will be written to the file.
+
+ Use something like a keyPressed() in PApplet to trigger it,
+ to avoid writing a bazillion .dxf files.
+
+ Usually, the file will be saved to the sketch's folder.
+ Use Sketch → Show Sketch Folder to see it from the PDE.
+
+ A simple example of how to use:
+
+ import processing.dxf.*;
+
+ boolean record;
+
+ void setup() {
+ size(500, 500, P3D);
+ }
+
+ void keyPressed() {
+ // use a key press so that it doesn't make a million files
+ if (key == 'r') record = true;
+ }
+
+ void draw() {
+ if (record) {
+ beginRaw(DXF, "output.dxf");
+ }
+
+ // do all your drawing here
+
+ if (record) {
+ endRaw();
+ record = false;
+ }
+ }
+
+ or to use it and be able to control the current layer:
+
+ import processing.dxf.*;
+
+ boolean record;
+ RawDXF dxf;
+
+ void setup() {
+ size(500, 500, P3D);
+ }
+
+ void keyPressed() {
+ // use a key press so that it doesn't make a million files
+ if (key == 'r') record = true;
+ }
+
+ void draw() {
+ if (record) {
+ dxf = (RawDXF) createGraphics(width, height, DXF, "output.dxf");
+ beginRaw(dxf);
+ }
+
+ // do all your drawing here, and to set the layer, call:
+ // if (record) {
+ // dxf.setLayer(num);
+ // }
+ // where 'num' is an integer.
+ // the default is zero, or you can set it to whatever.
+
+ if (record) {
+ endRaw();
+ record = false;
+ dxf = null;
+ }
+ }
+
+ Note that even though this class is a subclass of PGraphics, it only
+ implements the parts of the API that are necessary for beginRaw/endRaw.
+
+ Based on the original DXF writer from Simon Greenwold, February 2004.
+ Updated for Processing 0070 by Ben Fry in September 2004,
+ and again for Processing beta in April 2005.
+ Rewritten to support beginRaw/endRaw by Ben Fry in February 2006.
+ Updated again for inclusion as a core library in March 2006.
+ Constructor modifications in September 2008 as we approach 1.0.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+
+
+
Fields inherited from class processing.core.PGraphics3D
+ This is called when a sketch is shut down and this renderer was
+ specified using the size() command, or inside endRecord() and
+ endRaw(), in order to shut things off.
+
Return true if this renderer should be drawn to the screen. Defaults to
+ returning true, since nearly all renderers are on-screen beasts. But can
+ be overridden for subclasses like PDF so that a window doesn't open up.
+
+ A better name? showFrame, displayable, isVisible, visible, shouldDisplay,
+ what to call this?
+
See notes in PGraphics.
+ If z-sorting has been turned on, then the triangles will
+ all be quicksorted here (to make alpha work more properly)
+ and then blit to the screen.
+
Write a command on one line (as a String), then start a new line
+ and write out a formatted float. Available for anyone who wants to
+ insert additional commands into the DXF stream.
+
+
+
+
+
+
+
+
+println
+
+public void println(java.lang.String what)
+
+
Write a line to the dxf file. Available for anyone who wants to
+ insert additional commands into the DXF stream.
+
+ Differences between beginShape() and line() and point() methods.
+
+ beginShape() is intended to be more flexible at the expense of being
+ a little more complicated to use. it handles more complicated shapes
+ that can consist of many connected lines (so you get joins) or lines
+ mixed with curves.
+
+ The line() and point() command are for the far more common cases
+ (particularly for our audience) that simply need to draw a line
+ or a point on the screen.
+
+ From the code side of things, line() may or may not call beginShape()
+ to do the drawing. In the beta code, they do, but in the alpha code,
+ they did not. they might be implemented one way or the other depending
+ on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
+ meaning the speed that things run at vs. the speed it takes me to write
+ the code and maintain it. for beta, the latter is most important so
+ that's how things are implemented.
+
Disconnect from the server and calls disconnectEvent(Client c)
+ in the host PApplet.
+
+ Use this to shut the connection if you're finished with it
+ while your applet is still running. Otherwise, it will be
+ automatically be shut down by the host PApplet
+ (using dispose, which is identical)
+
+
+
+
+
+
+
+
+
+
+
+dispose
+
+public void dispose()
+
+
Disconnect from the server: internal use only.
+
+ This should only be called by the internal functions in PApplet,
+ use stop() instead from within your own applets.
+
+
+
+
+
+
+
+
+
+
+
+run
+
+public void run()
+
+
+
Specified by:
run in interface java.lang.Runnable
+
+
+
+
+
+
+
+
+active
+
+public boolean active()
+
+
Return true if this client is still active and hasn't run
+ into any trouble.
+
+
+
+
+
+
+
+
+
+
+
+ip
+
+public java.lang.String ip()
+
+
Returns the ip address of this feller as a String.
+
+
+
+
+
+
+
+
+
+
+
+available
+
+public int available()
+
+
Returns the number of bytes that have been read from serial
+ and are waiting to be dealt with by the user.
+
+
+
+
+
+
+
+
+
+
+
+clear
+
+public void clear()
+
+
Ignore all the bytes read so far and empty the buffer.
+
+
+
+
+
+
+
+
+
+
+
+read
+
+public int read()
+
+
Returns a number between 0 and 255 for the next byte that's
+ waiting in the buffer.
+ Returns -1 if there was no byte (although the user should
+ first check available() to see if things are ready to avoid this)
+
+
+
+
+
+
+
+
+
+
+
+readChar
+
+public char readChar()
+
+
Returns the next byte in the buffer as a char.
+ Returns -1, or 0xffff, if nothing is there.
+
+
+
+
+
+
+
+
+
+
+
+readBytes
+
+public byte[] readBytes()
+
+
Return a byte array of anything that's in the serial buffer.
+ Not particularly memory/speed efficient, because it creates
+ a byte array on each read, but it's easier to use than
+ readBytes(byte b[]) (see below).
+
+
+
+
+
+
+
+
+
+
+
+readBytes
+
+public int readBytes(byte[] outgoing)
+
+
Grab whatever is in the serial buffer, and stuff it into a
+ byte buffer passed in by the user. This is more memory/time
+ efficient than readBytes() returning a byte[] array.
+
+ Returns an int for how many bytes were read. If more bytes
+ are available than can fit into the byte array, only those
+ that will fit are read.
+
+
+
+
+
+
+
+
+
+
+
+readBytesUntil
+
+public byte[] readBytesUntil(int interesting)
+
+
Reads from the serial port into a buffer of bytes up to and
+ including a particular character. If the character isn't in
+ the serial buffer, then 'null' is returned.
+
+
+
+
+
+
+
+
+
+
+
+readBytesUntil
+
+public int readBytesUntil(int interesting,
+ byte[] outgoing)
+
+
Reads from the serial port into a buffer of bytes until a
+ particular character. If the character isn't in the serial
+ buffer, then 'null' is returned.
+
+ If outgoing[] is not big enough, then -1 is returned,
+ and an error message is printed on the console.
+ If nothing is in the buffer, zero is returned.
+ If 'interesting' byte is not in the buffer, then 0 is returned.
+
+
+
+
+
+
+
+
+
+
+
+readString
+
+public java.lang.String readString()
+
+
Return whatever has been read from the serial port so far
+ as a String. It assumes that the incoming characters are ASCII.
+
+ If you want to move Unicode data, you can first convert the
+ String to a byte stream in the representation of your choice
+ (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
+
Combination of readBytesUntil and readString. See caveats in
+ each function. Returns null if it still hasn't found what
+ you're looking for.
+
+ If you want to move Unicode data, you can first convert the
+ String to a byte stream in the representation of your choice
+ (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(int what)
+
+
This will handle ints, bytes and chars transparently.
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(byte[] bytes)
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(java.lang.String what)
+
+
Write a String to the output. Note that this doesn't account
+ for Unicode (two bytes per char), nor will it send UTF8
+ characters.. It assumes that you mean to send a byte buffer
+ (most often the case for networking and serial i/o) and
+ will only use the bottom 8 bits of each char in the string.
+ (Meaning that internally it uses String.getBytes)
+
+ If you want to move Unicode data, you can first convert the
+ String to a byte stream in the representation of your choice
+ (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
+
Returns the next client in line that has something to say.
+
+
+
+
+
+
+
+
+
+
+
+stop
+
+public void stop()
+
+
Disconnect all clients and stop the server.
+
+ Use this to shut down the server if you finish using it while your applet
+ is still running. Otherwise, it will be automatically be shut down by the
+ host PApplet using dispose(), which is identical.
+
+
+
+
+
+
+
+
+
+
+
+dispose
+
+public void dispose()
+
+
Disconnect all clients and stop the server: internal use only.
+
+
+
+
+
+
+
+
+
+
+
+run
+
+public void run()
+
+
+
Specified by:
run in interface java.lang.Runnable
+
+
+
+
+
+
+
+
+write
+
+public void write(int what)
+
+
Write a value to all the connected clients.
+ See Client.write() for operational details.
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(byte[] what)
+
+
Write a byte array to all the connected clients.
+ See Client.write() for operational details.
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(java.lang.String what)
+
+
Write a String to all the connected clients.
+ See Client.write() for operational details.
+
+There must be a better way to do this, but I'm having a brain fart
+ with all the inner class crap. Fix it later once this stuff is debugged.
+
+ The method "void vertex(float $1, float $2, float $3);" contained in
+ the enclosing type "processing.core.PGraphics3" is a perfect match for
+ this method call. However, it is not visible in this nested class because
+ a method with the same name in an intervening class is hiding it.
+
Implementation of the GLU_TESS_COMBINE callback.
+
+
+
Specified by:
combine in interface javax.media.opengl.glu.GLUtessellatorCallback
Overrides:
combine in class javax.media.opengl.glu.GLUtessellatorCallbackAdapter
+
+
+
Parameters:
coords - is the 3-vector of the new vertex
data - is the vertex data to be combined, up to four elements.
+ This is useful when mixing colors together or any other
+ user data that was passed in to gluTessVertex.
weight - is an array of weights, one for each element of "data"
+ that should be linearly combined for new values.
outData - is the set of new values of "data" after being
+ put back together based on the weights. it's passed back as a
+ single element Object[] array because that's the closest
+ that Java gets to a pointer.
+Implementation of the PGraphics API that employs OpenGL rendering via JOGL.
+
+ JOGL requires Java 1.4 or higher, so there are no restrictions on this
+ code to be compatible with Java 1.1 or Java 1.3.
+
+ This code relies on PGraphics3D for all lighting and transformations.
+ Meaning that translate(), rotate(), and any lighting will be done in
+ PGraphics3D, and OpenGL is only used to blit lines and triangles as fast
+ as it possibly can.
+
+ For this reason, OpenGL may not be accelerated as far as it could be,
+ but I don't have the time to maintain two separate versions of the
+ renderer. My development time must always be focused on implementation
+ and covering features first, and optimizing later.
+
+ Further, the difference may be negligible, as the primary slowdown
+ in Java is moving pixels (i.e. a large frame buffer is nearly impossible
+ because Java just can't do a MemoryImageSource at screen resolution)
+ and the overhead from JNI tends to be significant. In the latter case,
+ we may even save time in some cases where a large number of calls to
+ OpenGL would otherwise be used, but that's probably a stretch.
+
+ The code is also very messy, while features are being added and
+ removed rapidly as we head towards 1.0. Things got particularly ugly
+ as we approached beta while both Simon and I were working on it.
+ Relax, we'll get it fixed up later.
+
+ When exporting applets, the JOGL Applet Launcher is used. More information
+ about the launcher can be found at its documentation page.
+
+
+
+
+
+
+
+
+
+
+
+
+Nested Class Summary
+
+
+
+ class
+
PGraphicsOpenGL.TessCallback
+
+
+ There must be a better way to do this, but I'm having a brain fart
+ with all the inner class crap.
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+static boolean
+
BIG_ENDIAN
+
+
+ Set to true if the host system is big endian (PowerPC, MIPS, SPARC),
+ false if little endian (x86 Intel for Mac or PC).
canDraw()
+
+
+ OpenGL cannot draw until a proper native peer is available, so this
+ returns the value of PApplet.isDisplayable() (inherited from Component).
See notes in PGraphics.
+ If z-sorting has been turned on, then the triangles will
+ all be quicksorted here (to make alpha work more properly)
+ and then blit to the screen.
+
+ For the most part, hints are temporary api quirks,
+ for which a proper api hasn't been properly worked out.
+ for instance SMOOTH_IMAGES existed because smooth()
+ wasn't yet implemented, but it will soon go away.
+
+ They also exist for obscure features in the graphics
+ engine, like enabling/disabling single pixel lines
+ that ignore the zbuffer, the way they do in alphabot.
+
+ Current hint options:
+
+
DISABLE_DEPTH_TEST -
+ turns off the z-buffer in the P3D or OPENGL renderers.
+
Returns the ascent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Returns the descent of the current font at the current size.
+ This is a method, rather than a variable inside the PGraphics object
+ because it requires calculation.
+
Sets the current font. The font's size will be the "natural"
+ size of this font (the size that was set when using "Create Font").
+ The leading will also be reset.
+
Add an ambient light based on the current color mode.
+ This version includes an (x, y, z) position for situations
+ where the falloff distance is used.
+
Call this when you want to mess with the pixels[] array.
+
+ For subclasses where the pixels[] buffer isn't set by default,
+ this should copy all data into the pixels[] array
+
Returns an ARGB "color" type (a packed 32 bit int with the color.
+ If the coordinate is outside the image, zero is returned
+ (black, but completely transparent).
+
+ If the image is in RGB format (i.e. on a PVideo object),
+ the value will get its high bits set, just to avoid cases where
+ they haven't been set already.
+
+ If the image is in ALPHA format, this returns a white with its
+ alpha value set.
+
+ This function is included primarily for beginners. It is quite
+ slow because it has to check to see if the x, y that was provided
+ is inside the bounds, and then has to check to see what image
+ type it is. If you want things to be more efficient, access the
+ pixels[] array directly.
+
+ TODO not optimized properly, creates multiple temporary buffers
+ the size of the image. Needs to instead use image cache, but that
+ requires two types of image cache. One for power of 2 textures
+ and another for glReadPixels/glDrawPixels data that's flipped
+ vertically. Both have their components all swapped to native.
+
Set alpha channel for an image. Black colors in the source
+ image will make the destination image completely transparent,
+ and white will make things fully opaque. Gray values will
+ be in-between steps.
+
+ Strictly speaking the "blue" value from the source image is
+ used as the alpha color. For a fully grayscale image, this
+ is correct, but for a color image it's not 100% accurate.
+ For a more accurate conversion, first use filter(GRAY)
+ which will make the image into a "correct" grayscake by
+ performing a proper luminance-based conversion.
+
This is really inefficient and not a good idea in OpenGL.
+ Use get() and set() with a smaller image area, or call the
+ filter on an image instead, and then draw that.
+
This is really inefficient and not a good idea in OpenGL.
+ Use get() and set() with a smaller image area, or call the
+ filter on an image instead, and then draw that.
+
addFonts(java.lang.String directory)
+
+
+ Add a directory that should be searched for font data.
+
+
+
+ void
+
beginDraw()
+
+
+ Prepares the PGraphics for drawing.
+
+
+
+ void
+
blend(int sx,
+ int sy,
+ int dx,
+ int dy,
+ int mode)
+
+
+
+
+
+
+ void
+
blend(int sx1,
+ int sy1,
+ int sx2,
+ int sy2,
+ int dx1,
+ int dy1,
+ int dx2,
+ int dy2,
+ int mode)
+
+
+ Blends one area of this image to another area.
+
+
+
+ void
+
blend(PImage src,
+ int sx,
+ int sy,
+ int dx,
+ int dy,
+ int mode)
+
+
+
+
+
+
+ void
+
blend(PImage src,
+ int sx1,
+ int sy1,
+ int sx2,
+ int sy2,
+ int dx1,
+ int dy1,
+ int dx2,
+ int dy2,
+ int mode)
+
+
+ Copies area of one image into another PImage object.
+
+
+
+ void
+
copy(int sx1,
+ int sy1,
+ int sx2,
+ int sy2,
+ int dx1,
+ int dy1,
+ int dx2,
+ int dy2)
+
+
+ Copy things from one area of this image
+ to another area in the same image.
+
+
+
+ void
+
copy(PImage src,
+ int sx1,
+ int sy1,
+ int sx2,
+ int sy2,
+ int dx1,
+ int dy1,
+ int dx2,
+ int dy2)
+
+
+ Copies area of one image into another PImage object.
+
+
+
+ boolean
+
displayable()
+
+
+ Don't open a window for this renderer, it won't be used.
+
+
+
+ void
+
dispose()
+
+
+ Handle any takedown for this graphics context.
+
+
+
+ void
+
endDraw()
+
+
+ This will finalize rendering so that it can be shown on-screen.
+
+
+
+ void
+
filter(int kind)
+
+
+ Method to apply a variety of basic filters to this image.
+
+
+
+ void
+
filter(int kind,
+ float param)
+
+
+ Method to apply a variety of basic filters to this image.
This will finalize rendering so that it can be shown on-screen.
+
+ When creating your own PGraphics, you should call this when
+ you're finished drawing.
+
Change the textMode() to either SHAPE or MODEL.
+
+ This resets all renderer settings, and should therefore
+ be called before any other commands that set the fill()
+ or the textFont() or anything. Unlike other renderers,
+ use textMode() directly after the size() command.
+
+ This is called when a sketch is shut down and this renderer was
+ specified using the size() command, or inside endRecord() and
+ endRaw(), in order to shut things off.
+
Call this when you want to mess with the pixels[] array.
+
+ For subclasses where the pixels[] buffer isn't set by default,
+ this should copy all data into the pixels[] array
+
Returns an ARGB "color" type (a packed 32 bit int with the color.
+ If the coordinate is outside the image, zero is returned
+ (black, but completely transparent).
+
+ If the image is in RGB format (i.e. on a PVideo object),
+ the value will get its high bits set, just to avoid cases where
+ they haven't been set already.
+
+ If the image is in ALPHA format, this returns a white with its
+ alpha value set.
+
+ This function is included primarily for beginners. It is quite
+ slow because it has to check to see if the x, y that was provided
+ is inside the bounds, and then has to check to see what image
+ type it is. If you want things to be more efficient, access the
+ pixels[] array directly.
+
Efficient method of drawing an image's pixels directly to this surface.
+ No variations are employed, meaning that any scale, tint, or imageMode
+ settings will be ignored.
+
Set alpha channel for an image. Black colors in the source
+ image will make the destination image completely transparent,
+ and white will make things fully opaque. Gray values will
+ be in-between steps.
+
+ Strictly speaking the "blue" value from the source image is
+ used as the alpha color. For a fully grayscale image, this
+ is correct, but for a color image it's not 100% accurate.
+ For a more accurate conversion, first use filter(GRAY)
+ which will make the image into a "correct" grayscake by
+ performing a proper luminance-based conversion.
+
+ As of revision 0100, this function requires an absolute path,
+ in order to avoid confusion. To save inside the sketch folder,
+ use the function savePath() from PApplet, or use saveFrame() instead.
+ As of revision 0116, savePath() is not needed if this object has been
+ created (as recommended) via createImage() or createGraphics() or
+ one of its neighbors.
+
+ As of revision 0115, when using Java 1.4 and later, you can write
+ to several formats besides tga and tiff. If Java 1.4 is installed
+ and the extension used is supported (usually png, jpg, jpeg, bmp,
+ and tiff), then those methods will be used to write the image.
+ To get a list of the supported formats for writing, use:
+ println(javax.imageio.ImageIO.getReaderFormatNames())
+
+ To use the original built-in image writers, use .tga or .tif as the
+ extension, or don't include an extension. When no extension is used,
+ the extension .tif will be added to the file name.
+
+ The ImageIO API claims to support wbmp files, however they probably
+ require a black and white image. Basic testing produced a zero-length
+ file with no error.
+
Add a directory that should be searched for font data.
+
+ On Mac OS X, the following directories are added by default:
+
+
/System/Library/Fonts
+
/Library/Fonts
+
~/Library/Fonts
+
+ On Windows, all drive letters are searched for WINDOWS\Fonts
+ or WINNT\Fonts, any that exists is added.
+
+ On Linux or any other platform, you'll need to add the
+ directories by hand. (If there are actual standards here that we
+ can use as a starting point, please file a bug to make a note of it)
+
+
+
+
+
+
+
+
+listFonts
+
+public java.lang.String[] listFonts()
+
+
List the fonts known to the PDF renderer. This is like PFont.list(),
+ however not all those fonts are available by default.
+
Serial(PApplet parent,
+ java.lang.String iname,
+ int irate,
+ char iparity,
+ int idatabits,
+ float istopbits)
+
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ int
+
available()
+
+
+ Returns the number of bytes that have been read from serial
+ and are waiting to be dealt with by the user.
+
+
+
+ void
+
buffer(int count)
+
+
+ Set number of bytes to buffer before calling serialEvent()
+ in the host applet.
+
+
+
+ void
+
bufferUntil(int what)
+
+
+ Set a specific byte to buffer until before calling
+ serialEvent() in the host applet.
+
+
+
+ void
+
clear()
+
+
+ Ignore all the bytes read so far and empty the buffer.
+
+
+
+ void
+
dispose()
+
+
+ Used by PApplet to shut things down.
+
+
+
+static void
+
errorMessage(java.lang.String where,
+ java.lang.Throwable e)
+
+
+ General error reporting, all corraled here just in case
+ I think of something slightly more intelligent to do.
+
+
+
+ int
+
last()
+
+
+ Same as read() but returns the very last value received
+ and clears the buffer.
+ Basically just a user-accessible version of dispose().
+ For now, it just calls dispose(), but dispose shouldn't
+ be called from applets, because in some libraries,
+ dispose() blows shit up if it's called by a user who
+ doesn't know what they're doing.
+
serialEvent in interface gnu.io.SerialPortEventListener
+
+
+
+
+
+
+
+
+buffer
+
+public void buffer(int count)
+
+
Set number of bytes to buffer before calling serialEvent()
+ in the host applet.
+
+
+
+
+
+
+
+
+
+
+
+bufferUntil
+
+public void bufferUntil(int what)
+
+
Set a specific byte to buffer until before calling
+ serialEvent() in the host applet.
+
+
+
+
+
+
+
+
+
+
+
+available
+
+public int available()
+
+
Returns the number of bytes that have been read from serial
+ and are waiting to be dealt with by the user.
+
+
+
+
+
+
+
+
+
+
+
+clear
+
+public void clear()
+
+
Ignore all the bytes read so far and empty the buffer.
+
+
+
+
+
+
+
+
+
+
+
+read
+
+public int read()
+
+
Returns a number between 0 and 255 for the next byte that's
+ waiting in the buffer.
+ Returns -1 if there was no byte (although the user should
+ first check available() to see if things are ready to avoid this)
+
+
+
+
+
+
+
+
+
+
+
+last
+
+public int last()
+
+
Same as read() but returns the very last value received
+ and clears the buffer. Useful when you just want the most
+ recent value sent over the port.
+
+
+
+
+
+
+
+
+
+
+
+readChar
+
+public char readChar()
+
+
Returns the next byte in the buffer as a char.
+ Returns -1, or 0xffff, if nothing is there.
+
+
+
+
+
+
+
+
+
+
+
+lastChar
+
+public char lastChar()
+
+
Just like last() and readChar().
+
+
+
+
+
+
+
+
+
+
+
+readBytes
+
+public byte[] readBytes()
+
+
Return a byte array of anything that's in the serial buffer.
+ Not particularly memory/speed efficient, because it creates
+ a byte array on each read, but it's easier to use than
+ readBytes(byte b[]) (see below).
+
+
+
+
+
+
+
+
+
+
+
+readBytes
+
+public int readBytes(byte[] outgoing)
+
+
Grab whatever is in the serial buffer, and stuff it into a
+ byte buffer passed in by the user. This is more memory/time
+ efficient than readBytes() returning a byte[] array.
+
+ Returns an int for how many bytes were read. If more bytes
+ are available than can fit into the byte array, only those
+ that will fit are read.
+
+
+
+
+
+
+
+
+
+
+
+readBytesUntil
+
+public byte[] readBytesUntil(int interesting)
+
+
Reads from the serial port into a buffer of bytes up to and
+ including a particular character. If the character isn't in
+ the serial buffer, then 'null' is returned.
+
+
+
+
+
+
+
+
+
+
+
+readBytesUntil
+
+public int readBytesUntil(int interesting,
+ byte[] outgoing)
+
+
Reads from the serial port into a buffer of bytes until a
+ particular character. If the character isn't in the serial
+ buffer, then 'null' is returned.
+
+ If outgoing[] is not big enough, then -1 is returned,
+ and an error message is printed on the console.
+ If nothing is in the buffer, zero is returned.
+ If 'interesting' byte is not in the buffer, then 0 is returned.
+
+
+
+
+
+
+
+
+
+
+
+readString
+
+public java.lang.String readString()
+
+
Return whatever has been read from the serial port so far
+ as a String. It assumes that the incoming characters are ASCII.
+
+ If you want to move Unicode data, you can first convert the
+ String to a byte stream in the representation of your choice
+ (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
+
Combination of readBytesUntil and readString. See caveats in
+ each function. Returns null if it still hasn't found what
+ you're looking for.
+
+ If you want to move Unicode data, you can first convert the
+ String to a byte stream in the representation of your choice
+ (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(int what)
+
+
This will handle both ints, bytes and chars transparently.
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(byte[] bytes)
+
+
+
+
+
+
+
+
+
+
+
+write
+
+public void write(java.lang.String what)
+
+
Write a String to the output. Note that this doesn't account
+ for Unicode (two bytes per char), nor will it send UTF8
+ characters.. It assumes that you mean to send a byte buffer
+ (most often the case for networking and serial i/o) and
+ will only use the bottom 8 bits of each char in the string.
+ (Meaning that internally it uses String.getBytes)
+
+ If you want to move Unicode data, you can first convert the
+ String to a byte stream in the representation of your choice
+ (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
+
+
+
+
+
+
+
+
+
+
+
+list
+
+public static java.lang.String[] list()
+
+
If this just hangs and never completes on Windows,
+ it may be because the DLL doesn't have its exec bit set.
+ Why the hell that'd be the case, who knows.
+
Capture(PApplet parent,
+ int requestWidth,
+ int requestHeight)
+
+
+
+
+
+
Capture(PApplet parent,
+ int reqWidth,
+ int reqHeight,
+ int frameRate)
+
+
+
+
+
+
Capture(PApplet parent,
+ int reqWidth,
+ int reqHeight,
+ java.lang.String name)
+
+
+
+
+
+
Capture(PApplet parent,
+ int requestWidth,
+ int requestHeight,
+ java.lang.String name,
+ int frameRate)
+
+
+ If 'name' is null or the empty string, it won't set a specific
+ device, which means that QuickTime will use that last device
+ used by a QuickTime application.
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ boolean
+
available()
+
+
+ True if a frame is ready to be read.
+
+
+
+ void
+
crop(int x,
+ int y,
+ int w,
+ int h)
+
+
+ Set the video to crop from its original.
+
+
+
+ void
+
dispose()
+
+
+ Called by PApplet to shut down video so that QuickTime
+ can be used later by another applet.
+
+
+
+ void
+
format(int which)
+
+
+ Set the video format standard to use on the
+ video digitizer: NTSC, PAL, or SECAM.
+
+
+
+ void
+
frameRate(int iframeRate)
+
+
+ Set the frameRate for how quickly new frames are read
+ from the capture device.
+
+
+
+ void
+
init(PApplet parent,
+ int requestWidth,
+ int requestHeight,
+ java.lang.String name,
+ int frameRate)
+
+
+
+
+
+
+static java.lang.String[]
+
list()
+
+
+ Get a list of all available captures as a String array.
+
+
+
+ void
+
noCrop()
+
+
+ Remove the cropping (if any) of the image.
Temporary storage for the raw image
+ data read directly from the capture device
+
+
+
+
+
+
+
+dataWidth
+
+public int dataWidth
+
+
+
+
+
+
+
+dataHeight
+
+public int dataHeight
+
+
+
+
+
+
+
+dataRowBytes
+
+public int dataRowBytes
+
+
+
+
+
+
+
+crop
+
+public boolean crop
+
+
True if this image is currently being cropped
+
+
+
+
+
+
+
+cropX
+
+public int cropX
+
+
+
+
+
+
+
+cropY
+
+public int cropY
+
+
+
+
+
+
+
+cropW
+
+public int cropW
+
+
+
+
+
+
+
+cropH
+
+public int cropH
+
+
+
+
+
+
+
+frameRate
+
+public int frameRate
+
+
+
+
+
+
+
+raw
+
+public quicktime.util.RawEncodedImage raw
+
+
+
+
+
+
+
+capture
+
+public quicktime.std.sg.SequenceGrabber capture
+
+
+
+
+
+
+
+channel
+
+public quicktime.std.sg.SGVideoChannel channel
+
+
the guy who's doing all the work
+
+
+
+
+
+
+
+
+
+
+
+Constructor Detail
+
+
+
+
+Capture
+
+public Capture(PApplet parent,
+ int requestWidth,
+ int requestHeight)
+
+
+
+
+
+Capture
+
+public Capture(PApplet parent,
+ int reqWidth,
+ int reqHeight,
+ int frameRate)
+
+
+
+
+
+Capture
+
+public Capture(PApplet parent,
+ int reqWidth,
+ int reqHeight,
+ java.lang.String name)
+
+
+
+
+
+Capture
+
+public Capture(PApplet parent,
+ int requestWidth,
+ int requestHeight,
+ java.lang.String name,
+ int frameRate)
+
+
If 'name' is null or the empty string, it won't set a specific
+ device, which means that QuickTime will use that last device
+ used by a QuickTime application.
+
+ Unfortunately, Apple's QuickTime API uses the name to select devices,
+ and in some cases there might be cameras with the same name on a machine.
+ If you ask for a camera of the same name in sequence, you might see if it
+ just does the right thing and grabs each separate camera in succession.
+ If that doesn't work, you might try calling settings() which will
+ bring up the prompt where you can select a capture device.
+
+ If the following function:
+
public void captureEvent(Capture c)
+ is defined in the host PApplet, then it will be called every
+ time a new frame is available from the capture device.
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+init
+
+public void init(PApplet parent,
+ int requestWidth,
+ int requestHeight,
+ java.lang.String name,
+ int frameRate)
+
+
+
+
+
+
+
+
+
+
+
+available
+
+public boolean available()
+
+
True if a frame is ready to be read.
+
+ // put this somewhere inside draw
+ if (capture.available()) capture.read();
+
+ Alternatively, you can use captureEvent(Capture c) to notify you
+ whenever available() is set to true. In which case, things might
+ look like this:
+
+ public void captureEvent(Capture c) {
+ c.read();
+ // do something exciting now that c has been updated
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+crop
+
+public void crop(int x,
+ int y,
+ int w,
+ int h)
+
+
Set the video to crop from its original.
+
+ It seems common that captures add lines to the top or bottom
+ of an image, so this can be useful for removing them.
+ Internally, the pixel buffer size returned from QuickTime is
+ often a different size than requested, so crop will be set
+ more often than not.
+
+
+
+
+
+
+
+
+
+
+
+noCrop
+
+public void noCrop()
+
+
Remove the cropping (if any) of the image.
+
+ By default, cropping is often enabled to trim out black pixels.
+ But if you'd rather deal with them yourself (so as to avoid
+ an extra lag while the data is moved around) you can shut it off.
+
+
+
+
+
+
+
+
+
+
+
+read
+
+public void read()
+
+
+
+
+
+
+
+
+
+
+
+run
+
+public void run()
+
+
+
Specified by:
run in interface java.lang.Runnable
+
+
+
+
+
+
+
+
+frameRate
+
+public void frameRate(int iframeRate)
+
+
Set the frameRate for how quickly new frames are read
+ from the capture device.
+
+
+
+
+
+
+
+
+
+
+
+stop
+
+public void stop()
+
+
Called by applets to stop capturing video.
+
+
+
+
+
+
+
+
+
+
+
+dispose
+
+public void dispose()
+
+
Called by PApplet to shut down video so that QuickTime
+ can be used later by another applet.
+
+
+
+
+
+
+
+
+
+
+
+source
+
+public void source(int which)
+
+
Set the format to ask for from the video digitizer:
+ TUNER, COMPOSITE, SVIDEO, or COMPONENT.
+
+ The constants are just aliases to the constants returned from
+ QuickTime's getInputFormat() function, so any valid constant from
+ that will work just fine.
+
+
+
+
+
+
+
+
+
+
+
+format
+
+public void format(int which)
+
+
Set the video format standard to use on the
+ video digitizer: NTSC, PAL, or SECAM.
+
+ The constants are just aliases to the constants used for
+ QuickTime's setInputStandard() function, so any valid
+ constant from that will work just fine.
+
+
+
+
+
+
+
+
+
+
+
+settings
+
+public void settings()
+
+
Show the settings dialog for this input device.
+
+
+
+
+
+
+
+
+
+
+
+list
+
+public static java.lang.String[] list()
+
+
Get a list of all available captures as a String array.
+ i.e. println(Capture.list()) will show you the goodies.
+
+public Movie(PApplet parent,
+ java.lang.String filename,
+ int ifps)
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+init
+
+public void init(PApplet parent,
+ java.lang.String filename,
+ int fps)
+
+
+
+
+
+
+
+
+
+
+
+available
+
+public boolean available()
+
+
+
+
+
+
+
+
+
+
+
+read
+
+public void read()
+
+
+
+
+
+
+
+
+
+
+
+play
+
+public void play()
+
+
Begin playing the movie, with no repeat.
+
+
+
+
+
+
+
+
+
+
+
+loop
+
+public void loop()
+
+
Begin playing the movie, with repeat.
+
+
+
+
+
+
+
+
+
+
+
+noLoop
+
+public void noLoop()
+
+
Shut off the repeating loop.
+
+
+
+
+
+
+
+
+
+
+
+pause
+
+public void pause()
+
+
Pause the movie at its current time.
+
+
+
+
+
+
+
+
+
+
+
+stop
+
+public void stop()
+
+
Stop the movie, and rewind.
+
+
+
+
+
+
+
+
+
+
+
+frameRate
+
+public void frameRate(int ifps)
+
+
Set how often new frames are to be read from the movie.
+ Does not actually set the speed of the movie playback,
+ that's handled by the speed() method.
+
+
+
+
+
+
+
+
+
+
+
+speed
+
+public void speed(float rate)
+
+
Set a multiplier for how fast/slow the movie should be run.
+ The default is 1.0.
+
+
speed(2) will play the movie at double speed (2x).
+
speed(0.5) will play at half speed.
+
speed(-1) will play backwards at regular speed.
+
+
+
+
+
+
+
+
+
+
+
+
+time
+
+public float time()
+
+
Return the current time in seconds.
+ The number is a float so fractions of seconds can be used.
+
+
+
+
+
+
+
+
+
+
+
+jump
+
+public void jump(float where)
+
+
Jump to a specific location (in seconds).
+ The number is a float so fractions of seconds can be used.
+
+
+
+
+
+
+
+
+
+
+
+duration
+
+public float duration()
+
+
Get the full length of this movie (in seconds).
+
+
+
+
+
+
+
+
+
+
+
+run
+
+public void run()
+
+
+
Specified by:
run in interface java.lang.Runnable
+
+
+
+
+
+
+
+
+dispose
+
+public void dispose()
+
+
Call this to halt the movie from running, and stop its thread.
+
MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename)
+
+
+ Create a movie with the specified width, height, and filename.
+
+
+
MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename,
+ int _rate)
+
+
+ Create a movie with the specified width, height, filename, and frame rate.
+
+
+
MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename,
+ int _rate,
+ int _codecType,
+ int _codecQuality)
+
+
+ Create a movie with the specified width, height, filename, frame rate,
+ and codec type and quality.
+
+
+
MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename,
+ int _rate,
+ int _codecType,
+ int _codecQuality,
+ int _keyFrameRate)
+
+
+ Create a movie with the specified width, height, filename, frame rate,
+ codec type and quality, and key frame rate.
+public MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename)
+
+
Create a movie with the specified width, height, and filename.
+ The movie will be created at 15 frames per second.
+ The codec will be set to RAW and quality set to HIGH.
+
+
+
+
+
+MovieMaker
+
+public MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename,
+ int _rate)
+
+
Create a movie with the specified width, height, filename, and frame rate.
+ The codec will be set to RAW and quality set to HIGH.
+
+
+
+
+
+MovieMaker
+
+public MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename,
+ int _rate,
+ int _codecType,
+ int _codecQuality)
+
+
Create a movie with the specified width, height, filename, frame rate,
+ and codec type and quality. Key frames will be set at 15 frames.
+
+
+
+
+
+MovieMaker
+
+public MovieMaker(PApplet p,
+ int _w,
+ int _h,
+ java.lang.String _filename,
+ int _rate,
+ int _codecType,
+ int _codecQuality,
+ int _keyFrameRate)
+
+
Create a movie with the specified width, height, filename, frame rate,
+ codec type and quality, and key frame rate.
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+addFrame
+
+public void addFrame()
+
+
+
+
+
+
+
+
+addFrame
+
+public void addFrame(int[] _pixels,
+ int w,
+ int h)
addAttribute(java.lang.String key,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI,
+ java.lang.String value,
+ java.lang.String type)
+
+
+ This method is called when a new attribute of an XML element is
+ encountered.
+
+
+
+ void
+
addPCData(java.io.Reader reader,
+ java.lang.String systemID,
+ int lineNr)
+
+
+ This method is called when a PCDATA element is encountered.
+
+
+
+ void
+
elementAttributesProcessed(java.lang.String name,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI)
+
+
+ This method is called when the attributes of an XML element have been
+ processed.
+
+
+
+ void
+
endElement(java.lang.String name,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI)
+
+
+ This method is called when the end of an XML elemnt is encountered.
+
+
+
+ java.lang.Object
+
getResult()
+
+
+ Returns the result of the building process.
+
+
+
+ void
+
newProcessingInstruction(java.lang.String target,
+ java.io.Reader reader)
+
+
+ This method is called when a processing instruction is encountered.
+
+
+
+ void
+
startBuilding(java.lang.String systemID,
+ int lineNr)
+
+
+ This method is called before the parser starts processing its input.
+
+
+
+ void
+
startElement(java.lang.String name,
+ java.lang.String nsPrefix,
+ java.lang.String nsURI,
+ java.lang.String systemID,
+ int lineNr)
+
+
+ This method is called when a new XML element is encountered.
This method is called when a new attribute of an XML element is
+ encountered.
+
+
+
Parameters:
key - the key (name) of the attribute.
nsPrefix - the prefix used to identify the namespace. If no
+ namespace has been specified, this parameter is null.
nsURI - the URI associated with the namespace. If no
+ namespace has been specified, or no URI is
+ associated with nsPrefix, this parameter is null.
value - the value of the attribute.
type - the type of the attribute. If no type is known,
+ "CDATA" is returned.
+
Throws:
+
java.lang.Exception - If an exception occurred while processing the event.
+
+
+
+
+
+addPCData
+
+public void addPCData(java.io.Reader reader,
+ java.lang.String systemID,
+ int lineNr)
+
+
This method is called when a PCDATA element is encountered. A Java
+ reader is supplied from which you can read the data. The reader will
+ only read the data of the element. You don't need to check for
+ boundaries. If you don't read the full element, the rest of the data
+ is skipped. You also don't have to care about entities; they are
+ resolved by the parser.
+
+
+
Parameters:
reader - the Java reader from which you can retrieve the data.
systemID - the system ID of the XML data source.
lineNr - the line in the source where the element starts.
+
+
+
+
+
+getResult
+
+public java.lang.Object getResult()
+
+
Returns the result of the building process. This method is called just
+ before the parse method of StdXMLParser returns.
+
Starts a new stream from a Java reader. The new stream is used
+ temporary to read data from. If that stream is exhausted, control
+ returns to the parent stream.
+
+
+
Parameters:
reader - the non-null reader to read the new data from
Starts a new stream from a Java reader. The new stream is used
+ temporary to read data from. If that stream is exhausted, control
+ returns to the parent stream.
+
+
+
Parameters:
reader - the non-null reader to read the new data from
isInternalEntity - true if the reader is produced by resolving
+ an internal entity
+
+
+
+
+
+getStreamLevel
+
+public int getStreamLevel()
+
+
Returns the current "level" of the stream on the stack of streams.
+
+
+
+
+
+
+
+
+getLineNr
+
+public int getLineNr()
+
+
Returns the line number of the data in the current stream.
+
+XMLElement is an XML element. This is the base class used for the
+ Processing XML library, representing a single node of an XML tree.
+
+ This code is based on a modified version of NanoXML by Marc De Scheemaecker.
+
Begin parsing XML data passed in from a PApplet. This code
+ wraps exception handling, for more advanced exception handling,
+ use the constructor that takes a Reader or InputStream.
+
Return the #PCDATA content of the element. If the element has a
+ combination of #PCDATA content and child elements, the #PCDATA
+ sections can be retrieved as unnamed child objects. In this case,
+ this method returns null.
+
+
+
+
+
+
+
Returns:
the content.
+
+
+
+
+
+setContent
+
+public void setContent(java.lang.String content)
+
+
Sets the #PCDATA content. It is an error to call this method with a
+ non-null value if there are child objects.
+
+XMLValidator implementation based on NonValidator (which implemented
+ IXMLValidator in the original NanoXML).
+ This implementation processes the DTD and handles entity definitions.
+ It does not do any validation itself.
+
attributeAdded(java.lang.String key,
+ java.lang.String value,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ Indicates that an attribute has been added to the current element.
+
+
+
+ void
+
elementAttributesProcessed(java.lang.String name,
+ java.util.Properties extraAttributes,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ This method is called when the attributes of an XML element have been
+ processed.
+
+
+
+ void
+
elementEnded(java.lang.String name,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ Indicates that the current element has ended.
+
+
+
+ void
+
elementStarted(java.lang.String name,
+ java.lang.String systemId,
+ int lineNr)
+
+
+ Indicates that an element has been started.
This method is called when the attributes of an XML element have been
+ processed.
+ If there are attributes with a default value which have not been
+ specified yet, they have to be put into extraAttributes.
+
+
+
Parameters:
name - the name of the element.
extraAttributes - where to put extra attributes.
systemId - the system ID of the XML data of the element.
lineNr - the line number in the XML data of the element.
The PGraphics renderer associated with this PApplet
+
+
+
+
+
+
+frame
+
+java.awt.Frame frame
+
+
The frame containing this applet (if any)
+
+
+
+
+
+
+screen
+
+java.awt.Dimension screen
+
+
The screen size when the applet was started.
+
+ Access this via screen.width and screen.height. To make an applet
+ run at full screen, use size(screen.width, screen.height).
+
+ If you have multiple displays, this will be the size of the main
+ display. Running full screen across multiple displays isn't
+ particularly supported, and requires more monkeying with the values.
+ This probably can't/won't be fixed until/unless I get a dual head
+ system.
+
+ Note that this won't update if you change the resolution
+ of your screen once the the applet is running.
+
+ This variable is not static, because future releases need to be better
+ at handling multiple displays.
+
A leech graphics object that is echoing all events.
+
+
+
+
+
+
+args
+
+java.lang.String[] args
+
+
Command line options passed in from main().
+
+ This does not include the arguments passed in to PApplet itself.
+
+
+
+
+
+
+sketchPath
+
+java.lang.String sketchPath
+
+
Path to sketch folder
+
+
+
+
+
+
+defaultSize
+
+boolean defaultSize
+
+
true if no size() command has been executed. This is used to wait until
+ a size has been set before placing in the window and showing it.
+
+
+
+
+
+
+resizeRequest
+
+boolean resizeRequest
+
+
+
+
+
+
+resizeWidth
+
+int resizeWidth
+
+
+
+
+
+
+resizeHeight
+
+int resizeHeight
+
+
+
+
+
+
+pixels
+
+int[] pixels
+
+
Pixel buffer from this applet's PGraphics.
+
+ When used with OpenGL or Java2D, this value will
+ be null until loadPixels() has been called.
+
+
+
+
+
+
+width
+
+int width
+
+
width of this applet's associated PGraphics
+
+
+
+
+
+
+height
+
+int height
+
+
height of this applet's associated PGraphics
+
+
+
+
+
+
+mouseX
+
+int mouseX
+
+
current x position of the mouse
+
+
+
+
+
+
+mouseY
+
+int mouseY
+
+
current y position of the mouse
+
+
+
+
+
+
+pmouseX
+
+int pmouseX
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+pmouseY
+
+int pmouseY
+
+
Previous x/y position of the mouse. This will be a different value
+ when inside a mouse handler (like the mouseMoved() method) versus
+ when inside draw(). Inside draw(), pmouseX is updated once each
+ frame, but inside mousePressed() and friends, it's updated each time
+ an event comes through. Be sure to use only one or the other type of
+ means for tracking pmouseX and pmouseY within your sketch, otherwise
+ you're gonna run into trouble.
+
+
+
+
+
+
+dmouseX
+
+int dmouseX
+
+
previous mouseX/Y for the draw loop, separated out because this is
+ separate from the pmouseX/Y when inside the mouse event handlers.
+
+
+
+
+
+
+dmouseY
+
+int dmouseY
+
+
previous mouseX/Y for the draw loop, separated out because this is
+ separate from the pmouseX/Y when inside the mouse event handlers.
+
+
+
+
+
+
+emouseX
+
+int emouseX
+
+
pmouseX/Y for the event handlers (mousePressed(), mouseDragged() etc)
+ these are different because mouse events are queued to the end of
+ draw, so the previous position has to be updated on each event,
+ as opposed to the pmouseX/Y that's used inside draw, which is expected
+ to be updated once per trip through draw().
+
+
+
+
+
+
+emouseY
+
+int emouseY
+
+
pmouseX/Y for the event handlers (mousePressed(), mouseDragged() etc)
+ these are different because mouse events are queued to the end of
+ draw, so the previous position has to be updated on each event,
+ as opposed to the pmouseX/Y that's used inside draw, which is expected
+ to be updated once per trip through draw().
+
+
+
+
+
+
+firstMouse
+
+boolean firstMouse
+
+
Used to set pmouseX/Y to mouseX/Y the first time mouseX/Y are used,
+ otherwise pmouseX/Y are always zero, causing a nasty jump.
+
+ Just using (frameCount == 0) won't work since mouseXxxxx()
+ may not be called until a couple frames into things.
+
+
+
+
+
+
+mouseButton
+
+int mouseButton
+
+
Last mouse button pressed, one of LEFT, CENTER, or RIGHT.
+
+ If running on Mac OS, a ctrl-click will be interpreted as
+ the righthand mouse button (unlike Java, which reports it as
+ the left mouse).
+
+
+
+
+
+
+mousePressed
+
+boolean mousePressed
+
+
+
+
+
+
+mouseEvent
+
+java.awt.event.MouseEvent mouseEvent
+
+
+
+
+
+
+key
+
+char key
+
+
Last key pressed.
+
+ If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT,
+ this will be set to CODED (0xffff or 65535).
+
+
+
+
+
+
+keyCode
+
+int keyCode
+
+
When "key" is set to CODED, this will contain a Java key code.
+
+ For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT.
+ Also available are ALT, CONTROL and SHIFT. A full set of constants
+ can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables.
+
+
+
+
+
+
+keyPressed
+
+boolean keyPressed
+
+
true if the mouse is currently pressed.
+
+
+
+
+
+
+keyEvent
+
+java.awt.event.KeyEvent keyEvent
+
+
the last KeyEvent object passed into a mouse function.
+
+
+
+
+
+
+focused
+
+boolean focused
+
+
Gets set to true/false as the applet gains/loses focus.
+
+
+
+
+
+
+online
+
+boolean online
+
+
true if the applet is online.
+
+ This can be used to test how the applet should behave
+ since online situations are different (no file writing, etc).
+
+
+
+
+
+
+millisOffset
+
+long millisOffset
+
+
Time in milliseconds when the applet was started.
+
+ Used by the millis() function.
+
+
+
+
+
+
+frameRate
+
+float frameRate
+
+
The current value of frames per second.
+
+ The initial value will be 10 fps, and will be updated with each
+ frame thereafter. The value is not instantaneous (since that
+ wouldn't be very useful since it would jump around so much),
+ but is instead averaged (integrated) over several frames.
+ As such, this value won't be valid until after 5-10 frames.
+
+
+
+
+
+
+frameRateLastNanos
+
+long frameRateLastNanos
+
+
Last time in nanoseconds that frameRate was checked
+
+
+
+
+
+
+frameRateTarget
+
+float frameRateTarget
+
+
As of release 0116, frameRate(60) is called as a default
+
+
+
+
+
+
+frameRatePeriod
+
+long frameRatePeriod
+
+
+
+
+
+
+looping
+
+boolean looping
+
+
+
+
+
+
+redraw
+
+boolean redraw
+
+
flag set to true when a redraw is asked for by the user
+
+
+
+
+
+
+frameCount
+
+int frameCount
+
+
How many frames have been displayed since the applet started.
+
+ This value is read-only do not attempt to set it,
+ otherwise bad things will happen.
+
+ Inside setup(), frameCount is 0.
+ For the first iteration of draw(), frameCount will equal 1.
+
+
+
+
+
+
+finished
+
+boolean finished
+
+
true if this applet has had it.
+
+
+
+
+
+
+exitCalled
+
+boolean exitCalled
+
+
true if exit() has been called so that things shut down
+ once the main thread kicks off.
+
By trial and error, four image loading threads seem to work best when
+ loading images from online. This is consistent with the number of open
+ connections that web browsers will maintain. The variable is made public
+ (however no accessor has been added since it's esoteric) if you really
+ want to have control over the value used. For instance, when loading local
+ files, it might be better to only have a single thread (or two) loading
+ images so that you're disk isn't simply jumping around.
+
-
-
-
diff --git a/build/shared/lib/icon.gif b/build/shared/lib/icon.gif
deleted file mode 100644
index 62597c0cf..000000000
Binary files a/build/shared/lib/icon.gif and /dev/null differ
diff --git a/build/shared/lib/keywords.txt b/build/shared/lib/keywords.txt
index 1634c277c..178b933f9 100644
--- a/build/shared/lib/keywords.txt
+++ b/build/shared/lib/keywords.txt
@@ -57,7 +57,7 @@ true KEYWORD1
unsigned KEYWORD1
void KEYWORD1 Void
while KEYWORD1 While
-word KEYWORD1 Word
+word KEYWORD1 Word
# operators aren't highlighted, but may have documentation
@@ -102,7 +102,7 @@ char KEYWORD2 char_
float KEYWORD2 float_
int KEYWORD2 int_
long KEYWORD2 long_
-word KEYWORD2 word_
+word KEYWORD2 word_
# KEYWORD2 specifies methods and functions
@@ -130,13 +130,13 @@ sq KEYWORD2 Sq
sqrt KEYWORD2 Sqrt
tan KEYWORD2 Tan
-bitRead KEYWORD2 BitRead
-bitWrite KEYWORD2 BitWrite
-bitSet KEYWORD2 BitSet
-bitClear KEYWORD2 BitClear
-bit KEYWORD2 Bit
-highByte KEYWORD2 HighByte
-lowByte KEYWORD2 LowByte
+bitRead KEYWORD2 BitRead
+bitWrite KEYWORD2 BitWrite
+bitSet KEYWORD2 BitSet
+bitClear KEYWORD2 BitClear
+bit KEYWORD2 Bit
+highByte KEYWORD2 HighByte
+lowByte KEYWORD2 LowByte
analogReference KEYWORD2 AnalogReference
analogRead KEYWORD2 AnalogRead
@@ -155,7 +155,7 @@ pinMode KEYWORD2 PinMode
pulseIn KEYWORD2 PulseIn
shiftOut KEYWORD2 ShiftOut
-Serial KEYWORD3
+Serial KEYWORD3
Serial KEYWORD2
begin KEYWORD2 Serial_Begin
read KEYWORD2 Serial_Read
@@ -165,4 +165,4 @@ available KEYWORD2 Serial_Available
flush KEYWORD2 Serial_Flush
setup KEYWORD3 Setup
-loop KEYWORD3 Loop
\ No newline at end of file
+loop KEYWORD3 Loop
diff --git a/build/shared/lib/loading.gif b/build/shared/lib/loading.gif
deleted file mode 100755
index 133635807..000000000
Binary files a/build/shared/lib/loading.gif and /dev/null differ
diff --git a/build/shared/lib/mrj.jar b/build/shared/lib/mrj.jar
deleted file mode 100755
index 5faa8e8af..000000000
Binary files a/build/shared/lib/mrj.jar and /dev/null differ
diff --git a/build/shared/lib/preferences.txt b/build/shared/lib/preferences.txt
index c40779eac..a9d3c1deb 100755
--- a/build/shared/lib/preferences.txt
+++ b/build/shared/lib/preferences.txt
@@ -1,26 +1,32 @@
+# !!!!!!!! UNLIKE PREVIOUS VERSIONS OF PROCESSING !!!!!!!!!!
# DO NOT MODIFY THIS FILE, OR DELETE SETTINGS FROM THIS FILE
# These are the default preferences. If you want to modify
# them directly, use the per-user local version of the file:
-# Documents and Settings -> Application Data ->
-# Arduino -> preferences.txt (on windows)
+# Documents and Settings -> [username] -> Application Data ->
+# Processing -> preferences.txt (on Windows XP)
-# ~/Library -> Arduino -> preferences.txt (on macosx)
+# Users -> [username] -> AppData -> Roaming ->
+# Processing -> preferences.txt (on Windows Vista)
-# ~/.processing -> preferences.txt (on linux)
+# ~/Library -> Processing -> preferences.txt (on Mac OS X)
-# You'll have problems running Arduino if you incorrectly
+# ~/.processing -> preferences.txt (on Linux)
+
+# The exact location of your preferences file can be found at
+# the bottom of the Preferences window inside Processing.
+
+# Because AppData and Application Data may be considered
+# hidden or system folders on Windows, you'll have to ensure
+# that they're visible in order to get at preferences.txt
+
+# You'll have problems running Processing if you incorrectly
# modify lines in this file.
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-# Some colors have been hardcoded into the source in app/ in order to ensure
-# consistency with the images distributed and stored with the application.
-# They have been commented out below so that users who install an old
-# version of the software will not get incorrect colors left-over from this
-# config file.
# DEFAULT PATHS FOR SKETCHBOOK AND SETTINGS
@@ -30,125 +36,65 @@
# note that this path should use forward slashes (like unix)
# instead of \ on windows or : on macos or whatever else
-# the .fallback locations are used in case the default location
-# cannot be written (and the line above it is not customized)
-
-# if you don't want users to have their sketchbook default to
-# "my documents/processing" on windows and "documents/processing" on osx,
-# set this to another path that will be used by default
-#sketchbook.path=sketchbook
-sketchbook.path.fallback=sketchbook
+# If you don't want users to have their sketchbook default to
+# "My Documents/Processing" on Windows and "Documents/Processing" on OS X,
+# set this to another path that will be used by default.
+# Note that this path must exist already otherwise it won't see
+# the sketchbook folder, and will instead assume the sketchbook
+# has gone missing, and that it should instead use the default.
+#sketchbook.path=
# if you don't want settings to go into "application data" on windows
# and "library" on macosx, set this to the alternate location.
#settings.path=data
-settings.path.fallback=data
# temporary build path, normally this goes into the default
# "temp" folder for that platform (as defined by java)
# but this can be used to set a specific file in case of problems
#build.path=build
+# By default, no sketches currently open
+last.sketch.count=0
+
+
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
# by default, check the processing server for any updates
# (please avoid disabling, this also helps us know basic numbers
-# on how many people are using Arduino)
+# on how many people are using Processing)
update.check = true
+# on windows, automatically associate .pde files with processing.exe
+platform.auto_file_type_associations = true
+
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
# default size for the main window
default.window.width = 500
default.window.height = 600
# font size for editor
editor.font=Monospaced,plain,12
-
-# monospaced on java 1.3 was monaco, but on 1.4 it has changed
-# to courier, which actually matches other platforms better.
-# (and removes the 12 point being too large issue)
-# monaco is nicer on macosx, so use that explicitly
+# Monaco is nicer on Mac OS X, so use that explicitly
editor.font.macosx = Monaco,plain,10
# anti-aliased text, turned off by default
editor.antialias=false
-# foreground and background colors
-editor.fgcolor=#000000
-editor.bgcolor=#ffffff
-
# color to be used for background when 'external editor' enabled
editor.external=false
-editor.external.bgcolor=#168299
-# styles for various types of text
-
-# comments
-editor.comment1.style=#777755,plain
-editor.comment2.style=#777755,plain
-
-# e.g abstract, final, private
-editor.keyword1.style=#cc6600,plain
-# e.g. beginShape, point, line
-editor.keyword2.style=#996600,plain
-# e.g. byte, char, short, color
-editor.keyword3.style=#993300,bold
-
-# constants: e.g. null, true, this, RGB, TWO_PI
-editor.literal1.style=#cc0000,plain
-# p5 built in variables: e.g. mouseX, width, pixels
-editor.literal2.style=#cc0000,plain
-
-# ?? maybe this is for words followed by a colon
-# like in case statements or goto
-editor.label.style=#7E7E00,bold
-
-# e.g. + - = /
-editor.operator.style=#000000,plain
-
-# caret blinking and caret color
+# caret blinking
editor.caret.blink=true
-editor.caret.color=#333300
-
-# selection color
-editor.selection.color=#ffcc00
-
-# highlight for the current line
-editor.linehighlight=true
-editor.linehighlight.color=#ddddbb
-
-# bracket/brace highlighting
-editor.brackethighlight=true
-editor.brackethighlight.color=#000000
-
-# little pooties at the end of lines that show where they finish
-editor.eolmarkers=false
-editor.eolmarkers.color=#99991A
# area that's not in use by the text (replaced with tildes)
editor.invalid=false
-editor.invalid.style=#7E7E00,bold
-#buttons.bgcolor = #044F6F
-buttons.status.font = SansSerif,plain,12
-buttons.status.color = #FFFFFF
-
-# settings for the tabs at the top
-# actual tab images are stored in the lib/ folder
-#header.bgcolor = #216886
-header.text.selected.color = #1A1A00
-header.text.unselected.color = #ffffff
-header.text.font = SansSerif,plain,12
-
-console = true
-console.color = #000000
-console.output.color = #ccccbb
+console = true
console.output.file = stdout.txt
-console.error.color = #ff3000
console.error.file = stderr.txt
-console.font = Monospaced,plain,11
-console.font.macosx = Monaco,plain,10
console.lines = 4
# set to false to disable automatically clearing the console
@@ -159,14 +105,6 @@ console.auto_clear = true
# the default is 500, lengthen at your own peril
console.length = 500
-status.notice.fgcolor = #ffffff
-#status.notice.bgcolor = #54919E
-status.error.fgcolor = #ffffff
-status.error.bgcolor = #662000
-status.prompt.fgcolor = #000000
-status.prompt.bgcolor = #cc9900
-status.font = SansSerif,plain,12
-
# convert tabs to spaces? how many spaces?
editor.tabs.expand = true
editor.tabs.size = 2
@@ -181,21 +119,20 @@ editor.divider.size = 0
# but keeps it from being annoyingly obtrusive
editor.divider.size.windows = 2
-# background color for full-screen presentation mode
-run.present.bgcolor = #666666
-
# any additional java options when running externally
# (for applets that are run external to the environment...
# those with a code folder, or using any libraries)
# if you hose this and can't run things, it's your own durn fault
run.options =
+# settings for the -XmsNNNm and -XmxNNNm command line option
+run.options.memory = false
+run.options.memory.initial = 64
+run.options.memory.maximum = 256
+
# example of increasing the memory size for applets run externally
#run.options = -Xms128m -Xmx1024m
-# color of the stop button when running in present mode
-run.present.stop.color = #cccccc
-
# index of the default display to use for present mode
# (this setting not yet completely implemented)
run.display = 1
@@ -203,24 +140,39 @@ run.display = 1
# set internally
#run.window.bgcolor=
-# minimum size for the run window. windows can't go much smaller.
-# macosx can, though it's sorta nice to have the border.
-run.window.width.minimum = 120
-run.window.height.minimum = 120
+# set to false to open a new untitled window when closing the last window
+# (otherwise, the environment will quit)
+# default to the relative norm for the different platforms,
+# but the setting can be changed in the prefs dialog anyway
+#sketchbook.closing_last_window_quits = true
+#sketchbook.closing_last_window_quits.macosx = false
-# prompt for sketch location when 'new' is hit
-sketchbook.prompt = false
-
-# true if empty sketches should be removed automatically
-sketchbook.auto_clean = true
+apple.laf.useScreenMenuBar=true
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-history.recording = true
+#history.recording = true
# for advanced users, enable option to export a library
-export.library = false
+#export.library = false
+
+# which platforms to export by default
+export.application.platform.windows = true
+export.application.platform.macosx = true
+export.application.platform.linux = true
+
+# whether or not to export as full screen (present) mode
+export.application.fullscreen = false
+
+# whether to show the stop button when exporting to application
+export.application.stop = true
+
+# false will place all exported files into a single .jar
+export.applet.separate_jar_files = false
+
+# set to false to no longer delete applet or application folders before export
+export.delete_target_folder = true
# may be useful when attempting to debug the preprocessor
preproc.save_build_files=false
@@ -246,42 +198,30 @@ preproc.substitute_unicode = true
# viewed in (at least) Mozilla or IE. useful when debugging the preprocessor.
preproc.output_parse_tree = false
-# jdk version to use..
-preproc.jdk_version = 1.1
-
-# base imports to include for java 1.1 (or higher)
-preproc.imports.jdk11 = java.applet,java.awt,java.awt.image,java.awt.event,java.io,java.net,java.text,java.util,java.util.zip
-
-# additional imports when exporting to java 1.3 or higher
-preproc.imports.jdk13 = javax.sound.midi,javax.sound.midi.spi,javax.sound.sampled,javax.sound.sampled.spi
-
-# additional imports when exporting to java 1.4 or higher
-preproc.imports.jdk14 = javax.xml.parsers,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stream,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers
+# imports to use by default (changed for 0149, some imports removed)
+preproc.imports = java.applet,java.awt,java.awt.image,java.awt.event,java.io,java.net,java.text,java.util,java.util.zip,java.util.regex
# set the browser to be used on linux
browser.linux = mozilla
-# coloring for the editor line number status bar at the bottom of the screen
-#linestatus.bgcolor = #044F6F
-linestatus.font = SansSerif,plain,10
-linestatus.color = #ffffff
-linestatus.height = 20
+# set to the program to be used for launching apps on linux
+#launcher.linux = gnome-open
-# set the upload defaults
-upload.verbose=false
-upload.using=bootloader
+# FULL SCREEN (PRESENT MODE)
+run.present.bgcolor = #666666
+run.present.stop.color = #cccccc
+# starting in release 0159, don't use full screen exclusive anymore
+run.present.exclusive = false
+# use this by default to hide the menu bar and dock on osx
+run.present.exclusive.macosx = true
-# set the parallel port defaults (used if upload.programmer=dapa)
-parallel.port=0x378
+# ARDUINO PREFERENCES
+board = atmega328
+
+upload.using = bootloader
-# set the serial port defaults
serial.port=COM1
serial.databits=8
serial.stopbits=1
serial.parity=N
serial.debug_rate=9600
-serial.burn_rate=115200
-
-build.verbose=false
-
-board=atmega328
\ No newline at end of file
diff --git a/build/shared/lib/registry.jar b/build/shared/lib/registry.jar
deleted file mode 100644
index 2aefa0f39..000000000
Binary files a/build/shared/lib/registry.jar and /dev/null differ
diff --git a/build/shared/lib/buttons.gif b/build/shared/lib/theme/buttons.gif
similarity index 100%
rename from build/shared/lib/buttons.gif
rename to build/shared/lib/theme/buttons.gif
diff --git a/build/shared/lib/resize.gif b/build/shared/lib/theme/resize.gif
similarity index 100%
rename from build/shared/lib/resize.gif
rename to build/shared/lib/theme/resize.gif
diff --git a/build/shared/lib/tab-sel-left.gif b/build/shared/lib/theme/tab-sel-left.gif
similarity index 100%
rename from build/shared/lib/tab-sel-left.gif
rename to build/shared/lib/theme/tab-sel-left.gif
diff --git a/build/shared/lib/tab-sel-menu.gif b/build/shared/lib/theme/tab-sel-menu.gif
similarity index 100%
rename from build/shared/lib/tab-sel-menu.gif
rename to build/shared/lib/theme/tab-sel-menu.gif
diff --git a/build/shared/lib/tab-sel-mid.gif b/build/shared/lib/theme/tab-sel-mid.gif
similarity index 100%
rename from build/shared/lib/tab-sel-mid.gif
rename to build/shared/lib/theme/tab-sel-mid.gif
diff --git a/build/shared/lib/tab-sel-right.gif b/build/shared/lib/theme/tab-sel-right.gif
similarity index 100%
rename from build/shared/lib/tab-sel-right.gif
rename to build/shared/lib/theme/tab-sel-right.gif
diff --git a/build/shared/lib/tab-unsel-left.gif b/build/shared/lib/theme/tab-unsel-left.gif
similarity index 100%
rename from build/shared/lib/tab-unsel-left.gif
rename to build/shared/lib/theme/tab-unsel-left.gif
diff --git a/build/shared/lib/tab-unsel-menu.gif b/build/shared/lib/theme/tab-unsel-menu.gif
similarity index 100%
rename from build/shared/lib/tab-unsel-menu.gif
rename to build/shared/lib/theme/tab-unsel-menu.gif
diff --git a/build/shared/lib/tab-unsel-mid.gif b/build/shared/lib/theme/tab-unsel-mid.gif
similarity index 100%
rename from build/shared/lib/tab-unsel-mid.gif
rename to build/shared/lib/theme/tab-unsel-mid.gif
diff --git a/build/shared/lib/tab-unsel-right.gif b/build/shared/lib/theme/tab-unsel-right.gif
similarity index 100%
rename from build/shared/lib/tab-unsel-right.gif
rename to build/shared/lib/theme/tab-unsel-right.gif
diff --git a/build/shared/lib/theme/theme.txt b/build/shared/lib/theme/theme.txt
new file mode 100644
index 000000000..d3404179c
--- /dev/null
+++ b/build/shared/lib/theme/theme.txt
@@ -0,0 +1,101 @@
+# GUI - STATUS
+status.notice.fgcolor = #000000
+status.notice.bgcolor = #54919e
+status.error.fgcolor = #ffffff
+status.error.bgcolor = #662000
+status.edit.fgcolor = #000000
+status.edit.bgcolor = #cc9900
+status.font = SansSerif,plain,12
+
+# GUI - TABS
+# settings for the tabs at the top
+# (tab images are stored in the lib/theme folder)
+header.bgcolor = #216886
+header.text.selected.color = #1a1a00
+header.text.unselected.color = #ffffff
+header.text.font = SansSerif,plain,12
+
+# GUI - CONSOLE
+console.font = Monospaced,plain,11
+console.font.macosx = Monaco,plain,10
+console.color = #000000
+console.output.color = #cccccc
+console.error.color = #ff3000
+
+# GUI - BUTTONS
+buttons.bgcolor = #044f6f
+buttons.status.font = SansSerif,plain,12
+buttons.status.color = #ffffff
+
+# GUI - LINESTATUS
+linestatus.color = #ffffff
+linestatus.bgcolor = #044f6f
+
+# EDITOR - DETAILS
+
+# foreground and background colors
+editor.fgcolor = #000000
+editor.bgcolor = #ffffff
+
+# highlight for the current line
+editor.linehighlight.color=#e2e2e2
+# highlight for the current line
+editor.linehighlight=true
+
+# caret blinking and caret color
+editor.caret.color = #333300
+
+# color to be used for background when 'external editor' enabled
+editor.external.bgcolor = #c8d2dc
+
+# selection color
+editor.selection.color = #ffcc00
+
+# area that's not in use by the text (replaced with tildes)
+editor.invalid.style = #7e7e7e,bold
+
+# little pooties at the end of lines that show where they finish
+editor.eolmarkers = false
+editor.eolmarkers.color = #999999
+
+# bracket/brace highlighting
+editor.brackethighlight = true
+editor.brackethighlight.color = #006699
+
+
+# TEXT - KEYWORDS
+
+# e.g abstract, final, private
+editor.keyword1.style = #cc6600,plain
+
+# e.g. beginShape, point, line
+editor.keyword2.style = #cc6600,plain
+
+# e.g. byte, char, short, color
+editor.keyword3.style = #cc6600,bold
+
+
+# TEXT - LITERALS
+
+# constants: e.g. null, true, this, RGB, TWO_PI
+editor.literal1.style = #006699,plain
+
+# p5 built in variables: e.g. mouseX, width, pixels
+editor.literal2.style = #006699,plain
+
+# e.g. + - = /
+editor.operator.style = #000000,plain
+
+# ?? maybe this is for words followed by a colon
+# like in case statements or goto
+editor.label.style = #7e7e7e,bold
+
+
+# TEXT - COMMENTS
+editor.comment1.style = #7e7e7e,plain
+editor.comment2.style = #7e7e7e,plain
+
+
+# LINE STATUS - editor line number status bar at the bottom of the screen
+linestatus.font = SansSerif,plain,10
+linestatus.height = 20
diff --git a/build/shared/libraries/howto.txt b/build/shared/libraries/howto.txt
new file mode 100644
index 000000000..9865ab19a
--- /dev/null
+++ b/build/shared/libraries/howto.txt
@@ -0,0 +1,5 @@
+This file has been replaced by an entire section of dev.processing.org
+dedicated to libraries, people who make libraries, and people who
+love library development trivia. The new page can be found here:
+
+http://dev.processing.org/libraries/
diff --git a/build/shared/libraries/javascript/library/export.txt b/build/shared/libraries/javascript/library/export.txt
new file mode 100644
index 000000000..a642bb596
--- /dev/null
+++ b/build/shared/libraries/javascript/library/export.txt
@@ -0,0 +1,6 @@
+# don't actually export anything.. this is only to link against
+# inside of the p5 environment
+applet=
+
+# for an application, export to prevent from breaking
+application=javascript.jar
\ No newline at end of file
diff --git a/build/shared/libraries/javascript/library/javascript.jar b/build/shared/libraries/javascript/library/javascript.jar
new file mode 100644
index 000000000..93c7b9251
Binary files /dev/null and b/build/shared/libraries/javascript/library/javascript.jar differ
diff --git a/build/shared/libraries/minim/library/jl1.0.jar b/build/shared/libraries/minim/library/jl1.0.jar
new file mode 100755
index 000000000..17f7c0aa7
Binary files /dev/null and b/build/shared/libraries/minim/library/jl1.0.jar differ
diff --git a/build/shared/libraries/minim/library/jsminim.jar b/build/shared/libraries/minim/library/jsminim.jar
new file mode 100755
index 000000000..4e6f6e564
Binary files /dev/null and b/build/shared/libraries/minim/library/jsminim.jar differ
diff --git a/build/shared/libraries/minim/library/minim-spi.jar b/build/shared/libraries/minim/library/minim-spi.jar
new file mode 100755
index 000000000..4760de485
Binary files /dev/null and b/build/shared/libraries/minim/library/minim-spi.jar differ
diff --git a/build/shared/libraries/minim/library/minim.jar b/build/shared/libraries/minim/library/minim.jar
new file mode 100755
index 000000000..eb053ccec
Binary files /dev/null and b/build/shared/libraries/minim/library/minim.jar differ
diff --git a/build/shared/libraries/minim/library/mp3spi1.9.4.jar b/build/shared/libraries/minim/library/mp3spi1.9.4.jar
new file mode 100755
index 000000000..019b86c93
Binary files /dev/null and b/build/shared/libraries/minim/library/mp3spi1.9.4.jar differ
diff --git a/build/shared/libraries/minim/library/tritonus_aos.jar b/build/shared/libraries/minim/library/tritonus_aos.jar
new file mode 100755
index 000000000..4a02386d4
Binary files /dev/null and b/build/shared/libraries/minim/library/tritonus_aos.jar differ
diff --git a/build/shared/libraries/minim/library/tritonus_share.jar b/build/shared/libraries/minim/library/tritonus_share.jar
new file mode 100755
index 000000000..bb367d17e
Binary files /dev/null and b/build/shared/libraries/minim/library/tritonus_share.jar differ
diff --git a/build/shared/libraries/minim/license.txt b/build/shared/libraries/minim/license.txt
new file mode 100755
index 000000000..d511905c1
--- /dev/null
+++ b/build/shared/libraries/minim/license.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/build/shared/libraries/minim/version.txt b/build/shared/libraries/minim/version.txt
new file mode 100755
index 000000000..10bf840ed
--- /dev/null
+++ b/build/shared/libraries/minim/version.txt
@@ -0,0 +1 @@
+2.0.1
\ No newline at end of file
diff --git a/build/shared/reference.zip b/build/shared/reference.zip
index 8ac9aa831..f1dd44524 100644
Binary files a/build/shared/reference.zip and b/build/shared/reference.zip differ
diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt
new file mode 100644
index 000000000..f50448527
--- /dev/null
+++ b/build/shared/revisions.txt
@@ -0,0 +1,241 @@
+PROCESSING 1.0.3 (REV 0165) - 24 February 2009
+
+Bug fix release to repair a couple of regressions caused by changes in 1.0.2,
+as well as a couple other new problems encountered since.
+
+[ bug fixes ]
+
++ endRecord or endRaw produces a RuntimeException with the PDF library
+ http://dev.processing.org/bugs/show_bug.cgi?id=1169
+
++ Problem with beginRaw/endRaw and OpenGL
+ http://dev.processing.org/bugs/show_bug.cgi?id=1171
+
++ Set strokeWeight on points and lines with begin/endRaw
+ http://dev.processing.org/bugs/show_bug.cgi?id=1172
+
++ Fix strokeWeight quirks with P3D when used with points and lines
+
++ ArrayIndexOutOfBoundsException with point()
+ http://dev.processing.org/bugs/show_bug.cgi?id=1168
+
+[ changes ]
+
++ Update to iText 2.1.4 for the PDF library
+
+
+PROCESSING 1.0.2 (REV 0164) - 21 February 2009
+
+This release fixes many bugs and adds two minor functions to the XML library.
+
+[ bug fixes ]
+
++ Empty "code" folder causing problems with Export
+ http://dev.processing.org/bugs/show_bug.cgi?id=1084
+
++ Sketches not loading when .pde file is opened from the Windows Explorer
+ on Asian Windows systems.
+ http://dev.processing.org/bugs/show_bug.cgi?id=1089
+
++ Disable copying of metadata and resource forks in OS X build
+ http://dev.processing.org/bugs/show_bug.cgi?id=1098
+
++ Suppress goofy Apple error message about JVMArchs
+
++ StringIndexOutOfBoundsException caused by import statements with no dots
+ http://dev.processing.org/bugs/show_bug.cgi?id=1145
+
++ Pressing in "Are you sure you want to Quit?" dialog causes quit
+ http://dev.processing.org/bugs/show_bug.cgi?id=1134
+
++ Fix QUADS and QUAD_STRIP with P2D
+ http://dev.processing.org/bugs/show_bug.cgi?id=1162
+
++ ArrayIndexOutOfBoundsException when drawing curves in P3D and OPENGL
+ http://dev.processing.org/bugs/show_bug.cgi?id=1153
+
++ Problems with negatve arc() angles in OpenGL, P3D, other inconsistencies
+ http://dev.processing.org/bugs/show_bug.cgi?id=1095
+
++ requestImage() causing problems with JAVA2D
+
++ Fix minor strokeWeight bug with OpenGL
+
++ Minor bug fix to SVG files that weren't being resized properly
+
++ OpenGL is rendering darker in 0149+
+ http://dev.processing.org/bugs/show_bug.cgi?id=958
+ Thanks to Dave Bollinger for tracking this down and providing a solution
+
++ OutOfMemoryError with ellipse() in P3D and OPENGL
+ http://dev.processing.org/bugs/show_bug.cgi?id=1086
+
++ ArrayIndexOutOfBoundsException with P3D and OPENGL
+ http://dev.processing.org/bugs/show_bug.cgi?id=1117
+
++ point(x,y) ignores noStroke() in some renderers
+ http://dev.processing.org/bugs/show_bug.cgi?id=1090
+
++ Fix Windows startup problem when scheme coloring was odd
+ http://dev.processing.org/bugs/show_bug.cgi?id=1109
+ Changes to the system theme could cause Processing to not launch
+
++ Fix several point() problems with P3D
+ http://dev.processing.org/bugs/show_bug.cgi?id=1110
+
++ nextPage() not working properly with PDF as the renderer
+ http://dev.processing.org/bugs/show_bug.cgi?id=1131
+
++ Save style information when nextPage() is called in PDF renderer
+
++ beginRaw() broken (no DXF, etc working)
+ http://dev.processing.org/bugs/show_bug.cgi?id=1099
+ http://dev.processing.org/bugs/show_bug.cgi?id=1144
+
++ Fix algorithm for quadratic to cubic curve conversion
+ http://dev.processing.org/bugs/show_bug.cgi?id=1122
+ Thanks to user bits.in.shambles for providing a fix.
+
++ tint() not working in P2D
+ http://dev.processing.org/bugs/show_bug.cgi?id=1132
+
++ blend() y coordinates inverted when using OpenGL
+ http://dev.processing.org/bugs/show_bug.cgi?id=1137
+
++ Fix for getChild() and getChildren() with XML elements that have null names
+
+[ additions ]
+
++ Added listChildren() method to XMLElement
+
++ Added optional toString(boolean) parameter to enable/disable indents
+ in XMLElement
+
+
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+PROCESSING 1.0.1 (REV 0163) - 29 November 2008
+
+Processing 1.0 has arrived! You can read an overview of changes introduced
+in the last few months here: http://processing.org/reference/changes.html
+
+Also see the "known issues" section of the troubleshooting page:
+http://processing.org/reference/troubleshooting/#known
+
+This release (1.0.1) fixes a handful of issues that only showed up once we
+had more testing, particularly with the wider audience we've received in the
+past week following the announcement.
+
+[ bug fixes ]
+
++ ArrayIndexOutOfBoundsException with File > New
+ http://dev.processing.org/bugs/show_bug.cgi?id=1067
+
++ "CallStaticVoidMethod() threw an exception" on some Mac OS X machines
+ http://dev.processing.org/bugs/show_bug.cgi?id=1063
+ http://dev.processing.org/bugs/show_bug.cgi?id=1078
+
++ "editor.indent" preference setting does not work properly
+ http://dev.processing.org/bugs/show_bug.cgi?id=1073
+
++ Fixed some "An error occurred while starting the application" problems
+
++ Added a note about the Minim library to the changes page.
+
++ Disable parsing of regexps with the split() command
+ http://dev.processing.org/bugs/show_bug.cgi?id=1060
+
++ Fixed ArrayIndexOutOfBoundsException in ellipseImpl().
+ http://dev.processing.org/bugs/show_bug.cgi?id=1068
+
++ Fixed problem where small ellipses weren't showing up.
+
+[ changes ]
+
++ Implement multi-line tab via tab key (also outdent)
+ http://dev.processing.org/bugs/show_bug.cgi?id=1075
+
++ Code with 'import' and a space incorrectly parsed as an import statement
+ http://dev.processing.org/bugs/show_bug.cgi?id=1064
+
+
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+PROCESSING 1.0 (REV 0162) - 24 November 2008
+
+Processing 1.0 has arrived! You can read an overview of changes introduced
+in the last few months here: http://processing.org/reference/changes.html
+
+[ known issues ]
+
++ Sketches that size(w, h, OPENGL) and do not clear the background on each
+ frame can cause major flickering or problems when the screen clears anyway.
+ There are several possible solutions:
+
+ 1. You may need to disable the default 2x smoothing by using
+ hint(DISABLE_OPENGL_2X_SMOOTH).
+
+ 2. Update the drivers for your graphics card.
+
+ 3. Get a decent graphics card -- the OpenGL renderer is for advanced
+ use, we don't support using it with cheaper built-in graphics hardware
+ like the Intel GMA 950.
+
+ 4. If you're running Windows Vista, try disabling the Aero theme.
+
+ This flickering issue is being tracked here:
+ http://dev.processing.org/bugs/show_bug.cgi?id=1056
+
++ "An error occurred while starting the application" when launching
+ Processing.exe on Windows. This is a high priority however we cannot
+ reproduce it on any of our test machines, which has delayed a fix.
+ http://dev.processing.org/bugs/show_bug.cgi?id=986
+
++ With P2D, P3D, and OPENGL, series of connected lines (such as the stroke
+ around a polygon, triangle, or ellipse) produce unattractive results when
+ strokeWeight is set.
+ http://dev.processing.org/bugs/show_bug.cgi?id=955
+
++ Unlike most applications, the menu bar is inside the editor window when
+ Processing is used with Mac OS X 10.5. This is a workaround for an Apple
+ bug in Java 1.5 and 1.6 on Mac OS X 10.5 that causes the menu bar to be
+ so excessively slow that the application appears to have crashed.
+ http://dev.processing.org/bugs/show_bug.cgi?id=786
+
+ Please file a bug report with Apple at bugreporter.apple.com if you want
+ this fixed. The problem has existed since the spring, and we first filed
+ a bug with them in June, and we have received no indication that it when
+ it will be fixed, or if it will ever be fixed.
+
+ Or if you want to take your chances with the slow menu bar,
+ you can change the default setting in the Preferences window.
+
++ Sketches that use the video library plus OpenGL have a problem on some
+ OS X machines. The workaround is listed in Comment #16 of this bug:
+ http://dev.processing.org/bugs/show_bug.cgi?id=882#c16
+
++ Command line support arrived in a recent release, but is not working yet.
+ http://dev.processing.org/bugs/show_bug.cgi?id=1048
+
++ OpenGL rendering is more dim/darker in release 0149 and later.
+ http://dev.processing.org/bugs/show_bug.cgi?id=958
+ Any help tracking this down would be most appreciated.
+
++ The first few frames of OpenGL sketches on Windows run slowly.
+ http://dev.processing.org/bugs/show_bug.cgi?id=874
+
++ When used with P3D, strokeWeight does not interpolate the Z-coordinates
+ of the lines, which means that when rotated, these flat lines may
+ disappear. (Since, uh, lines are, you know, flat.) The OPENGL renderer
+ setting does not share this problem because it always draws lines
+ perpendicular to the screen (which we hope to do in a future release).
+ http://dev.processing.org/bugs/show_bug.cgi?id=956
+
+
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+in spite of their historical feel good campiness, i've removed the
+notes from earlier releases because this file was getting out of hand.
diff --git a/build/shared/tools/Mangler/make.sh b/build/shared/tools/Mangler/make.sh
new file mode 100755
index 000000000..e1c1ce37b
--- /dev/null
+++ b/build/shared/tools/Mangler/make.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# The pde.jar file may be buried inside the .app file on Mac OS X.
+PDE=`find ../.. -name pde.jar`
+
+javac -target 1.5 \
+ -cp "../../lib/core.jar:$PDE" \
+ -d bin \
+ src/Mangler.java
+
+cd bin && zip -r ../tool/mangler.jar * && cd ..
diff --git a/build/shared/tools/Mangler/src/Mangler.java b/build/shared/tools/Mangler/src/Mangler.java
new file mode 100644
index 000000000..cfd527954
--- /dev/null
+++ b/build/shared/tools/Mangler/src/Mangler.java
@@ -0,0 +1,94 @@
+/* -*- 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 com.transformers.supermangletron;
+
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.swing.JOptionPane;
+
+import processing.app.Editor;
+import processing.app.tools.Tool;
+
+
+/**
+ * Example Tools menu entry.
+ */
+public class Mangler implements Tool {
+ Editor editor;
+
+
+ public void init(Editor editor) {
+ this.editor = editor;
+ }
+
+
+ public String getMenuTitle() {
+ return "Mangle Selection";
+ }
+
+
+ public void run() {
+ String sketchName = editor.getSketch().getName();
+
+ Object[] options = { "Yes, please", "No, thanks" };
+ int result = JOptionPane.showOptionDialog(editor,
+ "Is " + sketchName +
+ " ready for destruction?",
+ "Super Mangle Tron",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[1]);
+ if (result == JOptionPane.YES_OPTION) {
+ mangleSelection();
+ }
+ }
+
+
+ protected void mangleSelection() {
+ if (editor.isSelectionActive()) {
+ String selection = editor.getSelectedText();
+ char[] stuff = selection.toCharArray();
+ // Randomly swap a bunch of characters in the text
+ for (int i = 0; i < stuff.length / 10; i++) {
+ int a = (int) (Math.random() * stuff.length);
+ int b = (int) (Math.random() * stuff.length);
+ if (stuff[a] == '\n' || stuff[b] == '\n') {
+ continue; // skip newline characters
+ }
+ stuff[a] = selection.charAt(b);
+ stuff[b] = selection.charAt(a);
+ }
+ editor.startCompoundEdit();
+ editor.setSelectedText(new String(stuff));
+ editor.stopCompoundEdit();
+ editor.statusNotice("Now that feels better, doesn't it?");
+
+ } else {
+ editor.statusError("No selection, no dice.");
+ }
+ }
+}
diff --git a/build/shared/tools/howto.txt b/build/shared/tools/howto.txt
new file mode 100644
index 000000000..77df31c91
--- /dev/null
+++ b/build/shared/tools/howto.txt
@@ -0,0 +1,143 @@
+TOOLS IN PROCESSING
+
+With initial help from code contributed by fjen, Processing release 0147 and
+later have a dynamically loading tools menu, which can be used to expand the
+environment in fun and fantastic ways.
+
+A Tool is a chunk of code that runs from the Tools menu. Tools are a means
+of building onto the Processing Development Environment without needing to
+rebuild the beast from source.
+
+The interface (at least for now) is extremely simple:
+
+
+package processing.app.tools.Tool;
+
+public interface Tool extends Runnable {
+
+ public void init(Editor editor);
+
+ public void run();
+
+ public String getMenuTitle();
+}
+
+
+The init() method is called when an Editor window first opens. This means
+you won't have access to a sketch object, or a GUI, and should only do minimal
+setup. (However it'd be a good idea to stash the "Editor" object for later.)
+
+The run() method will be called by the main application when the tool is
+selected from the menu. This is called using invokeLater(), so that the tool
+can safely use Swing and any other GUI yackety yack. If you're using a Frame,
+you'll need to detect whether the Frame is already open (and bring it to the
+front) or whether to create a new window.
+
+Faceless tools also use the run() method. You should avail yourselves of the
+statusNotice() and statusError() methods in Editor, to let the user know what's
+happened. (As per p. 107 of the Processing Development Environment Tools
+Reference User Interface Guide.)
+
+The getMenuTitle() method just returns the title for what should appear in the
+Tools menu. Not doing shortcuts for now, because resolving them between tools
+(and the rest of the interface) is fugly. We would also need additional
+modifiers for shift and alt. It just gets messy quick. Ordering in the Tools
+menu is alphabetical.
+
+
+//////////////////////////////////////////////////////////////
+
+
+Where to put Tools
+
+Core tools live inside the "tools" subfolder of the Processing distribution,
+however users should install "contributed" tools in their sketchbook folder,
+inside a subfolder named "tools".
+
+If a tool works only with a particular release of Processing, then it may make
+sense for the user to put things into the Processing tools folder, however we'd
+like to keep users out of there as much as possible. In fact, it may not be
+visible in future releases of Processing (for instance, on Mac OS X, the tools
+folder is hidden inside the .app bundle).
+
+Tools should be laid out similar to libraries, though the structure is a little
+more flexible. The tool folder should be the name of the main class (without
+its package name but using the same capitalization), and have a subfolder named
+"tool" that contains the .jar and .zip files it uses. I'll use the included
+"Mangler" tool as an example.
+
+(This Tool is not built by default, due to a lack of non-dubious arguments
+regarding the usefulness of including (by default) a Tool that mangles code.)
+
+The folder should be called Mangler (note the capitalization), and contain:
+
+sketchbook/Mangler -> tool folder
+sketchbook/Mangler/tool -> location for code
+sketchbook/Mangler/tool/mangle.jar -> jar with one or more classes
+
+The naming of jar and zip files in the tool/* directory doesn't matter.
+
+When Processing loads, the jar and zip files will be searched for
+Mangler.class. Even though this tool is found in package poos.shoe,
+it will be sussed out. Package names are required.
+
+Loose .class files are not supported, use only jar and zip files.
+
+
+//////////////////////////////////////////////////////////////
+
+
+What You Can and Cannot Do
+
+The only API methods that are officially scrubbed and sanctioned by the
+Commissioner on Fair API and Proper Manners for use by the Tools classes
+are found in:
+
+processing.app.Base
+processing.app.Editor
+processing.app.Preferences
+processing.app.Sketch
+processing.app.SketchCode
+
+In fact, most of the API you should be talking to is inside Editor.
+Full API documentation can be found on dev.processing.org:
+http://dev.processing.org/reference/everything/
+(Keep in mind that this is not always perfectly up to date, but we'll try.)
+
+Of course, you're welcome to go spelunking through the rest of the API
+(that's where all the fun stuff is anyway), but don't be upset when something
+changes and breaks your tool and makes your users sad.
+
+Currently, native code is not supported with tools. This might be possible,
+but it's another potentially messy thing to dynamically add native library
+paths to running code. (See "Future Releases" below.)
+
+
+//////////////////////////////////////////////////////////////
+
+
+Future Releases
+
+In future releases, we are considering the following features:
+
+1. How shortcut keys are handled.
+ http://dev.processing.org/bugs/show_bug.cgi?id=140
+
+2. Whether to allow tools to dock into the Preferences panel.
+ http://dev.processing.org/bugs/show_bug.cgi?id=883
+
+3. A means to run native code from the Tools menu.
+ http://dev.processing.org/bugs/show_bug.cgi?id=884
+
+4. Methods for reorganizing the Tools menu, or placing contributed
+ Tools inside other menus (such as Edit or Sketch).
+ http://dev.processing.org/bugs/show_bug.cgi?id=885
+
+This is the first round of documentation for the Tools menu, we reserve the
+right to update, clarify, and change our mind in future releases.
+
+
+//////////////////////////////////////////////////////////////
+
+
+Ben Fry, last updated 19 August 2008
diff --git a/build/windows/.cvsignore b/build/windows/.cvsignore
deleted file mode 100644
index b6254aa90..000000000
--- a/build/windows/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-work*
-processing-*
-
diff --git a/build/windows/dist/avr_tools.zip b/build/windows/avr_tools.zip
similarity index 100%
rename from build/windows/dist/avr_tools.zip
rename to build/windows/avr_tools.zip
diff --git a/build/windows/dist.sh b/build/windows/dist.sh
index 71c89a3ac..1be4d2780 100755
--- a/build/windows/dist.sh
+++ b/build/windows/dist.sh
@@ -1,10 +1,19 @@
#!/bin/sh
-REVISION=`head -c 4 ../../todo.txt`
+REVISION=`head -1 ../../todo.txt | awk '{print $1}'`
+
+if [ $1 ]
+then
+ RELEASE=$1
+ echo Creating Arduino release $RELEASE...
+else
+ RELEASE=$REVISION
+ echo Creating Arduino distribution for revision $REVISION...
+fi
# check to see if the version number in the app is correct
# so that mikkel doesn't kick my ass
-VERSIONED=`cat ../../app/Base.java | grep $REVISION`
+VERSIONED=`cat ../../app/src/processing/app/Base.java | grep $REVISION`
if [ -z "$VERSIONED" ]
then
echo Fix the revision number in Base.java
@@ -13,113 +22,90 @@ fi
./make.sh
-echo Creating P5 distribution for revision $REVISION...
-echo
-
# remove any old boogers
rm -rf arduino
rm -rf arduino-*
-# use 'shared' files as starting point
-cp -r ../shared arduino
mkdir arduino
-#cp -r work/lib/targets arduino/lib
+cp -r ../shared/lib arduino/
+cp -r ../shared/tools arduino/
-# new style examples thing ala reas
-#cd arduino
-#mkdir examples
-#unzip -d examples -q dist/examples.zip
-#rm dist/examples.zip
-#rm -rf dist
-#cd ..
+cp dist/*.dll arduino/
+cp -r dist/drivers arduino/
-mv arduino/dist/examples arduino/examples
-rm -rf arduino/dist
+cp -r ../../hardware arduino/
-# extract reference
-cd arduino
-unzip reference.zip
-rm reference.zip
-cd ..
+
+if [ $1 ]
+then
+ # write the release version number into the output directory
+ echo $1 > arduino/lib/version.txt
+fi
+
+cp ../../app/lib/antlr.jar arduino/lib/
+cp ../../app/lib/ecj.jar arduino/lib/
+cp ../../app/lib/jna.jar arduino/lib/
+cp ../../app/lib/oro.jar arduino/lib/
+cp ../../app/lib/RXTXcomm.jar arduino/lib/
+
+cp ../../readme.txt arduino/
+
+echo Copying examples...
+cp -r ../shared/examples arduino/
+
+echo Extracting reference...
+unzip -q -d arduino/ ../shared/reference.zip
+
+unzip -q -d arduino/hardware avr_tools.zip
# add java (jre) files
unzip -q -d arduino jre.zip
-# copy stuff from work/
-cp work/readme.txt arduino
-cp -r work/hardware arduino
-cp -r work/drivers arduino
-#cp -r work/examples arduino
-
-# directories used by the app
-#mkdir arduino/lib/build
+# get platform-specific goodies from the dist dir
+cp launcher/arduino.exe arduino/
# grab pde.jar and export from the working dir
cp work/lib/pde.jar arduino/lib/
-cp work/java/lib/rt.jar arduino/lib/
-#cp work/lib/core.jar arduino/lib/
-#cp -r work/lib/export arduino/lib/
-#rm -rf arduino/lib/export/CVS
+cp work/lib/core.jar arduino/lib/
-# get jikes and depedencies
-#gunzip < dist/jikes.gz > arduino/jikes.exe
-cp dist/jikes.exe arduino/
-chmod +x arduino/jikes.exe
-
-#cp dist/ICE_JNIRegistry.dll arduino/
-#chmod +x arduino/ICE_JNIRegistry.dll
-#cp work/rxtxSerial.dll arduino/
-#chmod +x arduino/rxtxSerial.dll
-cp work/*.dll arduino
-chmod +x arduino/*.dll
-
-# get platform-specific goodies from the dist dir
-cp launcher/arduino.exe arduino/
-cp dist/run.bat arduino/
-chmod +x arduino/run.bat
-
-# convert notes.txt to windows LFs
+# convert revisions.txt to windows LFs
# the 2> is because the app is a little chatty
-unix2dos arduino/revisions.txt 2> /dev/null
+unix2dos arduino/readme.txt 2> /dev/null
unix2dos arduino/lib/preferences.txt 2> /dev/null
unix2dos arduino/lib/keywords.txt 2> /dev/null
-rm -f arduino/*.bak
-rm -f arduino/lib/*.bak
# remove boogers
+find arduino -name "*.bak" -exec rm -f {} ';'
find arduino -name "*~" -exec rm -f {} ';'
find arduino -name ".DS_Store" -exec rm -f {} ';'
find arduino -name "._*" -exec rm -f {} ';'
find arduino -name "Thumbs.db" -exec rm -f {} ';'
# chmod +x the crew
+find arduino -name "*.html" -exec chmod +x {} ';'
find arduino -name "*.dll" -exec chmod +x {} ';'
find arduino -name "*.exe" -exec chmod +x {} ';'
find arduino -name "*.html" -exec chmod +x {} ';'
-# clean out the svn entries
+# clean out the cvs entries
+find arduino -name "CVS" -exec rm -rf {} ';' 2> /dev/null
+find arduino -name ".cvsignore" -exec rm -rf {} ';'
find arduino -name ".svn" -exec rm -rf {} ';' 2> /dev/null
# zip it all up for release
echo Packaging standard release...
echo
-P5=arduino-$REVISION
+P5=arduino-$RELEASE
mv arduino $P5
zip -rq $P5.zip $P5
# nah, keep the new directory around
#rm -rf $P5
# zip up another for experts
+#echo Expert release is disabled until further notice.
echo Packaging expert release...
echo
-
cp -a $P5 $P5-expert
-
-# can't use the run.bat that's tied to a local jre
-rm $P5-expert/run.bat
-cp dist/run-expert.bat $P5-expert/run.bat
-chmod +x $P5-expert/run.bat
-
# remove enormous java runtime
rm -rf $P5-expert/java
zip -rq $P5-expert.zip $P5-expert
diff --git a/build/windows/dist/ICE_JNIRegistry.dll b/build/windows/dist/ICE_JNIRegistry.dll
deleted file mode 100755
index 5463a70a4..000000000
Binary files a/build/windows/dist/ICE_JNIRegistry.dll and /dev/null differ
diff --git a/build/windows/dist/bootloader/burn.bat b/build/windows/dist/bootloader/burn.bat
deleted file mode 100755
index 04caa2b5b..000000000
--- a/build/windows/dist/bootloader/burn.bat
+++ /dev/null
@@ -1,8 +0,0 @@
-REM TODO: need way to specify serial port.
-
-cd ..
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_lock=0xFF
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xca
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --erase --upload --verify if=bootloader\ATMegaBOOT.hex
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_lock=0xCF
-cd bootloader
diff --git a/build/windows/dist/bootloader/burnpara.bat b/build/windows/dist/bootloader/burnpara.bat
deleted file mode 100755
index a9a1c87c0..000000000
--- a/build/windows/dist/bootloader/burnpara.bat
+++ /dev/null
@@ -1,18 +0,0 @@
-@REM burnpara.bat
-@REM David A. Mellis
-@REM 27 January 2006
-@REM Burns bootloader onto Arduino board with a parallel port programmer.
-
-REM Before running this for the first time, you'll need to install giveio.
-REM Unzip drivers\giveio.zip, then run ginstall.bat.
-
-@REM Need to be in directory with cygwin dll's.
-cd ..
-
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=dapa -dlpt=0x378 --wr_lock=0xFF
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=dapa -dlpt=0x378 --wr_fuse_l=0xdf --wr_fuse_h=0xca
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=dapa -dlpt=0x378 --erase --upload --verify if=bootloader\ATMegaBOOT.hex
-tools\avr\bin\uisp -dpart=ATmega8 -dprog=dapa -dlpt=0x378 --wr_lock=0xCF
-
-@REM Return to bootloader directory.
-cd bootloader
diff --git a/build/windows/dist/core/makefile.w2k b/build/windows/dist/core/makefile.w2k
deleted file mode 100755
index d2568b41d..000000000
--- a/build/windows/dist/core/makefile.w2k
+++ /dev/null
@@ -1,420 +0,0 @@
-# Hey Emacs, this is a -*- makefile -*-
-#
-# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
-# Released to the Public Domain
-# Please read the make user manual!
-#
-# Additional material for this makefile was submitted by:
-# Tim Henigan
-# Peter Fleury
-# Reiner Patommel
-# Sander Pool
-# Frederik Rouleau
-# Markus Pfaff
-#
-# On command line:
-#
-# make all = Make software.
-#
-# make clean = Clean out built project files.
-#
-# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
-#
-# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
-# 4.07 or greater).
-#
-# make program = Download the hex file to the device, using avrdude. Please
-# customize the avrdude settings below first!
-#
-# make filename.s = Just compile filename.c into the assembler code only
-#
-# To rebuild project do "make clean" then "make all".
-#
-
-
-# MCU name
-MCU = atmega8
-
-# Output format. (can be srec, ihex, binary)
-FORMAT = ihex
-
-# Target file name (without extension).
-TARGET = prog
-
-
-# List C source files here. (C dependencies are automatically generated.)
-#SRC = pins_arduino.c wiring.c ../avrlib/uart.c ../avrlib/buffer.c ../avrlib/timer.c ../avrlib/a2d.c $(TARGET).c
-SRC = pins_arduino.c wiring.c ../avrlib/uart.c ../avrlib/buffer.c ../avrlib/timer.c $(TARGET).c
-
-# List Assembler source files here.
-# Make them always end in a capital .S. Files ending in a lowercase .s
-# will not be considered source files but generated files (assembler
-# output from the compiler), and will be deleted upon "make clean"!
-# Even though the DOS/Win* filesystem matches both .s and .S the same,
-# it will preserve the spelling of the filenames, and gcc itself does
-# care about how the name is spelled on its command-line.
-ASRC =
-
-
-
-# Optimization level, can be [0, 1, 2, 3, s].
-# 0 = turn off optimization. s = optimize for size.
-# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
-OPT = s
-
-
-# List any extra directories to look for include files here.
-# Each directory must be seperated by a space.
-EXTRAINCDIRS = ../avrlib
-
-
-# Compiler flag to set the C Standard level.
-# c89 - "ANSI" C
-# gnu89 - c89 plus GCC extensions
-# c99 - ISO C99 standard (not yet fully implemented)
-# gnu99 - c99 plus GCC extensions
-CSTANDARD = -std=gnu99
-
-# Place -D or -U options here
-CDEFS = -D F_CPU=16000000L
-
-# Place -I options here
-CINCS =
-
-
-# Compiler flags.
-# -g: generate debugging information
-# -O*: optimization level
-# -f...: tuning, see GCC manual and avr-libc documentation
-# -Wall...: warning level
-# -Wa,...: tell GCC to pass this to the assembler.
-# -adhlns...: create assembler listing
-CFLAGS = -g
-CFLAGS += $(CDEFS) $(CINCS)
-CFLAGS += -O$(OPT)
-CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -Wall -Wstrict-prototypes
-CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
-CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
-CFLAGS += $(CSTANDARD)
-
-
-
-# Assembler flags.
-# -Wa,...: tell GCC to pass this to the assembler.
-# -ahlms: create listing
-# -gstabs: have the assembler create line number information; note that
-# for use in COFF files, additional information about filenames
-# and function names needs to be present in the assembler source
-# files -- see avr-libc docs [FIXME: not yet described there]
-ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
-
-
-
-#Additional libraries.
-
-# Minimalistic printf version
-PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
-
-# Floating point printf version (requires MATH_LIB = -lm below)
-PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
-
-PRINTF_LIB =
-
-# Minimalistic scanf version
-SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
-
-# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
-SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
-
-SCANF_LIB =
-
-MATH_LIB = -lm
-
-# External memory options
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# used for variables (.data/.bss) and heap (malloc()).
-#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# only used for heap (malloc()).
-#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
-
-EXTMEMOPTS =
-
-# Linker flags.
-# -Wl,...: tell GCC to pass this to linker.
-# -Map: create map file
-# --cref: add cross reference to map file
-LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
-LDFLAGS += $(EXTMEMOPTS)
-LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
-
-
-
-
-# Programming support using avrdude. Settings and variables.
-
-# Programming hardware: alf avr910 avrisp bascom bsd
-# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
-#
-# Type: avrdude -c ?
-# to get a full listing.
-#
-AVRDUDE_PROGRAMMER = stk500
-
-# com1 = serial port. Use lpt1 to connect to parallel port.
-AVRDUDE_PORT = com1 # programmer connected to serial device
-
-AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
-#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
-
-
-# Uncomment the following if you want avrdude's erase cycle counter.
-# Note that this counter needs to be initialized first using -Yn,
-# see avrdude manual.
-#AVRDUDE_ERASE_COUNTER = -y
-
-# Uncomment the following if you do /not/ wish a verification to be
-# performed after programming the device.
-#AVRDUDE_NO_VERIFY = -V
-
-# Increase verbosity level. Please use this when submitting bug
-# reports about avrdude. See
-# to submit bug reports.
-#AVRDUDE_VERBOSE = -v -v
-
-AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
-AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
-AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
-AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
-
-
-
-# ---------------------------------------------------------------------------
-
-# Define directories, if needed.
-DIRAVR = ..\..\..\tools\avr
-DIRAVRBIN = $(DIRAVR)\bin
-
-# Define programs and commands.
-SHELL = sh
-CC = ${DIRAVRBIN}\avr-gcc
-OBJCOPY = ${DIRAVRBIN}\avr-objcopy
-OBJDUMP = ${DIRAVRBIN}\avr-objdump
-SIZE = ${DIRAVRBIN}\avr-size
-NM = ${DIRAVRBIN}\avr-nm
-AVRDUDE = avrdude
-REMOVE = rm -f
-COPY = cp
-
-
-
-
-# Define Messages
-# English
-MSG_ERRORS_NONE = Errors: none
-MSG_BEGIN = -------- begin --------
-MSG_END = -------- end --------
-MSG_SIZE_BEFORE = Size before:
-MSG_SIZE_AFTER = Size after:
-MSG_COFF = Converting to AVR COFF:
-MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
-MSG_FLASH = Creating load file for Flash:
-MSG_EEPROM = Creating load file for EEPROM:
-MSG_EXTENDED_LISTING = Creating Extended Listing:
-MSG_SYMBOL_TABLE = Creating Symbol Table:
-MSG_LINKING = Linking:
-MSG_COMPILING = Compiling:
-MSG_ASSEMBLING = Assembling:
-MSG_CLEANING = Cleaning project:
-
-
-
-
-# Define all object files.
-OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
-
-# Define all listing files.
-LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
-
-
-# Compiler flags to generate dependency files.
-GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,dep/$(@F).d
-
-
-# Combine all necessary flags and optional flags.
-# Add target processor to flags.
-ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
-ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
-
-
-
-
-
-# Default target.
-#all: begin gccversion sizebefore build sizeafter finished end
-all: begin gccversion build finished end
-
-build: elf hex eep lss sym
-
-elf: $(TARGET).elf
-hex: $(TARGET).hex
-eep: $(TARGET).eep
-lss: $(TARGET).lss
-sym: $(TARGET).sym
-
-
-
-# Eye candy.
-# AVR Studio 3.x does not check make's exit code but relies on
-# the following magic strings to be generated by the compile job.
-begin:
- @echo
- @echo $(MSG_BEGIN)
-
-finished:
- @echo $(MSG_ERRORS_NONE)
-
-end:
- @echo $(MSG_END)
- @echo
-
-
-# Display size of file.
-HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
-ELFSIZE = $(SIZE) -A $(TARGET).elf
-sizebefore:
- @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
-
-sizeafter:
- @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
-
-
-
-# Display compiler version information.
-gccversion :
- @$(CC) --version
-
-
-
-# Program the device.
-program: $(TARGET).hex $(TARGET).eep
- $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
-
-
-
-
-# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
-COFFCONVERT=$(OBJCOPY) --debugging \
---change-section-address .data-0x800000 \
---change-section-address .bss-0x800000 \
---change-section-address .noinit-0x800000 \
---change-section-address .eeprom-0x810000
-
-
-coff: $(TARGET).elf
- @echo
- @echo $(MSG_COFF) $(TARGET).cof
- $(COFFCONVERT) -O coff-avr $< $(TARGET).cof
-
-
-extcoff: $(TARGET).elf
- @echo
- @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
- $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
-
-
-
-# Create final output files (.hex, .eep) from ELF output file.
-%.hex: %.elf
- @echo
- @echo $(MSG_FLASH) $@
- $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
-
-%.eep: %.elf
- @echo
- @echo $(MSG_EEPROM) $@
- -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
- --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
-
-# Create extended listing file from ELF output file.
-%.lss: %.elf
- @echo
- @echo $(MSG_EXTENDED_LISTING) $@
- $(OBJDUMP) -h -S $< > $@
-
-# Create a symbol table from ELF output file.
-%.sym: %.elf
- @echo
- @echo $(MSG_SYMBOL_TABLE) $@
- $(NM) -n $< > $@
-
-
-
-# Link: create ELF output file from object files.
-.SECONDARY : $(TARGET).elf
-.PRECIOUS : $(OBJ)
-%.elf: $(OBJ)
- @echo
- @echo $(MSG_LINKING) $@
- $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
-
-
-# Compile: create object files from C source files.
-%.o : %.c
- @echo
- @echo $(MSG_COMPILING) $<
- $(CC) -c $(ALL_CFLAGS) $< -o $@
-
-
-# Compile: create assembler files from C source files.
-%.s : %.c
- $(CC) -S $(ALL_CFLAGS) $< -o $@
-
-
-# Assemble: create object files from assembler source files.
-%.o : %.S
- @echo
- @echo $(MSG_ASSEMBLING) $<
- $(CC) -c $(ALL_ASFLAGS) $< -o $@
-
-
-
-# Target: clean project.
-clean: begin clean_list finished end
-
-clean_list :
- @echo
- @echo $(MSG_CLEANING)
- $(REMOVE) $(TARGET).hex
- $(REMOVE) $(TARGET).eep
- $(REMOVE) $(TARGET).obj
- $(REMOVE) $(TARGET).cof
- $(REMOVE) $(TARGET).elf
- $(REMOVE) $(TARGET).map
- $(REMOVE) $(TARGET).obj
- $(REMOVE) $(TARGET).a90
- $(REMOVE) $(TARGET).sym
- $(REMOVE) $(TARGET).lnk
- $(REMOVE) $(TARGET).lss
- $(REMOVE) $(OBJ)
- $(REMOVE) $(LST)
- $(REMOVE) $(SRC:.c=.s)
- $(REMOVE) $(SRC:.c=.d)
- $(REMOVE) dep/*
-
-
-
-# Include the dependency files.
--include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
-
-
-# Listing of phony targets.
-.PHONY : all begin finish end sizebefore sizeafter gccversion \
-build elf hex eep lss sym coff extcoff \
-clean clean_list program
-
-
-
diff --git a/build/windows/dist/core/makefile.win b/build/windows/dist/core/makefile.win
deleted file mode 100755
index 46deb6a16..000000000
--- a/build/windows/dist/core/makefile.win
+++ /dev/null
@@ -1,420 +0,0 @@
-# Hey Emacs, this is a -*- makefile -*-
-#
-# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
-# Released to the Public Domain
-# Please read the make user manual!
-#
-# Additional material for this makefile was submitted by:
-# Tim Henigan
-# Peter Fleury
-# Reiner Patommel
-# Sander Pool
-# Frederik Rouleau
-# Markus Pfaff
-#
-# On command line:
-#
-# make all = Make software.
-#
-# make clean = Clean out built project files.
-#
-# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
-#
-# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
-# 4.07 or greater).
-#
-# make program = Download the hex file to the device, using avrdude. Please
-# customize the avrdude settings below first!
-#
-# make filename.s = Just compile filename.c into the assembler code only
-#
-# To rebuild project do "make clean" then "make all".
-#
-
-
-# MCU name
-MCU = atmega8
-
-# Output format. (can be srec, ihex, binary)
-FORMAT = ihex
-
-# Target file name (without extension).
-TARGET = prog
-
-
-# List C source files here. (C dependencies are automatically generated.)
-#SRC = pins_arduino.c wiring.c ../avrlib/uart.c ../avrlib/buffer.c ../avrlib/timer.c ../avrlib/a2d.c $(TARGET).c
-SRC = pins_arduino.c wiring.c ../avrlib/uart.c ../avrlib/buffer.c ../avrlib/timer.c $(TARGET).c
-
-# List Assembler source files here.
-# Make them always end in a capital .S. Files ending in a lowercase .s
-# will not be considered source files but generated files (assembler
-# output from the compiler), and will be deleted upon "make clean"!
-# Even though the DOS/Win* filesystem matches both .s and .S the same,
-# it will preserve the spelling of the filenames, and gcc itself does
-# care about how the name is spelled on its command-line.
-ASRC =
-
-
-
-# Optimization level, can be [0, 1, 2, 3, s].
-# 0 = turn off optimization. s = optimize for size.
-# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
-OPT = s
-
-
-# List any extra directories to look for include files here.
-# Each directory must be seperated by a space.
-EXTRAINCDIRS = ../avrlib
-
-
-# Compiler flag to set the C Standard level.
-# c89 - "ANSI" C
-# gnu89 - c89 plus GCC extensions
-# c99 - ISO C99 standard (not yet fully implemented)
-# gnu99 - c99 plus GCC extensions
-CSTANDARD = -std=gnu99
-
-# Place -D or -U options here
-CDEFS = -D F_CPU=16000000L
-
-# Place -I options here
-CINCS =
-
-
-# Compiler flags.
-# -g: generate debugging information
-# -O*: optimization level
-# -f...: tuning, see GCC manual and avr-libc documentation
-# -Wall...: warning level
-# -Wa,...: tell GCC to pass this to the assembler.
-# -adhlns...: create assembler listing
-CFLAGS = -g
-CFLAGS += $(CDEFS) $(CINCS)
-CFLAGS += -O$(OPT)
-CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
-CFLAGS += -Wall -Wstrict-prototypes
-CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
-CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
-CFLAGS += $(CSTANDARD)
-
-
-
-# Assembler flags.
-# -Wa,...: tell GCC to pass this to the assembler.
-# -ahlms: create listing
-# -gstabs: have the assembler create line number information; note that
-# for use in COFF files, additional information about filenames
-# and function names needs to be present in the assembler source
-# files -- see avr-libc docs [FIXME: not yet described there]
-ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
-
-
-
-#Additional libraries.
-
-# Minimalistic printf version
-PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
-
-# Floating point printf version (requires MATH_LIB = -lm below)
-PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
-
-PRINTF_LIB =
-
-# Minimalistic scanf version
-SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
-
-# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
-SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
-
-SCANF_LIB =
-
-MATH_LIB = -lm
-
-# External memory options
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# used for variables (.data/.bss) and heap (malloc()).
-#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# only used for heap (malloc()).
-#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
-
-EXTMEMOPTS =
-
-# Linker flags.
-# -Wl,...: tell GCC to pass this to linker.
-# -Map: create map file
-# --cref: add cross reference to map file
-LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
-LDFLAGS += $(EXTMEMOPTS)
-LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
-
-
-
-
-# Programming support using avrdude. Settings and variables.
-
-# Programming hardware: alf avr910 avrisp bascom bsd
-# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
-#
-# Type: avrdude -c ?
-# to get a full listing.
-#
-AVRDUDE_PROGRAMMER = stk500
-
-# com1 = serial port. Use lpt1 to connect to parallel port.
-AVRDUDE_PORT = com1 # programmer connected to serial device
-
-AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
-#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
-
-
-# Uncomment the following if you want avrdude's erase cycle counter.
-# Note that this counter needs to be initialized first using -Yn,
-# see avrdude manual.
-#AVRDUDE_ERASE_COUNTER = -y
-
-# Uncomment the following if you do /not/ wish a verification to be
-# performed after programming the device.
-#AVRDUDE_NO_VERIFY = -V
-
-# Increase verbosity level. Please use this when submitting bug
-# reports about avrdude. See
-# to submit bug reports.
-#AVRDUDE_VERBOSE = -v -v
-
-AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
-AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
-AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
-AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
-
-
-
-# ---------------------------------------------------------------------------
-
-# Define directories, if needed.
-DIRAVR = ../../../tools/avr
-DIRAVRBIN = $(DIRAVR)/bin
-
-# Define programs and commands.
-SHELL = sh
-CC = ${DIRAVRBIN}/avr-gcc
-OBJCOPY = ${DIRAVRBIN}/avr-objcopy
-OBJDUMP = ${DIRAVRBIN}/avr-objdump
-SIZE = ${DIRAVRBIN}/avr-size
-NM = ${DIRAVRBIN}/avr-nm
-AVRDUDE = avrdude
-REMOVE = rm -f
-COPY = cp
-
-
-
-
-# Define Messages
-# English
-MSG_ERRORS_NONE = Errors: none
-MSG_BEGIN = -------- begin --------
-MSG_END = -------- end --------
-MSG_SIZE_BEFORE = Size before:
-MSG_SIZE_AFTER = Size after:
-MSG_COFF = Converting to AVR COFF:
-MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
-MSG_FLASH = Creating load file for Flash:
-MSG_EEPROM = Creating load file for EEPROM:
-MSG_EXTENDED_LISTING = Creating Extended Listing:
-MSG_SYMBOL_TABLE = Creating Symbol Table:
-MSG_LINKING = Linking:
-MSG_COMPILING = Compiling:
-MSG_ASSEMBLING = Assembling:
-MSG_CLEANING = Cleaning project:
-
-
-
-
-# Define all object files.
-OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
-
-# Define all listing files.
-LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
-
-
-# Compiler flags to generate dependency files.
-GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,dep/$(@F).d
-
-
-# Combine all necessary flags and optional flags.
-# Add target processor to flags.
-ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
-ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
-
-
-
-
-
-# Default target.
-#all: begin gccversion sizebefore build sizeafter finished end
-all: begin gccversion build finished end
-
-build: elf hex eep lss sym
-
-elf: $(TARGET).elf
-hex: $(TARGET).hex
-eep: $(TARGET).eep
-lss: $(TARGET).lss
-sym: $(TARGET).sym
-
-
-
-# Eye candy.
-# AVR Studio 3.x does not check make's exit code but relies on
-# the following magic strings to be generated by the compile job.
-begin:
- @echo
- @echo $(MSG_BEGIN)
-
-finished:
- @echo $(MSG_ERRORS_NONE)
-
-end:
- @echo $(MSG_END)
- @echo
-
-
-# Display size of file.
-HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
-ELFSIZE = $(SIZE) -A $(TARGET).elf
-sizebefore:
- @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
-
-sizeafter:
- @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
-
-
-
-# Display compiler version information.
-gccversion :
- @$(CC) --version
-
-
-
-# Program the device.
-program: $(TARGET).hex $(TARGET).eep
- $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
-
-
-
-
-# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
-COFFCONVERT=$(OBJCOPY) --debugging \
---change-section-address .data-0x800000 \
---change-section-address .bss-0x800000 \
---change-section-address .noinit-0x800000 \
---change-section-address .eeprom-0x810000
-
-
-coff: $(TARGET).elf
- @echo
- @echo $(MSG_COFF) $(TARGET).cof
- $(COFFCONVERT) -O coff-avr $< $(TARGET).cof
-
-
-extcoff: $(TARGET).elf
- @echo
- @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
- $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
-
-
-
-# Create final output files (.hex, .eep) from ELF output file.
-%.hex: %.elf
- @echo
- @echo $(MSG_FLASH) $@
- $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
-
-%.eep: %.elf
- @echo
- @echo $(MSG_EEPROM) $@
- -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
- --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
-
-# Create extended listing file from ELF output file.
-%.lss: %.elf
- @echo
- @echo $(MSG_EXTENDED_LISTING) $@
- $(OBJDUMP) -h -S $< > $@
-
-# Create a symbol table from ELF output file.
-%.sym: %.elf
- @echo
- @echo $(MSG_SYMBOL_TABLE) $@
- $(NM) -n $< > $@
-
-
-
-# Link: create ELF output file from object files.
-.SECONDARY : $(TARGET).elf
-.PRECIOUS : $(OBJ)
-%.elf: $(OBJ)
- @echo
- @echo $(MSG_LINKING) $@
- $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
-
-
-# Compile: create object files from C source files.
-%.o : %.c
- @echo
- @echo $(MSG_COMPILING) $<
- $(CC) -c $(ALL_CFLAGS) $< -o $@
-
-
-# Compile: create assembler files from C source files.
-%.s : %.c
- $(CC) -S $(ALL_CFLAGS) $< -o $@
-
-
-# Assemble: create object files from assembler source files.
-%.o : %.S
- @echo
- @echo $(MSG_ASSEMBLING) $<
- $(CC) -c $(ALL_ASFLAGS) $< -o $@
-
-
-
-# Target: clean project.
-clean: begin clean_list finished end
-
-clean_list :
- @echo
- @echo $(MSG_CLEANING)
- $(REMOVE) $(TARGET).hex
- $(REMOVE) $(TARGET).eep
- $(REMOVE) $(TARGET).obj
- $(REMOVE) $(TARGET).cof
- $(REMOVE) $(TARGET).elf
- $(REMOVE) $(TARGET).map
- $(REMOVE) $(TARGET).obj
- $(REMOVE) $(TARGET).a90
- $(REMOVE) $(TARGET).sym
- $(REMOVE) $(TARGET).lnk
- $(REMOVE) $(TARGET).lss
- $(REMOVE) $(OBJ)
- $(REMOVE) $(LST)
- $(REMOVE) $(SRC:.c=.s)
- $(REMOVE) $(SRC:.c=.d)
- $(REMOVE) dep/*
-
-
-
-# Include the dependency files.
--include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
-
-
-# Listing of phony targets.
-.PHONY : all begin finish end sizebefore sizeafter gccversion \
-build elf hex eep lss sym coff extcoff \
-clean clean_list program
-
-
-
diff --git a/build/windows/dist/jikes.exe b/build/windows/dist/jikes.exe
deleted file mode 100755
index ea1733c28..000000000
Binary files a/build/windows/dist/jikes.exe and /dev/null differ
diff --git a/build/windows/dist/lib/makefile.w2k b/build/windows/dist/lib/makefile.w2k
deleted file mode 100755
index 54c4f3c03..000000000
--- a/build/windows/dist/lib/makefile.w2k
+++ /dev/null
@@ -1,55 +0,0 @@
-# Arduino Makefile (for Windows 2000)
-# Nick Zambetti and David A. Mellis
-# $Id$
-
-# Windows 2000 seems to need backslashes in certain commands
-# (e.g. bin\rm in the compile rule below) where Windows XP
-# wants forward slashes. Hence this makefile.
-
-# By default, this makefile uses the serial device specified by
-# Wiring (either in the Tools | Serial Port menu or the Wiring
-# preferences file in the sketchbook directory) and passed as
-# an argument to make. To override this value, uncomment the
-# following line and change the value to the desired device.
-# SERIAL=com1
-
-# The Wiring Lite IDE runs the "compile" rule when you click the play button.
-compile:
- -bin\rm tmp/*
- bin\cat include/wiringlite.inc > tmp/prog.c
- bin\cat ../build/*.c >> tmp/prog.c
- bin\cp include/* tmp
- bin\cp ../../cyg*.dll tmp
- bin\gnumake -s -C tmp
-
-# The IDE runs the "program" rule when you hit the export button.
-# The string after the colon determines the method used to
-# program the microcontroller: program-using-bootloader,
-# program-with-isp, or program-over-parallel-port.
-program: program-using-bootloader-avrdude
-
-# This rule is for uploading code using a bootloader already on
-# the microcontroller. It should run at the baud rate specified
-# in the bootloader's code, currently 9600 baud.
-program-using-bootloader-avrdude:
- bin/avrdude -p atmega8 -P ${SERIAL} -c stk500@9600 -V -U flash:w:tmp/prog.hex
-
-# This rule is for uploading code using a bootloader already on
-# the microcontroller. It should run at the baud rate specified
-# in the bootloader's code, currently 9600 baud.
-program-using-bootloader:
- cp ../../cyg*.dll .
- bin/uisp -dprog=stk500 -dspeed=9600 -dserial=${SERIAL} -dpart=ATmega8 if=tmp/prog.hex --upload
-
-# This rule is for uploading code using an in-system programmer,
-# e.g. the one sold by Atmel. In this case, you want to erase the
-# microcontroller, upload the code, and then verify it.
-# Atmel's isp follows the stk500 protocol and works at 115200 baud.
-program-with-isp:
- cp ../../cyg*.dll .
- bin/uisp -dprog=stk500 -dspeed=115200 -dserial=${SERIAL} -dpart=ATmega8 if=tmp/prog.hex --erase --upload --verify
-
-# This rule is for uploading code using a parallel port programmer.
-program-over-parallel-port:
- cp ../../cyg*.dll .
- bin/uisp -dprog=dapa -dpart=ATmega8 if=tmp/prog.hex -dlpt=0x378 --erase --upload
diff --git a/build/windows/dist/lib/makefile.win b/build/windows/dist/lib/makefile.win
deleted file mode 100755
index 4e087efe6..000000000
--- a/build/windows/dist/lib/makefile.win
+++ /dev/null
@@ -1,54 +0,0 @@
-# Arduino Makefile (for Windows XP)
-# Nick Zambetti and David A. Mellis
-# $Id$
-
-# By default, this makefile uses the serial device specified by
-# Wiring (either in the Tools | Serial Port menu or the Wiring
-# preferences file in the sketchbook directory) and passed as
-# an argument to make. To override this value, uncomment the
-# following line and change the value to the desired device.
-# SERIAL=com1
-
-# The Wiring Lite IDE runs the "compile" rule when you click the play button.
-compile:
- -bin/rm tmp/*
- bin/cat include/wiringlite.inc > tmp/prog.c
- bin/cat ../build/*.c >> tmp/prog.c
- bin/cp include/* tmp
- bin/cp ../../cyg*.dll tmp
- bin/gnumake -s -C tmp
-
-# The IDE runs the "program" rule when you hit the export button.
-# The string after the colon determines the method used to
-# program the microcontroller: program-using-bootloader,
-# program-with-isp, or program-over-parallel-port.
-program: program-using-bootloader-avrdude
-
-# This rule is for uploading code using a bootloader already on
-# the microcontroller. It should run at the baud rate specified
-# in the bootloader's code, current 9600 baud.
-program-using-bootloader-avrdude:
- bin/avrdude -p atmega8 -P ${SERIAL} -c stk500@9600 -V -U flash:w:tmp/prog.hex
-
-# This rule is for uploading code using a bootloader already on
-# the microcontroller. It should run at the baud rate specified
-# in the bootloader's code, current 9600 baud. On Windows, use
-# program-using-bootloader-avrdude instead, as uisp seems to have
-# problems talking to the bootloader over the serial port (though
-# it appears to work fine with a Keyspan USB-to-serial adapter).
-program-using-bootloader:
- cp ../../cyg*.dll .
- bin/uisp -dprog=stk500 -dspeed=9600 -dserial=${SERIAL} -dpart=ATmega8 if=tmp/prog.hex --upload
-
-# This rule is for uploading code using an in-system programmer,
-# e.g. the one sold by Atmel. In this case, you want to erase the
-# microcontroller, upload the code, and then verify it.
-# Atmel's isp follows the stk500 protocol and works at 115200 baud.
-program-with-isp:
- cp ../../cyg*.dll .
- bin/uisp -dprog=stk500 -dspeed=115200 -dserial=${SERIAL} -dpart=ATmega8 if=tmp/prog.hex --erase --upload --verify
-
-# This rule is for uploading code using a parallel port programmer.
-program-over-parallel-port:
- cp ../../cyg*.dll .
- bin/uisp -dprog=dapa -dpart=ATmega8 if=tmp/prog.hex -dlpt=0x378 --erase --upload
diff --git a/build/windows/dist/run.bat b/build/windows/dist/run.bat
deleted file mode 100644
index c38482c05..000000000
--- a/build/windows/dist/run.bat
+++ /dev/null
@@ -1,34 +0,0 @@
-@echo off
-
-REM --- if you're running out of memory, change the 128m
-REM --- (which means 128 megabytes) to something higher.
-
-set SAVEDCP=%CLASSPATH%
-set SAVEDPATH=%PATH%
-set JAVA_HOME="java\bin"
-
-if %JAVA_HOME% == "" GOTO Error
-
-set CLASSPATH=java\lib\rt.jar;lib;lib\build;lib\pde.jar;lib\antlr.jar;lib\RXTXcomm.jar;lib\oro.jar;lib\registry.jar;lib\mrj.jar
-set PATH=java\bin;lib;%PATH%
-
-REM start javaw -ms128m -mx128m processing.app.Base
-%JAVA_HOME%\java processing.app.Base
-
-set CLASSPATH=%SAVEDCP%
-set PATH=%SAVEDPATH%
-
-GOTO End
-
-:Error
-echo *** Error: cannot execute Arduino
-echo *** Reason: lacking the directory where to find Java in your computer
-echo ***
-echo *** Fix: Edit run.bat and add the JAVA_HOME directory
-echo *** at the 'set JAVA_HOME=""' line
-echo ***
-echo *** then call the batch file run.bat in order to execute Arduino
-
-:End
-Pause
-echo Bye.
\ No newline at end of file
diff --git a/build/windows/jre.zip b/build/windows/jre.zip
index 01426c5c3..a9522ec68 100644
Binary files a/build/windows/jre.zip and b/build/windows/jre.zip differ
diff --git a/build/windows/launcher/.cvsignore b/build/windows/launcher/.cvsignore
deleted file mode 100644
index 42bdcceae..000000000
--- a/build/windows/launcher/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.o
-
-
diff --git a/build/windows/launcher/Makefile b/build/windows/launcher/Makefile
deleted file mode 100644
index cfd1b1683..000000000
--- a/build/windows/launcher/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-CXXFLAGS = -mwindows -mno-cygwin -O2 -Wall
-OBJS = launcher.o launcher-rc.o
-
-arduino.exe: $(OBJS)
- $(LINK.cc) $(CXXFLAGS) -o $@ $(OBJS)
- cp arduino.exe ../work/
-
-$(OBJS): Makefile
-
-launcher-rc.o: launcher.rc
- windres -i $< -o $@
-
-clean:
- $(RM) $(OBJS) arduino.exe
diff --git a/build/windows/launcher/Makefile.win b/build/windows/launcher/Makefile.win
deleted file mode 100644
index 09a0ac34c..000000000
--- a/build/windows/launcher/Makefile.win
+++ /dev/null
@@ -1,33 +0,0 @@
-# Project: launcher
-# Makefile created by Dev-C++ 4.9.9.2
-
-CPP = g++.exe
-CC = gcc.exe
-WINDRES = windres.exe
-RES = launcher_private.res
-OBJ = launcher.o $(RES)
-LINKOBJ = launcher.o $(RES)
-LIBS = -L"C:/Development/Dev-Cpp/lib"
-INCS = -I"C:/Development/Dev-Cpp/include"
-CXXINCS = -I"C:/Development/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Development/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Development/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Development/Dev-Cpp/include/c++/3.4.2" -I"C:/Development/Dev-Cpp/include"
-BIN = launcher.exe
-CXXFLAGS = $(CXXINCS)
-CFLAGS = $(INCS)
-RM = rm -f
-
-.PHONY: all all-before all-after clean clean-custom
-
-all: all-before launcher.exe all-after
-
-
-clean: clean-custom
- ${RM} $(OBJ) $(BIN)
-
-$(BIN): $(OBJ)
- $(CPP) $(LINKOBJ) -o "launcher.exe" $(LIBS)
-
-launcher.o: launcher.cpp
- $(CPP) -c launcher.cpp -o launcher.o $(CXXFLAGS)
-
-launcher_private.res: launcher_private.rc launcher.rc
- $(WINDRES) -i launcher_private.rc --input-format=rc -o launcher_private.res -O coff
diff --git a/build/windows/launcher/about.bmp b/build/windows/launcher/about.bmp
new file mode 100755
index 000000000..c8eceac06
Binary files /dev/null and b/build/windows/launcher/about.bmp differ
diff --git a/build/windows/launcher/application.ico b/build/windows/launcher/application.ico
index 982f54e69..3cc622730 100644
Binary files a/build/windows/launcher/application.ico and b/build/windows/launcher/application.ico differ
diff --git a/build/windows/launcher/arduino.exe b/build/windows/launcher/arduino.exe
deleted file mode 100644
index a3440b756..000000000
Binary files a/build/windows/launcher/arduino.exe and /dev/null differ
diff --git a/build/windows/launcher/config.xml b/build/windows/launcher/config.xml
new file mode 100755
index 000000000..877e390a1
--- /dev/null
+++ b/build/windows/launcher/config.xml
@@ -0,0 +1,45 @@
+
+ true
+ gui
+ lib
+ arduino.exe
+
+
+ .
+ normal
+ http://java.sun.com/javase/downloads/
+
+ false
+ false
+
+ application.ico
+
+ processing.app.Base
+ lib/pde.jar
+ lib/core.jar
+ lib/jna.jar
+ lib/ecj.jar
+ lib/oro.jar
+ lib/RXTXcomm.jar
+
+
+ java
+ 1.5.0
+
+ preferJre
+ -Xms128m -Xmx128m
+
+
+ about.bmp
+ true
+ 60
+ true
+
+
+ An error occurred while starting the application.
+ This application was configured to use a bundled Java Runtime Environment but the runtime is missing or corrupted.
+ This application requires at least Java Development Kit
+ The registry refers to a nonexistent Java Development Kit installation or the runtime is corrupted.
+ An application instance is already running.
+
+
diff --git a/build/windows/launcher/document.ico b/build/windows/launcher/document.ico
deleted file mode 100644
index 982f54e69..000000000
Binary files a/build/windows/launcher/document.ico and /dev/null differ
diff --git a/build/windows/launcher/launch4j/.classpath b/build/windows/launcher/launch4j/.classpath
new file mode 100755
index 000000000..734d175a6
--- /dev/null
+++ b/build/windows/launcher/launch4j/.classpath
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/windows/launcher/launch4j/.project b/build/windows/launcher/launch4j/.project
new file mode 100755
index 000000000..1c1309dfa
--- /dev/null
+++ b/build/windows/launcher/launch4j/.project
@@ -0,0 +1,17 @@
+
+
+ launch4j
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/build/windows/launcher/launch4j/.settings/org.eclipse.jdt.core.prefs b/build/windows/launcher/launch4j/.settings/org.eclipse.jdt.core.prefs
new file mode 100755
index 000000000..056498058
--- /dev/null
+++ b/build/windows/launcher/launch4j/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Sun Jul 20 14:10:30 CEST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+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.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.source=1.4
diff --git a/build/windows/launcher/launch4j/LICENSE.txt b/build/windows/launcher/launch4j/LICENSE.txt
new file mode 100755
index 000000000..82223322f
--- /dev/null
+++ b/build/windows/launcher/launch4j/LICENSE.txt
@@ -0,0 +1,30 @@
+Launch4j (http://launch4j.sourceforge.net/)
+Cross-platform Java application wrapper for creating Windows native executables.
+
+Copyright (c) 2004, 2008 Grzegorz Kowal
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/bin/COPYING b/build/windows/launcher/launch4j/bin/COPYING
new file mode 100755
index 000000000..60549be51
--- /dev/null
+++ b/build/windows/launcher/launch4j/bin/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C) 19yy
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/build/windows/launcher/launch4j/bin/ld.exe b/build/windows/launcher/launch4j/bin/ld.exe
new file mode 100755
index 000000000..f388b9513
Binary files /dev/null and b/build/windows/launcher/launch4j/bin/ld.exe differ
diff --git a/build/windows/launcher/launch4j/bin/windres.exe b/build/windows/launcher/launch4j/bin/windres.exe
new file mode 100755
index 000000000..4ad2ae98a
Binary files /dev/null and b/build/windows/launcher/launch4j/bin/windres.exe differ
diff --git a/build/windows/launcher/launch4j/build.xml b/build/windows/launcher/launch4j/build.xml
new file mode 100755
index 000000000..a7682ce0c
--- /dev/null
+++ b/build/windows/launcher/launch4j/build.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/ConsoleApp.exe b/build/windows/launcher/launch4j/demo/ConsoleApp/ConsoleApp.exe
new file mode 100755
index 000000000..d8a8f75d0
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/ConsoleApp/ConsoleApp.exe differ
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/ConsoleApp.jar b/build/windows/launcher/launch4j/demo/ConsoleApp/ConsoleApp.jar
new file mode 100755
index 000000000..6d4b126e6
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/ConsoleApp/ConsoleApp.jar differ
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/build.bat b/build/windows/launcher/launch4j/demo/ConsoleApp/build.bat
new file mode 100755
index 000000000..ed5f704e3
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/ConsoleApp/build.bat
@@ -0,0 +1,14 @@
+@echo off
+if "%ANT_HOME%"=="" goto noAntHome
+if "%JAVA_HOME%"=="" goto noJavaHome
+call "%ANT_HOME%\bin\ant.bat" exe
+goto end
+
+:noAntHome
+echo ANT_HOME environment variable is not set
+goto end
+
+:noJavaHome
+echo JAVA_HOME environment variable is not set
+
+:end
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/build.xml b/build/windows/launcher/launch4j/demo/ConsoleApp/build.xml
new file mode 100755
index 000000000..5f3473da6
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/ConsoleApp/build.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/l4j/ConsoleApp.ico b/build/windows/launcher/launch4j/demo/ConsoleApp/l4j/ConsoleApp.ico
new file mode 100755
index 000000000..cc4c540e2
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/ConsoleApp/l4j/ConsoleApp.ico differ
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/lib/readme.txt b/build/windows/launcher/launch4j/demo/ConsoleApp/lib/readme.txt
new file mode 100755
index 000000000..ef44ded3a
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/ConsoleApp/lib/readme.txt
@@ -0,0 +1,8 @@
+Put your jar libs here and the build script will include them
+in the classpath stored inside the jar manifest.
+In order to run your application move the output exe file from
+the dist directory to the same level as lib.
+
+SimpleApp.exe
+lib/
+lib/xml.jar
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/readme.txt b/build/windows/launcher/launch4j/demo/ConsoleApp/readme.txt
new file mode 100755
index 000000000..fa38dc8bd
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/ConsoleApp/readme.txt
@@ -0,0 +1 @@
+To build the example application set JAVA_HOME and ANT_HOME environment variables.
diff --git a/build/windows/launcher/launch4j/demo/ConsoleApp/src/net/sf/launch4j/example/ConsoleApp.java b/build/windows/launcher/launch4j/demo/ConsoleApp/src/net/sf/launch4j/example/ConsoleApp.java
new file mode 100755
index 000000000..eb1398c2c
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/ConsoleApp/src/net/sf/launch4j/example/ConsoleApp.java
@@ -0,0 +1,72 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.example;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class ConsoleApp {
+ public static void main(String[] args) {
+ StringBuffer sb = new StringBuffer("Hello World!\n\nJava version: ");
+ sb.append(System.getProperty("java.version"));
+ sb.append("\nJava home: ");
+ sb.append(System.getProperty("java.home"));
+ sb.append("\nCurrent dir: ");
+ sb.append(System.getProperty("user.dir"));
+ if (args.length > 0) {
+ sb.append("\nArgs: ");
+ for (int i = 0; i < args.length; i++) {
+ sb.append(args[i]);
+ sb.append(' ');
+ }
+ }
+ sb.append("\n\nEnter a line of text, Ctrl-C to stop.\n\n>");
+ System.out.print(sb.toString());
+ try {
+ BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
+ String line;
+ while ((line = is.readLine()) != null && !line.equalsIgnoreCase("quit")) {
+ System.out.print("You wrote: " + line + "\n\n>");
+ }
+ is.close();
+ System.exit(123);
+ } catch (IOException e) {
+ System.err.print(e);
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/demo/LICENSE.txt b/build/windows/launcher/launch4j/demo/LICENSE.txt
new file mode 100755
index 000000000..d6d6bb5ea
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/LICENSE.txt
@@ -0,0 +1,30 @@
+Launch4j (http://launch4j.sourceforge.net/)
+Cross-platform Java application wrapper for creating Windows native executables.
+
+Copyright (c) 2004, 2007 Grzegorz Kowal
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/SimpleApp.exe b/build/windows/launcher/launch4j/demo/SimpleApp/SimpleApp.exe
new file mode 100755
index 000000000..1a75fc298
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/SimpleApp/SimpleApp.exe differ
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/SimpleApp.jar b/build/windows/launcher/launch4j/demo/SimpleApp/SimpleApp.jar
new file mode 100755
index 000000000..f02c6133b
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/SimpleApp/SimpleApp.jar differ
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/build.bat b/build/windows/launcher/launch4j/demo/SimpleApp/build.bat
new file mode 100755
index 000000000..ed5f704e3
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/SimpleApp/build.bat
@@ -0,0 +1,14 @@
+@echo off
+if "%ANT_HOME%"=="" goto noAntHome
+if "%JAVA_HOME%"=="" goto noJavaHome
+call "%ANT_HOME%\bin\ant.bat" exe
+goto end
+
+:noAntHome
+echo ANT_HOME environment variable is not set
+goto end
+
+:noJavaHome
+echo JAVA_HOME environment variable is not set
+
+:end
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/build.xml b/build/windows/launcher/launch4j/demo/SimpleApp/build.xml
new file mode 100755
index 000000000..82f4b4998
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/SimpleApp/build.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/l4j/SimpleApp.ico b/build/windows/launcher/launch4j/demo/SimpleApp/l4j/SimpleApp.ico
new file mode 100755
index 000000000..cc4c540e2
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/SimpleApp/l4j/SimpleApp.ico differ
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/l4j/SimpleApp.xml b/build/windows/launcher/launch4j/demo/SimpleApp/l4j/SimpleApp.xml
new file mode 100755
index 000000000..9a7dc940a
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/SimpleApp/l4j/SimpleApp.xml
@@ -0,0 +1,18 @@
+
+ gui
+ ../SimpleApp.jar
+ ../SimpleApp.exe
+ SimpleApp
+ .
+ true
+ SimpleApp.ico
+
+ 1.4.0
+
+
+ splash.bmp
+ true
+ 60
+ true
+
+
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/l4j/splash.bmp b/build/windows/launcher/launch4j/demo/SimpleApp/l4j/splash.bmp
new file mode 100755
index 000000000..88d7bbf10
Binary files /dev/null and b/build/windows/launcher/launch4j/demo/SimpleApp/l4j/splash.bmp differ
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/lib/readme.txt b/build/windows/launcher/launch4j/demo/SimpleApp/lib/readme.txt
new file mode 100755
index 000000000..ef44ded3a
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/SimpleApp/lib/readme.txt
@@ -0,0 +1,8 @@
+Put your jar libs here and the build script will include them
+in the classpath stored inside the jar manifest.
+In order to run your application move the output exe file from
+the dist directory to the same level as lib.
+
+SimpleApp.exe
+lib/
+lib/xml.jar
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/readme.txt b/build/windows/launcher/launch4j/demo/SimpleApp/readme.txt
new file mode 100755
index 000000000..fa38dc8bd
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/SimpleApp/readme.txt
@@ -0,0 +1 @@
+To build the example application set JAVA_HOME and ANT_HOME environment variables.
diff --git a/build/windows/launcher/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java b/build/windows/launcher/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java
new file mode 100755
index 000000000..8e87c5953
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java
@@ -0,0 +1,104 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.example;
+
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.UIManager;
+
+public class SimpleApp extends JFrame {
+ public SimpleApp(String[] args) {
+ super("Java Application");
+ final int inset = 100;
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ setBounds (inset, inset,
+ screenSize.width - inset * 2, screenSize.height - inset * 2);
+
+ JMenu menu = new JMenu("File");
+ menu.add(new JMenuItem("Open"));
+ menu.add(new JMenuItem("Save"));
+ JMenuBar mb = new JMenuBar();
+ mb.setOpaque(true);
+ mb.add(menu);
+ setJMenuBar(mb);
+
+ this.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ System.exit(123);
+ }});
+ setVisible(true);
+
+ StringBuffer sb = new StringBuffer("Java version: ");
+ sb.append(System.getProperty("java.version"));
+ sb.append("\nJava home: ");
+ sb.append(System.getProperty("java.home"));
+ sb.append("\nCurrent dir: ");
+ sb.append(System.getProperty("user.dir"));
+ if (args.length > 0) {
+ sb.append("\nArgs: ");
+ for (int i = 0; i < args.length; i++) {
+ sb.append(args[i]);
+ sb.append(' ');
+ }
+ }
+ JOptionPane.showMessageDialog(this,
+ sb.toString(),
+ "Info",
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ public static void setLAF() {
+ JFrame.setDefaultLookAndFeelDecorated(true);
+ Toolkit.getDefaultToolkit().setDynamicLayout(true);
+ System.setProperty("sun.awt.noerasebackground","true");
+ try {
+ UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
+ } catch (Exception e) {
+ System.err.println("Failed to set LookAndFeel");
+ }
+ }
+
+ public static void main(String[] args) {
+ setLAF();
+ new SimpleApp(args);
+ }
+}
diff --git a/build/windows/launcher/launch4j/demo/readme.txt b/build/windows/launcher/launch4j/demo/readme.txt
new file mode 100755
index 000000000..f59178214
--- /dev/null
+++ b/build/windows/launcher/launch4j/demo/readme.txt
@@ -0,0 +1,3 @@
+JRE/SDK 1.4.0 or higher must be installed on your system to run this demo.
+
+try running it with some command line arguments...
diff --git a/build/windows/launcher/launch4j/head/LICENSE.txt b/build/windows/launcher/launch4j/head/LICENSE.txt
new file mode 100755
index 000000000..536488e61
--- /dev/null
+++ b/build/windows/launcher/launch4j/head/LICENSE.txt
@@ -0,0 +1,23 @@
+Copyright (c) 2004, 2007 Grzegorz Kowal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/head_src/LICENSE.txt b/build/windows/launcher/launch4j/head_src/LICENSE.txt
new file mode 100755
index 000000000..2805f412a
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/LICENSE.txt
@@ -0,0 +1,23 @@
+Copyright (c) 2004, 2008 Grzegorz Kowal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/build/windows/launcher/launch4j/head_src/consolehead/Makefile.win b/build/windows/launcher/launch4j/head_src/consolehead/Makefile.win
new file mode 100755
index 000000000..349e4c00f
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/consolehead/Makefile.win
@@ -0,0 +1,33 @@
+# Project: consolehead
+# Makefile created by Dev-C++ 4.9.9.2
+
+CPP = g++.exe
+CC = gcc.exe
+WINDRES = windres.exe
+RES =
+OBJ = ../../head/consolehead.o ../../head/head.o $(RES)
+LINKOBJ = ../../head/consolehead.o ../../head/head.o $(RES)
+LIBS = -L"C:/Dev-Cpp/lib" -n -s
+INCS = -I"C:/Dev-Cpp/include"
+CXXINCS = -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"
+BIN = consolehead.exe
+CXXFLAGS = $(CXXINCS) -fexpensive-optimizations -O3
+CFLAGS = $(INCS) -fexpensive-optimizations -O3
+RM = rm -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before consolehead.exe all-after
+
+
+clean: clean-custom
+ ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+# $(CC) $(LINKOBJ) -o "consolehead.exe" $(LIBS)
+
+../../head/consolehead.o: consolehead.c
+ $(CC) -c consolehead.c -o ../../head/consolehead.o $(CFLAGS)
+
+../../head/head.o: ../head.c
+ $(CC) -c ../head.c -o ../../head/head.o $(CFLAGS)
diff --git a/build/windows/launcher/launch4j/head_src/consolehead/consolehead.c b/build/windows/launcher/launch4j/head_src/consolehead/consolehead.c
new file mode 100755
index 000000000..755a7673c
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/consolehead/consolehead.c
@@ -0,0 +1,65 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ Except as contained in this notice, the name(s) of the above copyright holders
+ shall not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "../resource.h"
+#include "../head.h"
+
+int main(int argc, char* argv[])
+{
+ setConsoleFlag();
+ LPTSTR cmdLine = GetCommandLine();
+ if (*cmdLine == '"') {
+ if (*(cmdLine = strchr(cmdLine + 1, '"') + 1)) {
+ cmdLine++;
+ }
+ } else if ((cmdLine = strchr(cmdLine, ' ')) != NULL) {
+ cmdLine++;
+ } else {
+ cmdLine = "";
+ }
+ int result = prepare(cmdLine);
+ if (result == ERROR_ALREADY_EXISTS) {
+ char errMsg[BIG_STR] = {0};
+ loadString(INSTANCE_ALREADY_EXISTS_MSG, errMsg);
+ msgBox(errMsg);
+ closeLogFile();
+ return 2;
+ }
+ if (result != TRUE) {
+ signalError();
+ return 1;
+ }
+
+ result = (int) execute(TRUE);
+ if (result == -1) {
+ signalError();
+ } else {
+ return result;
+ }
+}
diff --git a/build/windows/launcher/launch4j/head_src/consolehead/consolehead.dev b/build/windows/launcher/launch4j/head_src/consolehead/consolehead.dev
new file mode 100755
index 000000000..a309ec94f
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/consolehead/consolehead.dev
@@ -0,0 +1,108 @@
+[Project]
+FileName=consolehead.dev
+Name=consolehead
+UnitCount=4
+Type=1
+Ver=1
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=-n_@@_
+IsCpp=0
+Icon=
+ExeOutput=
+ObjectOutput=..\..\head
+OverrideOutput=0
+OverrideOutputName=consolehead.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=Makefile.win
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000001001000000100
+
+[Unit1]
+FileName=consolehead.c
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit2]
+FileName=..\resource.h
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\head.c
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=..\head.h
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=..\head.rc
+Folder=consolehead
+Compile=1
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=..\resid.h
+CompileCpp=0
+Folder=consolehead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/build/windows/launcher/launch4j/head_src/guihead/Makefile.win b/build/windows/launcher/launch4j/head_src/guihead/Makefile.win
new file mode 100755
index 000000000..3c642f8fc
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/guihead/Makefile.win
@@ -0,0 +1,38 @@
+# Project: guihead
+# Makefile created by Dev-C++ 4.9.9.2
+
+CPP = g++.exe
+CC = gcc.exe
+WINDRES = windres.exe
+RES =
+OBJ = ../../head/guihead.o ../../head/head.o $(RES)
+LINKOBJ = ../../head/guihead.o ../../head/head.o $(RES)
+
+# removed dev-cpp flags, replacing for cygwin/mingw [fry]
+CXXFLAGS = -mwindows -mno-cygwin -O2 -Wall
+CFLAGS = -mwindows -mno-cygwin -O2 -Wall
+#CFLAGS = -I/cygdrive/c/cygwin/usr/include/mingw
+#LIBS = -L"C:/Dev-Cpp/lib" -mwindows -n -s
+#INCS = -I"C:/Dev-Cpp/include"
+#CXXINCS = -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"
+BIN = guihead.exe
+#CXXFLAGS = $(CXXINCS) -fexpensive-optimizations -O3
+#CFLAGS = $(INCS) -fexpensive-optimizations -O3
+RM = rm -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before guihead.exe all-after
+
+
+clean: clean-custom
+ ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+# $(CC) $(LINKOBJ) -o "guihead.exe" $(LIBS)
+
+../../head/guihead.o: guihead.c
+ $(CC) -c guihead.c -o ../../head/guihead.o $(CFLAGS)
+
+../../head/head.o: ../head.c
+ $(CC) -c ../head.c -o ../../head/head.o $(CFLAGS)
diff --git a/build/windows/launcher/launch4j/head_src/guihead/guihead.c b/build/windows/launcher/launch4j/head_src/guihead/guihead.c
new file mode 100755
index 000000000..508a5bdac
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/guihead/guihead.c
@@ -0,0 +1,185 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+ Sylvain Mina (single instance patch)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ Except as contained in this notice, the name(s) of the above copyright holders
+ shall not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "../resource.h"
+#include "../head.h"
+#include "guihead.h"
+
+extern FILE* hLog;
+extern PROCESS_INFORMATION pi;
+
+HWND hWnd;
+DWORD dwExitCode = 0;
+BOOL stayAlive = FALSE;
+BOOL splash = FALSE;
+BOOL splashTimeoutErr;
+BOOL waitForWindow;
+int splashTimeout = DEFAULT_SPLASH_TIMEOUT;
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow) {
+ int result = prepare(lpCmdLine);
+ if (result == ERROR_ALREADY_EXISTS) {
+ HWND handle = getInstanceWindow();
+ ShowWindow(handle, SW_SHOW);
+ SetForegroundWindow(handle);
+ closeLogFile();
+ return 2;
+ }
+ if (result != TRUE) {
+ signalError();
+ return 1;
+ }
+
+ splash = loadBool(SHOW_SPLASH)
+ && strstr(lpCmdLine, "--l4j-no-splash") == NULL;
+ stayAlive = loadBool(GUI_HEADER_STAYS_ALIVE)
+ && strstr(lpCmdLine, "--l4j-dont-wait") == NULL;
+ if (splash || stayAlive) {
+ hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, "STATIC", "",
+ WS_POPUP | SS_BITMAP,
+ 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
+ if (splash) {
+ char timeout[10] = {0};
+ if (loadString(SPLASH_TIMEOUT, timeout)) {
+ splashTimeout = atoi(timeout);
+ if (splashTimeout <= 0 || splashTimeout > MAX_SPLASH_TIMEOUT) {
+ splashTimeout = DEFAULT_SPLASH_TIMEOUT;
+ }
+ }
+ splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR)
+ && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL;
+ waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW);
+ HANDLE hImage = LoadImage(hInstance, // handle of the instance containing the image
+ MAKEINTRESOURCE(SPLASH_BITMAP), // name or identifier of image
+ IMAGE_BITMAP, // type of image
+ 0, // desired width
+ 0, // desired height
+ LR_DEFAULTSIZE);
+ if (hImage == NULL) {
+ signalError();
+ return 1;
+ }
+ SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImage);
+ RECT rect;
+ GetWindowRect(hWnd, &rect);
+ int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
+ int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
+ SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
+ ShowWindow(hWnd, nCmdShow);
+ UpdateWindow (hWnd);
+ }
+ if (!SetTimer (hWnd, ID_TIMER, 1000 /* 1s */, TimerProc)) {
+ signalError();
+ return 1;
+ }
+ }
+ if (execute(FALSE) == -1) {
+ signalError();
+ return 1;
+ }
+ if (!(splash || stayAlive)) {
+ debug("Exit code:\t0\n");
+ closeHandles();
+ return 0;
+ }
+
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ debug("Exit code:\t%d\n", dwExitCode);
+ closeHandles();
+ return dwExitCode;
+}
+
+HWND getInstanceWindow() {
+ char windowTitle[STR];
+ char instWindowTitle[STR] = {0};
+ if (loadString(INSTANCE_WINDOW_TITLE, instWindowTitle)) {
+ HWND handle = FindWindowEx(NULL, NULL, NULL, NULL);
+ while (handle != NULL) {
+ GetWindowText(handle, windowTitle, STR - 1);
+ if (strstr(windowTitle, instWindowTitle) != NULL) {
+ return handle;
+ } else {
+ handle = FindWindowEx(NULL, handle, NULL, NULL);
+ }
+ }
+ }
+ return NULL;
+}
+
+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam) {
+ DWORD processId;
+ GetWindowThreadProcessId(hwnd, &processId);
+ if (pi.dwProcessId == processId) {
+ LONG styles = GetWindowLong(hwnd, GWL_STYLE);
+ if ((styles & WS_VISIBLE) != 0) {
+ splash = FALSE;
+ ShowWindow(hWnd, SW_HIDE);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+VOID CALLBACK TimerProc(
+ HWND hwnd, // handle of window for timer messages
+ UINT uMsg, // WM_TIMER message
+ UINT idEvent, // timer identifier
+ DWORD dwTime) { // current system time
+
+ if (splash) {
+ if (splashTimeout == 0) {
+ splash = FALSE;
+ ShowWindow(hWnd, SW_HIDE);
+ if (waitForWindow && splashTimeoutErr) {
+ KillTimer(hwnd, ID_TIMER);
+ signalError();
+ PostQuitMessage(0);
+ }
+ } else {
+ splashTimeout--;
+ if (waitForWindow) {
+ EnumWindows(enumwndfn, 0);
+ }
+ }
+ }
+ GetExitCodeProcess(pi.hProcess, &dwExitCode);
+ if (dwExitCode != STILL_ACTIVE
+ || !(splash || stayAlive)) {
+ KillTimer(hWnd, ID_TIMER);
+ PostQuitMessage(0);
+ }
+}
diff --git a/build/windows/launcher/launch4j/head_src/guihead/guihead.dev b/build/windows/launcher/launch4j/head_src/guihead/guihead.dev
new file mode 100755
index 000000000..7c30088f1
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/guihead/guihead.dev
@@ -0,0 +1,109 @@
+[Project]
+FileName=guihead.dev
+Name=guihead
+UnitCount=5
+Type=0
+Ver=1
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=-n_@@_
+IsCpp=0
+Icon=
+ExeOutput=
+ObjectOutput=..\..\head
+OverrideOutput=0
+OverrideOutputName=guihead.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=1
+CustomMakefile=Makefile.win
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000001001000000100
+
+[Unit1]
+FileName=guihead.c
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=$(CC) -c guihead.c -o ../../head/guihead.o $(CFLAGS)
+
+[Unit2]
+FileName=guihead.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit4]
+FileName=..\head.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=..\resid.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\head.c
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=..\resource.h
+CompileCpp=0
+Folder=guihead
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/build/windows/launcher/launch4j/head_src/guihead/guihead.h b/build/windows/launcher/launch4j/head_src/guihead/guihead.h
new file mode 100755
index 000000000..2fc71e31f
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/guihead/guihead.h
@@ -0,0 +1,43 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ Except as contained in this notice, the name(s) of the above copyright holders
+ shall not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#define ID_TIMER 1
+#define DEFAULT_SPLASH_TIMEOUT 60 /* 60 seconds */
+#define MAX_SPLASH_TIMEOUT 60 * 15 /* 15 minutes */
+
+HWND getInstanceWindow();
+
+BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam);
+
+VOID CALLBACK TimerProc(
+ HWND hwnd, // handle of window for timer messages
+ UINT uMsg, // WM_TIMER message
+ UINT idEvent, // timer identifier
+ DWORD dwTime // current system time
+);
diff --git a/build/windows/launcher/launch4j/head_src/head.c b/build/windows/launcher/launch4j/head_src/head.c
new file mode 100755
index 000000000..1ff937694
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/head.c
@@ -0,0 +1,818 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2008 Grzegorz Kowal,
+ Ian Roberts (jdk preference patch)
+ Sylvain Mina (single instance patch)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ Except as contained in this notice, the name(s) of the above copyright holders
+ shall not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "resource.h"
+#include "head.h"
+
+HMODULE hModule;
+FILE* hLog;
+BOOL console = FALSE;
+BOOL wow64 = FALSE;
+int foundJava = NO_JAVA_FOUND;
+
+struct _stat statBuf;
+PROCESS_INFORMATION pi;
+DWORD priority;
+
+char mutexName[STR] = {0};
+
+char errUrl[256] = {0};
+char errTitle[STR] = "Launch4j";
+char errMsg[BIG_STR] = {0};
+
+char javaMinVer[STR] = {0};
+char javaMaxVer[STR] = {0};
+char foundJavaVer[STR] = {0};
+char foundJavaKey[_MAX_PATH] = {0};
+
+char oldPwd[_MAX_PATH] = {0};
+char workingDir[_MAX_PATH] = {0};
+char cmd[_MAX_PATH] = {0};
+char args[MAX_ARGS] = {0};
+
+FILE* openLogFile(const char* exePath, const int pathLen) {
+ char path[_MAX_PATH] = {0};
+ strncpy(path, exePath, pathLen);
+ strcat(path, "\\launch4j.log");
+ return fopen(path, "a");
+}
+
+void closeLogFile() {
+ if (hLog != NULL) {
+ fclose(hLog);
+ }
+}
+
+void setWow64Flag() {
+ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
+ GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+ if (fnIsWow64Process != NULL) {
+ fnIsWow64Process(GetCurrentProcess(), &wow64);
+ }
+ debug("WOW64:\t\t%s\n", wow64 ? "yes" : "no");
+}
+
+void setConsoleFlag() {
+ console = TRUE;
+}
+
+void msgBox(const char* text) {
+ if (console) {
+ printf("%s: %s\n", errTitle, text);
+ } else {
+ MessageBox(NULL, text, errTitle, MB_OK);
+ }
+}
+
+void signalError() {
+ DWORD err = GetLastError();
+ if (err) {
+ LPVOID lpMsgBuf;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL);
+ debug("Error:\t\t%s\n", (LPCTSTR) lpMsgBuf);
+ strcat(errMsg, "\n\n");
+ strcat(errMsg, (LPCTSTR) lpMsgBuf);
+ msgBox(errMsg);
+ LocalFree(lpMsgBuf);
+ } else {
+ msgBox(errMsg);
+ }
+ if (*errUrl) {
+ debug("Open URL:\t%s\n", errUrl);
+ ShellExecute(NULL, "open", errUrl, NULL, NULL, SW_SHOWNORMAL);
+ }
+ closeLogFile();
+}
+
+BOOL loadString(const int resID, char* buffer) {
+ HRSRC hResource;
+ HGLOBAL hResourceLoaded;
+ LPBYTE lpBuffer;
+
+ hResource = FindResourceEx(hModule, RT_RCDATA, MAKEINTRESOURCE(resID),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
+ if (NULL != hResource) {
+ hResourceLoaded = LoadResource(hModule, hResource);
+ if (NULL != hResourceLoaded) {
+ lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
+ if (NULL != lpBuffer) {
+ int x = 0;
+ do {
+ buffer[x] = (char) lpBuffer[x];
+ } while (buffer[x++] != 0);
+ // debug("Resource %d:\t%s\n", resID, buffer);
+ return TRUE;
+ }
+ }
+ } else {
+ SetLastError(0);
+ }
+ return FALSE;
+}
+
+BOOL loadBool(const int resID) {
+ char boolStr[20] = {0};
+ loadString(resID, boolStr);
+ return strcmp(boolStr, TRUE_STR) == 0;
+}
+
+int loadInt(const int resID) {
+ char intStr[20] = {0};
+ loadString(resID, intStr);
+ return atoi(intStr);
+}
+
+BOOL regQueryValue(const char* regPath, unsigned char* buffer,
+ unsigned long bufferLength) {
+ HKEY hRootKey;
+ char* key;
+ char* value;
+ if (strstr(regPath, HKEY_CLASSES_ROOT_STR) == regPath) {
+ hRootKey = HKEY_CLASSES_ROOT;
+ } else if (strstr(regPath, HKEY_CURRENT_USER_STR) == regPath) {
+ hRootKey = HKEY_CURRENT_USER;
+ } else if (strstr(regPath, HKEY_LOCAL_MACHINE_STR) == regPath) {
+ hRootKey = HKEY_LOCAL_MACHINE;
+ } else if (strstr(regPath, HKEY_USERS_STR) == regPath) {
+ hRootKey = HKEY_USERS;
+ } else if (strstr(regPath, HKEY_CURRENT_CONFIG_STR) == regPath) {
+ hRootKey = HKEY_CURRENT_CONFIG;
+ } else {
+ return FALSE;
+ }
+ key = strchr(regPath, '\\') + 1;
+ value = strrchr(regPath, '\\') + 1;
+ *(value - 1) = 0;
+
+ HKEY hKey;
+ unsigned long datatype;
+ BOOL result = FALSE;
+ if ((wow64 && RegOpenKeyEx(hRootKey,
+ key,
+ 0,
+ KEY_READ | KEY_WOW64_64KEY,
+ &hKey) == ERROR_SUCCESS)
+ || RegOpenKeyEx(hRootKey,
+ key,
+ 0,
+ KEY_READ,
+ &hKey) == ERROR_SUCCESS) {
+ result = RegQueryValueEx(hKey, value, NULL, &datatype, buffer, &bufferLength)
+ == ERROR_SUCCESS;
+ RegCloseKey(hKey);
+ }
+ *(value - 1) = '\\';
+ return result;
+}
+
+void regSearch(const HKEY hKey, const char* keyName, const int searchType) {
+ DWORD x = 0;
+ unsigned long size = BIG_STR;
+ FILETIME time;
+ char buffer[BIG_STR] = {0};
+ while (RegEnumKeyEx(
+ hKey, // handle to key to enumerate
+ x++, // index of subkey to enumerate
+ buffer, // address of buffer for subkey name
+ &size, // address for size of subkey buffer
+ NULL, // reserved
+ NULL, // address of buffer for class string
+ NULL, // address for size of class buffer
+ &time) == ERROR_SUCCESS) {
+
+ if (strcmp(buffer, javaMinVer) >= 0
+ && (!*javaMaxVer || strcmp(buffer, javaMaxVer) <= 0)
+ && strcmp(buffer, foundJavaVer) > 0) {
+ strcpy(foundJavaVer, buffer);
+ strcpy(foundJavaKey, keyName);
+ appendPath(foundJavaKey, buffer);
+ foundJava = searchType;
+ debug("Match:\t\t%s\\%s\n", keyName, buffer);
+ } else {
+ debug("Ignore:\t\t%s\\%s\n", keyName, buffer);
+ }
+ size = BIG_STR;
+ }
+}
+
+void regSearchWow(const char* keyName, const int searchType) {
+ HKEY hKey;
+ debug("64-bit search:\t%s...\n", keyName);
+ if (wow64 && RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ keyName,
+ 0,
+ KEY_READ | KEY_WOW64_64KEY,
+ &hKey) == ERROR_SUCCESS) {
+
+ regSearch(hKey, keyName, searchType | KEY_WOW64_64KEY);
+ RegCloseKey(hKey);
+ if ((foundJava & KEY_WOW64_64KEY) != NO_JAVA_FOUND)
+ {
+ debug("Using 64-bit runtime.\n");
+ return;
+ }
+ }
+ debug("32-bit search:\t%s...\n", keyName);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ keyName,
+ 0,
+ KEY_READ,
+ &hKey) == ERROR_SUCCESS) {
+ regSearch(hKey, keyName, searchType);
+ RegCloseKey(hKey);
+ }
+}
+
+void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
+ const int jdkPreference) {
+ if (jdkPreference == JDK_ONLY || jdkPreference == PREFER_JDK) {
+ regSearchWow(sdkKeyName, FOUND_SDK);
+ if (jdkPreference != JDK_ONLY) {
+ regSearchWow(jreKeyName, FOUND_JRE);
+ }
+ } else { // jdkPreference == JRE_ONLY or PREFER_JRE
+ regSearchWow(jreKeyName, FOUND_JRE);
+ if (jdkPreference != JRE_ONLY) {
+ regSearchWow(sdkKeyName, FOUND_SDK);
+ }
+ }
+}
+
+BOOL findJavaHome(char* path, const int jdkPreference) {
+ regSearchJreSdk("SOFTWARE\\JavaSoft\\Java Runtime Environment",
+ "SOFTWARE\\JavaSoft\\Java Development Kit",
+ jdkPreference);
+ if (foundJava == NO_JAVA_FOUND) {
+ regSearchJreSdk("SOFTWARE\\IBM\\Java2 Runtime Environment",
+ "SOFTWARE\\IBM\\Java Development Kit",
+ jdkPreference);
+ }
+ if (foundJava != NO_JAVA_FOUND) {
+ HKEY hKey;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ foundJavaKey,
+ 0,
+ KEY_READ | (foundJava & KEY_WOW64_64KEY),
+ &hKey) == ERROR_SUCCESS) {
+ unsigned char buffer[BIG_STR] = {0};
+ unsigned long bufferlength = BIG_STR;
+ unsigned long datatype;
+ if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer,
+ &bufferlength) == ERROR_SUCCESS) {
+ int i = 0;
+ do {
+ path[i] = buffer[i];
+ } while (path[i++] != 0);
+ // (foundJava & FOUND_SDK) { // removed by fry
+ // appendPath(path, "jre");
+ //
+ RegCloseKey(hKey);
+ return TRUE;
+ }
+ RegCloseKey(hKey);
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Extract the executable name, returns path length.
+ */
+int getExePath(char* exePath) {
+ if (GetModuleFileName(hModule, exePath, _MAX_PATH) == 0) {
+ return -1;
+ }
+ return strrchr(exePath, '\\') - exePath;
+}
+
+void appendPath(char* basepath, const char* path) {
+ if (basepath[strlen(basepath) - 1] != '\\') {
+ strcat(basepath, "\\");
+ }
+ strcat(basepath, path);
+}
+
+void appendJavaw(char* jrePath) {
+ if (console) {
+ appendPath(jrePath, "bin\\java.exe");
+ } else {
+ appendPath(jrePath, "bin\\javaw.exe");
+ }
+}
+
+void appendLauncher(const BOOL setProcName, char* exePath,
+ const int pathLen, char* cmd) {
+ if (setProcName) {
+ char tmpspec[_MAX_PATH];
+ char tmpfile[_MAX_PATH];
+ strcpy(tmpspec, cmd);
+ strcat(tmpspec, LAUNCH4J_TMP_DIR);
+ tmpspec[strlen(tmpspec) - 1] = 0;
+ if (_stat(tmpspec, &statBuf) == 0) {
+ // Remove temp launchers and manifests
+ struct _finddata_t c_file;
+ long hFile;
+ appendPath(tmpspec, "*.exe");
+ strcpy(tmpfile, cmd);
+ strcat(tmpfile, LAUNCH4J_TMP_DIR);
+ char* filename = tmpfile + strlen(tmpfile);
+ if ((hFile = _findfirst(tmpspec, &c_file)) != -1L) {
+ do {
+ strcpy(filename, c_file.name);
+ debug("Unlink:\t\t%s\n", tmpfile);
+ _unlink(tmpfile);
+ strcat(tmpfile, MANIFEST);
+ debug("Unlink:\t\t%s\n", tmpfile);
+ _unlink(tmpfile);
+ } while (_findnext(hFile, &c_file) == 0);
+ }
+ _findclose(hFile);
+ } else {
+ if (_mkdir(tmpspec) != 0) {
+ debug("Mkdir failed:\t%s\n", tmpspec);
+ appendJavaw(cmd);
+ return;
+ }
+ }
+ char javaw[_MAX_PATH];
+ strcpy(javaw, cmd);
+ appendJavaw(javaw);
+ strcpy(tmpfile, cmd);
+ strcat(tmpfile, LAUNCH4J_TMP_DIR);
+ char* tmpfilename = tmpfile + strlen(tmpfile);
+ char* exeFilePart = exePath + pathLen + 1;
+
+ // Copy manifest
+ char manifest[_MAX_PATH] = {0};
+ strcpy(manifest, exePath);
+ strcat(manifest, MANIFEST);
+ if (_stat(manifest, &statBuf) == 0) {
+ strcat(tmpfile, exeFilePart);
+ strcat(tmpfile, MANIFEST);
+ debug("Copy:\t\t%s -> %s\n", manifest, tmpfile);
+ CopyFile(manifest, tmpfile, FALSE);
+ }
+
+ // Copy launcher
+ strcpy(tmpfilename, exeFilePart);
+ debug("Copy:\t\t%s -> %s\n", javaw, tmpfile);
+ if (CopyFile(javaw, tmpfile, FALSE)) {
+ strcpy(cmd, tmpfile);
+ return;
+ } else if (_stat(javaw, &statBuf) == 0) {
+ long fs = statBuf.st_size;
+ if (_stat(tmpfile, &statBuf) == 0 && fs == statBuf.st_size) {
+ debug("Reusing:\t\t%s\n", tmpfile);
+ strcpy(cmd, tmpfile);
+ return;
+ }
+ }
+ }
+ appendJavaw(cmd);
+}
+
+void appendAppClasspath(char* dst, const char* src, const char* classpath) {
+ strcat(dst, src);
+ if (*classpath) {
+ strcat(dst, ";");
+ }
+}
+
+BOOL isJrePathOk(const char* path) {
+ char javaw[_MAX_PATH];
+ BOOL result = FALSE;
+ if (*path) {
+ strcpy(javaw, path);
+ appendJavaw(javaw);
+ result = _stat(javaw, &statBuf) == 0;
+ }
+ debug("Check launcher:\t%s %s\n", javaw, result ? "(OK)" : "(n/a)");
+ return result;
+}
+
+/*
+ * Expand environment %variables%
+ */
+BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen) {
+ char varName[STR];
+ char varValue[MAX_VAR_SIZE];
+ while (strlen(src) > 0) {
+ char *start = strchr(src, '%');
+ if (start != NULL) {
+ char *end = strchr(start + 1, '%');
+ if (end == NULL) {
+ return FALSE;
+ }
+ // Copy content up to %VAR%
+ strncat(dst, src, start - src);
+ // Insert value of %VAR%
+ *varName = 0;
+ strncat(varName, start + 1, end - start - 1);
+ // Remember value start for logging
+ char *varValue = dst + strlen(dst);
+ if (strcmp(varName, "EXEDIR") == 0) {
+ strncat(dst, exePath, pathLen);
+ } else if (strcmp(varName, "EXEFILE") == 0) {
+ strcat(dst, exePath);
+ } else if (strcmp(varName, "PWD") == 0) {
+ GetCurrentDirectory(_MAX_PATH, dst + strlen(dst));
+ } else if (strcmp(varName, "OLDPWD") == 0) {
+ strcat(dst, oldPwd);
+ } else if (strstr(varName, HKEY_STR) == varName) {
+ regQueryValue(varName, dst + strlen(dst), BIG_STR);
+ } else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0) {
+ strcat(dst, varValue);
+ }
+ debug("Substitute:\t%s = %s\n", varName, varValue);
+ src = end + 1;
+ } else {
+ // Copy remaining content
+ strcat(dst, src);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+void appendHeapSizes(char *dst) {
+ MEMORYSTATUS m;
+ memset(&m, 0, sizeof(m));
+ GlobalMemoryStatus(&m);
+
+ appendHeapSize(dst, INITIAL_HEAP_SIZE, INITIAL_HEAP_PERCENT,
+ m.dwAvailPhys, "-Xms");
+ appendHeapSize(dst, MAX_HEAP_SIZE, MAX_HEAP_PERCENT,
+ m.dwAvailPhys, "-Xmx");
+}
+
+void appendHeapSize(char *dst, const int absID, const int percentID,
+ const DWORD freeMemory, const char *option) {
+
+ const int mb = 1048576; // 1 MB
+ int abs = loadInt(absID);
+ int percent = loadInt(percentID);
+ int free = (long long) freeMemory * percent / (100 * mb); // 100% * 1 MB
+ int size = free > abs ? free : abs;
+ if (size > 0) {
+ debug("Heap %s:\t%d MB / %d%%, Free: %d MB, Heap size: %d MB\n",
+ option, abs, percent, freeMemory / mb, size);
+ strcat(dst, option);
+ _itoa(size, dst + strlen(dst), 10); // 10 -- radix
+ strcat(dst, "m ");
+ }
+}
+
+int prepare(const char *lpCmdLine) {
+ char tmp[MAX_ARGS] = {0};
+ hModule = GetModuleHandle(NULL);
+ if (hModule == NULL) {
+ return FALSE;
+ }
+
+ // Get executable path
+ char exePath[_MAX_PATH] = {0};
+ int pathLen = getExePath(exePath);
+ if (pathLen == -1) {
+ return FALSE;
+ }
+
+ // Initialize logging
+ if (strstr(lpCmdLine, "--l4j-debug") != NULL) {
+ hLog = openLogFile(exePath, pathLen);
+ if (hLog == NULL) {
+ return FALSE;
+ }
+ debug("\n\nCmdLine:\t%s %s\n", exePath, lpCmdLine);
+ }
+
+ setWow64Flag();
+
+ // Set default error message, title and optional support web site url.
+ loadString(SUPPORT_URL, errUrl);
+ loadString(ERR_TITLE, errTitle);
+ if (!loadString(STARTUP_ERR, errMsg)) {
+ return FALSE;
+ }
+
+ // Single instance
+ loadString(MUTEX_NAME, mutexName);
+ if (*mutexName) {
+ SECURITY_ATTRIBUTES security;
+ security.nLength = sizeof(SECURITY_ATTRIBUTES);
+ security.bInheritHandle = TRUE;
+ security.lpSecurityDescriptor = NULL;
+ CreateMutexA(&security, FALSE, mutexName);
+ if (GetLastError() == ERROR_ALREADY_EXISTS) {
+ debug("Instance already exists.");
+ return ERROR_ALREADY_EXISTS;
+ }
+ }
+
+ // Working dir
+ char tmp_path[_MAX_PATH] = {0};
+ GetCurrentDirectory(_MAX_PATH, oldPwd);
+ if (loadString(CHDIR, tmp_path)) {
+ strncpy(workingDir, exePath, pathLen);
+ appendPath(workingDir, tmp_path);
+ _chdir(workingDir);
+ debug("Working dir:\t%s\n", workingDir);
+ }
+
+ // Use bundled jre or find java
+ if (loadString(JRE_PATH, tmp_path)) {
+ char jrePath[MAX_ARGS] = {0};
+ expandVars(jrePath, tmp_path, exePath, pathLen);
+ debug("Bundled JRE:\t%s\n", jrePath);
+ if (jrePath[0] == '\\' || jrePath[1] == ':') {
+ // Absolute
+ strcpy(cmd, jrePath);
+ } else {
+ // Relative
+ strncpy(cmd, exePath, pathLen);
+ appendPath(cmd, jrePath);
+ }
+ }
+ if (!isJrePathOk(cmd)) {
+ if (!loadString(JAVA_MIN_VER, javaMinVer)) {
+ loadString(BUNDLED_JRE_ERR, errMsg);
+ return FALSE;
+ }
+ loadString(JAVA_MAX_VER, javaMaxVer);
+ if (!findJavaHome(cmd, loadInt(JDK_PREFERENCE))) {
+ loadString(JRE_VERSION_ERR, errMsg);
+ strcat(errMsg, " ");
+ strcat(errMsg, javaMinVer);
+ if (*javaMaxVer) {
+ strcat(errMsg, " - ");
+ strcat(errMsg, javaMaxVer);
+ }
+ loadString(DOWNLOAD_URL, errUrl);
+ return FALSE;
+ }
+ if (!isJrePathOk(cmd)) {
+ loadString(LAUNCHER_ERR, errMsg);
+ return FALSE;
+ }
+ }
+
+ // Append a path to the Path environment variable
+ char jreBinPath[_MAX_PATH];
+ strcpy(jreBinPath, cmd);
+ strcat(jreBinPath, "\\bin");
+ if (!appendToPathVar(jreBinPath)) {
+ return FALSE;
+ }
+
+ // Set environment variables
+ char envVars[MAX_VAR_SIZE] = {0};
+ loadString(ENV_VARIABLES, envVars);
+ char *var = strtok(envVars, "\t");
+ while (var != NULL) {
+ char *varValue = strchr(var, '=');
+ *varValue++ = 0;
+ *tmp = 0;
+ expandVars(tmp, varValue, exePath, pathLen);
+ debug("Set var:\t%s = %s\n", var, tmp);
+ SetEnvironmentVariable(var, tmp);
+ var = strtok(NULL, "\t");
+ }
+ *tmp = 0;
+
+ // Process priority
+ priority = loadInt(PRIORITY_CLASS);
+
+ // Custom process name
+ const BOOL setProcName = loadBool(SET_PROC_NAME)
+ && strstr(lpCmdLine, "--l4j-default-proc") == NULL;
+ const BOOL wrapper = loadBool(WRAPPER);
+
+ char jdk_path[_MAX_PATH] = {0}; // fry
+ strcpy(jdk_path, cmd);
+ //msgBox(jdk_path);
+
+ appendLauncher(setProcName, exePath, pathLen, cmd);
+
+ // Heap sizes
+ appendHeapSizes(args);
+
+ // JVM options
+ if (loadString(JVM_OPTIONS, tmp)) {
+ strcat(tmp, " ");
+ } else {
+ *tmp = 0;
+ }
+ /*
+ * Load additional JVM options from .l4j.ini file
+ * Options are separated by spaces or CRLF
+ * # starts an inline comment
+ */
+ strncpy(tmp_path, exePath, strlen(exePath) - 3);
+ strcat(tmp_path, "l4j.ini");
+ long hFile;
+ if ((hFile = _open(tmp_path, _O_RDONLY)) != -1) {
+ const int jvmOptLen = strlen(tmp);
+ char* src = tmp + jvmOptLen;
+ char* dst = src;
+ const int len = _read(hFile, src, MAX_ARGS - jvmOptLen - BIG_STR);
+ BOOL copy = TRUE;
+ int i;
+ for (i = 0; i < len; i++, src++) {
+ if (*src == '#') {
+ copy = FALSE;
+ } else if (*src == 13 || *src == 10) {
+ copy = TRUE;
+ if (dst > tmp && *(dst - 1) != ' ') {
+ *dst++ = ' ';
+ }
+ } else if (copy) {
+ *dst++ = *src;
+ }
+ }
+ *dst = 0;
+ if (len > 0 && *(dst - 1) != ' ') {
+ strcat(tmp, " ");
+ }
+ _close(hFile);
+ }
+
+ // Expand environment %variables%
+ expandVars(args, tmp, exePath, pathLen);
+
+ // MainClass + Classpath or Jar
+ char mainClass[STR] = {0};
+ char jar[_MAX_PATH] = {0};
+ loadString(JAR, jar);
+ if (loadString(MAIN_CLASS, mainClass)) {
+ if (!loadString(CLASSPATH, tmp)) {
+ return FALSE;
+ }
+ char exp[MAX_ARGS] = {0};
+ expandVars(exp, tmp, exePath, pathLen);
+ strcat(args, "-classpath \"");
+ if (wrapper) {
+ appendAppClasspath(args, exePath, exp);
+ } else if (*jar) {
+ appendAppClasspath(args, jar, exp);
+ }
+
+ // add tools.jar for JDK [fry]
+ char tools[_MAX_PATH] = { 0 };
+ sprintf(tools, "%s\\lib\\tools.jar", jdk_path);
+ appendAppClasspath(args, tools, exp);
+
+ // Deal with wildcards or >> strcat(args, exp); <<
+ char* cp = strtok(exp, ";");
+ while(cp != NULL) {
+ debug("Add classpath:\t%s\n", cp);
+ if (strpbrk(cp, "*?") != NULL) {
+ int len = strrchr(cp, '\\') - cp + 1;
+ strncpy(tmp_path, cp, len);
+ char* filename = tmp_path + len;
+ *filename = 0;
+ struct _finddata_t c_file;
+ long hFile;
+ if ((hFile = _findfirst(cp, &c_file)) != -1L) {
+ do {
+ strcpy(filename, c_file.name);
+ strcat(args, tmp_path);
+ strcat(args, ";");
+ debug(" \" :\t%s\n", tmp_path);
+ } while (_findnext(hFile, &c_file) == 0);
+ }
+ _findclose(hFile);
+ } else {
+ strcat(args, cp);
+ strcat(args, ";");
+ }
+ cp = strtok(NULL, ";");
+ }
+ *(args + strlen(args) - 1) = 0;
+
+ strcat(args, "\" ");
+ strcat(args, mainClass);
+ } else if (wrapper) {
+ strcat(args, "-jar \"");
+ strcat(args, exePath);
+ strcat(args, "\"");
+ } else {
+ strcat(args, "-jar \"");
+ strncat(args, exePath, pathLen);
+ appendPath(args, jar);
+ strcat(args, "\"");
+ }
+
+ // Constant command line args
+ if (loadString(CMD_LINE, tmp)) {
+ strcat(args, " ");
+ strcat(args, tmp);
+ }
+
+ // Command line args
+ if (*lpCmdLine) {
+ strcpy(tmp, lpCmdLine);
+ char* dst;
+ while ((dst = strstr(tmp, "--l4j-")) != NULL) {
+ char* src = strchr(dst, ' ');
+ if (src == NULL || *(src + 1) == 0) {
+ *dst = 0;
+ } else {
+ strcpy(dst, src + 1);
+ }
+ }
+ if (*tmp) {
+ strcat(args, " ");
+ strcat(args, tmp);
+ }
+ }
+
+ debug("Launcher:\t%s\n", cmd);
+ debug("Launcher args:\t%s\n", args);
+ debug("Args length:\t%d/32768 chars\n", strlen(args));
+ return TRUE;
+}
+
+void closeHandles() {
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ closeLogFile();
+}
+
+/*
+ * Append a path to the Path environment variable
+ */
+BOOL appendToPathVar(const char* path) {
+ char chBuf[MAX_VAR_SIZE] = {0};
+
+ const int pathSize = GetEnvironmentVariable("Path", chBuf, MAX_VAR_SIZE);
+ if (MAX_VAR_SIZE - pathSize - 1 < strlen(path)) {
+ return FALSE;
+ }
+ strcat(chBuf, ";");
+ strcat(chBuf, path);
+ return SetEnvironmentVariable("Path", chBuf);
+}
+
+// may need to ignore STILL_ACTIVE (error code 259) here
+// http://msdn.microsoft.com/en-us/library/ms683189(VS.85).aspx
+DWORD execute(const BOOL wait) {
+ STARTUPINFO si;
+ memset(&pi, 0, sizeof(pi));
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ DWORD dwExitCode = -1;
+ char cmdline[MAX_ARGS];
+ strcpy(cmdline, "\"");
+ strcat(cmdline, cmd);
+ strcat(cmdline, "\" ");
+ strcat(cmdline, args);
+ if (CreateProcess(NULL, cmdline, NULL, NULL,
+ TRUE, priority, NULL, NULL, &si, &pi)) {
+ if (wait) {
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ GetExitCodeProcess(pi.hProcess, &dwExitCode);
+ debug("Exit code:\t%d\n", dwExitCode);
+ closeHandles();
+ } else {
+ dwExitCode = 0;
+ }
+ }
+ return dwExitCode;
+}
diff --git a/build/windows/launcher/launch4j/head_src/head.h b/build/windows/launcher/launch4j/head_src/head.h
new file mode 100755
index 000000000..2e3bdb1d0
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/head.h
@@ -0,0 +1,113 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2008 Grzegorz Kowal,
+ Ian Roberts (jdk preference patch)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ Except as contained in this notice, the name(s) of the above copyright holders
+ shall not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef _LAUNCH4J_HEAD__INCLUDED_
+#define _LAUNCH4J_HEAD__INCLUDED_
+
+#define WIN32_LEAN_AND_MEAN // VC - Exclude rarely-used stuff from Windows headers
+
+// Windows Header Files:
+#include
+
+// C RunTime Header Files
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define NO_JAVA_FOUND 0
+#define FOUND_JRE 1
+#define FOUND_SDK 2
+
+#define JRE_ONLY 0
+#define PREFER_JRE 1
+#define PREFER_JDK 2
+#define JDK_ONLY 3
+
+#define LAUNCH4J_TMP_DIR "\\launch4j-tmp\\"
+#define MANIFEST ".manifest"
+
+#define KEY_WOW64_64KEY 0x0100
+
+#define HKEY_STR "HKEY"
+#define HKEY_CLASSES_ROOT_STR "HKEY_CLASSES_ROOT"
+#define HKEY_CURRENT_USER_STR "HKEY_CURRENT_USER"
+#define HKEY_LOCAL_MACHINE_STR "HKEY_LOCAL_MACHINE"
+#define HKEY_USERS_STR "HKEY_USERS"
+#define HKEY_CURRENT_CONFIG_STR "HKEY_CURRENT_CONFIG"
+
+#define STR 128
+#define BIG_STR 1024
+#define MAX_VAR_SIZE 32767
+#define MAX_ARGS 32768
+
+#define TRUE_STR "true"
+#define FALSE_STR "false"
+
+#define debug(args...) if (hLog != NULL) fprintf(hLog, ## args);
+
+typedef void (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+FILE* openLogFile(const char* exePath, const int pathLen);
+void closeLogFile();
+void msgBox(const char* text);
+void signalError();
+BOOL loadString(const int resID, char* buffer);
+BOOL loadBool(const int resID);
+int loadInt(const int resID);
+BOOL regQueryValue(const char* regPath, unsigned char* buffer,
+ unsigned long bufferLength);
+void regSearch(const HKEY hKey, const char* keyName, const int searchType);
+void regSearchWow(const char* keyName, const int searchType);
+void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
+ const int jdkPreference);
+BOOL findJavaHome(char* path, const int jdkPreference);
+int getExePath(char* exePath);
+void appendPath(char* basepath, const char* path);
+void appendJavaw(char* jrePath);
+void appendAppClasspath(char* dst, const char* src, const char* classpath);
+BOOL isJrePathOk(const char* path);
+BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathLen);
+void appendHeapSizes(char *dst);
+void appendHeapSize(char *dst, const int absID, const int percentID,
+ const DWORD freeMemory, const char *option);
+int prepare(const char *lpCmdLine);
+void closeHandles();
+BOOL appendToPathVar(const char* path);
+DWORD execute(const BOOL wait);
+
+#endif // _LAUNCH4J_HEAD__INCLUDED_
diff --git a/build/windows/launcher/launch4j/head_src/resource.h b/build/windows/launcher/launch4j/head_src/resource.h
new file mode 100755
index 000000000..3c0f73cfc
--- /dev/null
+++ b/build/windows/launcher/launch4j/head_src/resource.h
@@ -0,0 +1,71 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2008 Grzegorz Kowal
+ Ian Roberts (jdk preference patch)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ Except as contained in this notice, the name(s) of the above copyright holders
+ shall not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+// ICON
+#define APP_ICON 1
+
+// BITMAP
+#define SPLASH_BITMAP 1
+
+// RCDATA
+#define JRE_PATH 1
+#define JAVA_MIN_VER 2
+#define JAVA_MAX_VER 3
+#define SHOW_SPLASH 4
+#define SPLASH_WAITS_FOR_WINDOW 5
+#define SPLASH_TIMEOUT 6
+#define SPLASH_TIMEOUT_ERR 7
+#define CHDIR 8
+#define SET_PROC_NAME 9
+#define ERR_TITLE 10
+#define GUI_HEADER_STAYS_ALIVE 11
+#define JVM_OPTIONS 12
+#define CMD_LINE 13
+#define JAR 14
+#define MAIN_CLASS 15
+#define CLASSPATH 16
+#define WRAPPER 17
+#define JDK_PREFERENCE 18
+#define ENV_VARIABLES 19
+#define PRIORITY_CLASS 20
+#define DOWNLOAD_URL 21
+#define SUPPORT_URL 22
+#define MUTEX_NAME 23
+#define INSTANCE_WINDOW_TITLE 24
+#define INITIAL_HEAP_SIZE 25
+#define INITIAL_HEAP_PERCENT 26
+#define MAX_HEAP_SIZE 27
+#define MAX_HEAP_PERCENT 28
+
+#define STARTUP_ERR 101
+#define BUNDLED_JRE_ERR 102
+#define JRE_VERSION_ERR 103
+#define LAUNCHER_ERR 104
+#define INSTANCE_ALREADY_EXISTS_MSG 105
diff --git a/build/windows/launcher/launch4j/launch4j.exe b/build/windows/launcher/launch4j/launch4j.exe
new file mode 100755
index 000000000..0e2eb2ba5
Binary files /dev/null and b/build/windows/launcher/launch4j/launch4j.exe differ
diff --git a/build/windows/launcher/launch4j/launch4j.jar b/build/windows/launcher/launch4j/launch4j.jar
new file mode 100755
index 000000000..ec68ae48d
Binary files /dev/null and b/build/windows/launcher/launch4j/launch4j.jar differ
diff --git a/build/windows/launcher/launch4j/launch4j.jfpr b/build/windows/launcher/launch4j/launch4j.jfpr
new file mode 100755
index 000000000..a2e63ebc5
Binary files /dev/null and b/build/windows/launcher/launch4j/launch4j.jfpr differ
diff --git a/build/windows/launcher/launch4j/launch4jc.exe b/build/windows/launcher/launch4j/launch4jc.exe
new file mode 100755
index 000000000..565cc2f07
Binary files /dev/null and b/build/windows/launcher/launch4j/launch4jc.exe differ
diff --git a/build/windows/launcher/launch4j/lib/JGoodies.Forms.LICENSE.txt b/build/windows/launcher/launch4j/lib/JGoodies.Forms.LICENSE.txt
new file mode 100755
index 000000000..9ba2419e7
--- /dev/null
+++ b/build/windows/launcher/launch4j/lib/JGoodies.Forms.LICENSE.txt
@@ -0,0 +1,31 @@
+
+ The BSD License for the JGoodies Forms
+ ======================================
+
+Copyright (c) 2002-2004 JGoodies Karsten Lentzsch. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ o Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ o Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ o Neither the name of JGoodies Karsten Lentzsch nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build/windows/launcher/launch4j/lib/JGoodies.Looks.LICENSE.txt b/build/windows/launcher/launch4j/lib/JGoodies.Looks.LICENSE.txt
new file mode 100755
index 000000000..8bbefa2eb
--- /dev/null
+++ b/build/windows/launcher/launch4j/lib/JGoodies.Looks.LICENSE.txt
@@ -0,0 +1,31 @@
+
+ The BSD License for the JGoodies Looks
+ ======================================
+
+Copyright (c) 2001-2007 JGoodies Karsten Lentzsch. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ o Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ o Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ o Neither the name of JGoodies Karsten Lentzsch nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build/windows/launcher/launch4j/lib/Nuvola.Icon.Theme.LICENSE.txt b/build/windows/launcher/launch4j/lib/Nuvola.Icon.Theme.LICENSE.txt
new file mode 100755
index 000000000..cbee875ba
--- /dev/null
+++ b/build/windows/launcher/launch4j/lib/Nuvola.Icon.Theme.LICENSE.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/build/windows/launcher/launch4j/lib/XStream.LICENSE.txt b/build/windows/launcher/launch4j/lib/XStream.LICENSE.txt
new file mode 100755
index 000000000..5ccad8694
--- /dev/null
+++ b/build/windows/launcher/launch4j/lib/XStream.LICENSE.txt
@@ -0,0 +1,27 @@
+(BSD Style License)
+
+Copyright (c) 2003-2004, Joe Walnes
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of
+conditions and the following disclaimer. Redistributions in binary form must reproduce
+the above copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the distribution.
+
+Neither the name of XStream nor the names of its contributors may be used to endorse
+or promote products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
diff --git a/build/windows/launcher/launch4j/lib/commons-beanutils.jar b/build/windows/launcher/launch4j/lib/commons-beanutils.jar
new file mode 100755
index 000000000..b1b89c9c9
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/commons-beanutils.jar differ
diff --git a/build/windows/launcher/launch4j/lib/commons-logging.jar b/build/windows/launcher/launch4j/lib/commons-logging.jar
new file mode 100755
index 000000000..b73a80fab
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/commons-logging.jar differ
diff --git a/build/windows/launcher/launch4j/lib/commons.LICENSE.txt b/build/windows/launcher/launch4j/lib/commons.LICENSE.txt
new file mode 100755
index 000000000..fdb647522
--- /dev/null
+++ b/build/windows/launcher/launch4j/lib/commons.LICENSE.txt
@@ -0,0 +1,50 @@
+/*
+
+ ============================================================================
+ The Apache Software License, Version 1.1
+ ============================================================================
+
+ Copyright (C) @year@ The Apache Software Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modifica-
+ tion, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. The end-user documentation included with the redistribution, if any, must
+ include the following acknowledgment: "This product includes software
+ developed by the Apache Software Foundation (http://www.apache.org/)."
+ Alternately, this acknowledgment may appear in the software itself, if
+ and wherever such third-party acknowledgments normally appear.
+
+ 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be
+ used to endorse or promote products derived from this software without
+ prior written permission. For written permission, please contact
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation and was originally created by
+ Stefano Mazzocchi . For more information on the Apache
+ Software Foundation, please see .
+
+*/
diff --git a/build/windows/launcher/launch4j/lib/forms.jar b/build/windows/launcher/launch4j/lib/forms.jar
new file mode 100755
index 000000000..aed060a49
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/forms.jar differ
diff --git a/build/windows/launcher/launch4j/lib/formsrt.jar b/build/windows/launcher/launch4j/lib/formsrt.jar
new file mode 100755
index 000000000..e0de6ecf1
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/formsrt.jar differ
diff --git a/build/windows/launcher/launch4j/lib/foxtrot.LICENSE.txt b/build/windows/launcher/launch4j/lib/foxtrot.LICENSE.txt
new file mode 100755
index 000000000..5fa4019d5
--- /dev/null
+++ b/build/windows/launcher/launch4j/lib/foxtrot.LICENSE.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2002, Simone Bordet & Marco Cravero
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted
+provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ - Neither the name of Foxtrot nor the names of the contributors may be used
+ to endorse or promote products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build/windows/launcher/launch4j/lib/foxtrot.jar b/build/windows/launcher/launch4j/lib/foxtrot.jar
new file mode 100755
index 000000000..f39103a09
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/foxtrot.jar differ
diff --git a/build/windows/launcher/launch4j/lib/looks.jar b/build/windows/launcher/launch4j/lib/looks.jar
new file mode 100755
index 000000000..d2c47c743
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/looks.jar differ
diff --git a/build/windows/launcher/launch4j/lib/xstream.jar b/build/windows/launcher/launch4j/lib/xstream.jar
new file mode 100755
index 000000000..392e1c937
Binary files /dev/null and b/build/windows/launcher/launch4j/lib/xstream.jar differ
diff --git a/build/windows/launcher/launch4j/manifest/uac.exe.manifest b/build/windows/launcher/launch4j/manifest/uac.exe.manifest
new file mode 100755
index 000000000..3041fbc5b
--- /dev/null
+++ b/build/windows/launcher/launch4j/manifest/uac.exe.manifest
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/manifest/xp-themes.exe.manifest b/build/windows/launcher/launch4j/manifest/xp-themes.exe.manifest
new file mode 100755
index 000000000..e2c7511f9
--- /dev/null
+++ b/build/windows/launcher/launch4j/manifest/xp-themes.exe.manifest
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/src/images/asterix-o.gif b/build/windows/launcher/launch4j/src/images/asterix-o.gif
new file mode 100755
index 000000000..f5cf3b307
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/asterix-o.gif differ
diff --git a/build/windows/launcher/launch4j/src/images/asterix.gif b/build/windows/launcher/launch4j/src/images/asterix.gif
new file mode 100755
index 000000000..ba801670a
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/asterix.gif differ
diff --git a/build/windows/launcher/launch4j/src/images/build.png b/build/windows/launcher/launch4j/src/images/build.png
new file mode 100755
index 000000000..625285f0b
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/build.png differ
diff --git a/build/windows/launcher/launch4j/src/images/button_ok.png b/build/windows/launcher/launch4j/src/images/button_ok.png
new file mode 100755
index 000000000..5b0f6a617
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/button_ok.png differ
diff --git a/build/windows/launcher/launch4j/src/images/cancel16.png b/build/windows/launcher/launch4j/src/images/cancel16.png
new file mode 100755
index 000000000..a432b492c
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/cancel16.png differ
diff --git a/build/windows/launcher/launch4j/src/images/down16.png b/build/windows/launcher/launch4j/src/images/down16.png
new file mode 100755
index 000000000..f3bc4cd09
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/down16.png differ
diff --git a/build/windows/launcher/launch4j/src/images/edit_add16.png b/build/windows/launcher/launch4j/src/images/edit_add16.png
new file mode 100755
index 000000000..e9485082e
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/edit_add16.png differ
diff --git a/build/windows/launcher/launch4j/src/images/info.png b/build/windows/launcher/launch4j/src/images/info.png
new file mode 100755
index 000000000..eb37d9a08
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/info.png differ
diff --git a/build/windows/launcher/launch4j/src/images/new.png b/build/windows/launcher/launch4j/src/images/new.png
new file mode 100755
index 000000000..6e2700ad9
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/new.png differ
diff --git a/build/windows/launcher/launch4j/src/images/new16.png b/build/windows/launcher/launch4j/src/images/new16.png
new file mode 100755
index 000000000..f38d02ee5
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/new16.png differ
diff --git a/build/windows/launcher/launch4j/src/images/ok16.png b/build/windows/launcher/launch4j/src/images/ok16.png
new file mode 100755
index 000000000..5b0f6a617
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/ok16.png differ
diff --git a/build/windows/launcher/launch4j/src/images/open.png b/build/windows/launcher/launch4j/src/images/open.png
new file mode 100755
index 000000000..a801665fd
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/open.png differ
diff --git a/build/windows/launcher/launch4j/src/images/open16.png b/build/windows/launcher/launch4j/src/images/open16.png
new file mode 100755
index 000000000..5321c17c6
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/open16.png differ
diff --git a/build/windows/launcher/launch4j/src/images/run.png b/build/windows/launcher/launch4j/src/images/run.png
new file mode 100755
index 000000000..b41fa2b97
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/run.png differ
diff --git a/build/windows/launcher/launch4j/src/images/save.png b/build/windows/launcher/launch4j/src/images/save.png
new file mode 100755
index 000000000..74b37b0b5
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/save.png differ
diff --git a/build/windows/launcher/launch4j/src/images/up16.png b/build/windows/launcher/launch4j/src/images/up16.png
new file mode 100755
index 000000000..184c118b6
Binary files /dev/null and b/build/windows/launcher/launch4j/src/images/up16.png differ
diff --git a/build/windows/launcher/launch4j/src/launch4j.properties b/build/windows/launcher/launch4j/src/launch4j.properties
new file mode 100755
index 000000000..463c7a034
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/launch4j.properties
@@ -0,0 +1,2 @@
+versionNumber=3.0.1.0
+version=3.0.1
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/Builder.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/Builder.java
new file mode 100755
index 000000000..d7badc7f3
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/Builder.java
@@ -0,0 +1,207 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2005-04-24
+ */
+package net.sf.launch4j;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sf.launch4j.binding.InvariantViolationException;
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.config.ConfigPersister;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Builder {
+ private final Log _log;
+ private final File _basedir;
+
+ public Builder(Log log) {
+ _log = log;
+ _basedir = Util.getJarBasedir();
+ }
+
+ public Builder(Log log, File basedir) {
+ _log = log;
+ _basedir = basedir;
+ }
+
+ /**
+ * @return Output file path.
+ */
+ public File build() throws BuilderException {
+ final Config c = ConfigPersister.getInstance().getConfig();
+ try {
+ c.validate();
+ } catch (InvariantViolationException e) {
+ throw new BuilderException(e.getMessage());
+ }
+ File rc = null;
+ File ro = null;
+ File outfile = null;
+ FileInputStream is = null;
+ FileOutputStream os = null;
+ final RcBuilder rcb = new RcBuilder();
+ try {
+ rc = rcb.build(c);
+ ro = Util.createTempFile("o");
+ outfile = ConfigPersister.getInstance().getOutputFile();
+
+ Cmd resCmd = new Cmd(_basedir);
+ resCmd.addExe("windres")
+ .add(Util.WINDOWS_OS ? "--preprocessor=type" : "--preprocessor=cat")
+ .add("-J rc -O coff -F pe-i386")
+ .addAbsFile(rc)
+ .addAbsFile(ro);
+ _log.append(Messages.getString("Builder.compiling.resources"));
+ resCmd.exec(_log);
+
+ Cmd ldCmd = new Cmd(_basedir);
+ ldCmd.addExe("ld")
+ .add("-mi386pe")
+ .add("--oformat pei-i386")
+ .add((c.getHeaderType().equals(Config.GUI_HEADER))
+ ? "--subsystem windows" : "--subsystem console")
+ .add("-s") // strip symbols
+ .addFiles(c.getHeaderObjects())
+ .addAbsFile(ro)
+ .addFiles(c.getLibs())
+ .add("-o")
+ .addAbsFile(outfile);
+ _log.append(Messages.getString("Builder.linking"));
+ ldCmd.exec(_log);
+
+ if (!c.isDontWrapJar()) {
+ _log.append(Messages.getString("Builder.wrapping"));
+ int len;
+ byte[] buffer = new byte[1024];
+ is = new FileInputStream(Util.getAbsoluteFile(
+ ConfigPersister.getInstance().getConfigPath(), c.getJar()));
+ os = new FileOutputStream(outfile, true);
+ while ((len = is.read(buffer)) > 0) {
+ os.write(buffer, 0, len);
+ }
+ }
+ _log.append(Messages.getString("Builder.success") + outfile.getPath());
+ return outfile;
+ } catch (IOException e) {
+ Util.delete(outfile);
+ _log.append(e.getMessage());
+ throw new BuilderException(e);
+ } catch (ExecException e) {
+ Util.delete(outfile);
+ String msg = e.getMessage();
+ if (msg != null && msg.indexOf("windres") != -1) {
+ if (e.getErrLine() != -1) {
+ _log.append(Messages.getString("Builder.line.has.errors",
+ String.valueOf(e.getErrLine())));
+ _log.append(rcb.getLine(e.getErrLine()));
+ } else {
+ _log.append(Messages.getString("Builder.generated.resource.file"));
+ _log.append(rcb.getContent());
+ }
+ }
+ throw new BuilderException(e);
+ } finally {
+ Util.close(is);
+ Util.close(os);
+ Util.delete(rc);
+ Util.delete(ro);
+ }
+ }
+}
+
+class Cmd {
+ private final List _cmd = new ArrayList();
+ private final File _basedir;
+ private final File _bindir;
+
+ public Cmd(File basedir) {
+ _basedir = basedir;
+ String path = System.getProperty("launch4j.bindir");
+ if (path == null) {
+ _bindir = new File(basedir, "bin");
+ } else {
+ File bindir = new File(path);
+ _bindir = bindir.isAbsolute() ? bindir : new File(basedir, path);
+ }
+ }
+
+ public Cmd add(String s) {
+ StringTokenizer st = new StringTokenizer(s);
+ while (st.hasMoreTokens()) {
+ _cmd.add(st.nextToken());
+ }
+ return this;
+ }
+
+ public Cmd addAbsFile(File file) {
+ _cmd.add(file.getPath());
+ return this;
+ }
+
+ public Cmd addFile(String pathname) {
+ _cmd.add(new File(_basedir, pathname).getPath());
+ return this;
+ }
+
+ public Cmd addExe(String pathname) {
+ if (Util.WINDOWS_OS) {
+ pathname += ".exe";
+ }
+ _cmd.add(new File(_bindir, pathname).getPath());
+ return this;
+ }
+
+ public Cmd addFiles(List files) {
+ for (Iterator iter = files.iterator(); iter.hasNext();) {
+ addFile((String) iter.next());
+ }
+ return this;
+ }
+
+ public void exec(Log log) throws ExecException {
+ String[] cmd = (String[]) _cmd.toArray(new String[_cmd.size()]);
+ Util.exec(cmd, log);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/BuilderException.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/BuilderException.java
new file mode 100755
index 000000000..a84c2e279
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/BuilderException.java
@@ -0,0 +1,52 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 13, 2005
+ */
+package net.sf.launch4j;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class BuilderException extends Exception {
+ public BuilderException() {}
+
+ public BuilderException(Throwable t) {
+ super(t);
+ }
+
+ public BuilderException(String msg) {
+ super(msg);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ExecException.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ExecException.java
new file mode 100755
index 000000000..236ae780f
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ExecException.java
@@ -0,0 +1,66 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 14, 2005
+ */
+package net.sf.launch4j;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class ExecException extends Exception {
+ private final int _errLine;
+
+ public ExecException(Throwable t, int errLine) {
+ super(t);
+ _errLine = errLine;
+ }
+
+ public ExecException(Throwable t) {
+ this(t, -1);
+ }
+
+ public ExecException(String msg, int errLine) {
+ super(msg);
+ _errLine = errLine;
+ }
+
+ public ExecException(String msg) {
+ this(msg, -1);
+ }
+
+ public int getErrLine() {
+ return _errLine;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/FileChooserFilter.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/FileChooserFilter.java
new file mode 100755
index 000000000..5199a6deb
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/FileChooserFilter.java
@@ -0,0 +1,76 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2004-01-15
+ */
+package net.sf.launch4j;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * @author Copyright (C) 2004 Grzegorz Kowal
+ */
+public class FileChooserFilter extends FileFilter {
+ String _description;
+ String[] _extensions;
+
+ public FileChooserFilter(String description, String extension) {
+ _description = description;
+ _extensions = new String[] {extension};
+ }
+
+ public FileChooserFilter(String description, String[] extensions) {
+ _description = description;
+ _extensions = extensions;
+ }
+
+ public boolean accept(File f) {
+ if (f.isDirectory()) {
+ return true;
+ }
+ String ext = Util.getExtension(f);
+ for (int i = 0; i < _extensions.length; i++) {
+ if (ext.toLowerCase().equals(_extensions[i].toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getDescription() {
+ return _description;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/Log.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/Log.java
new file mode 100755
index 000000000..c4d591b0c
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/Log.java
@@ -0,0 +1,105 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 12, 2005
+ */
+package net.sf.launch4j;
+
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public abstract class Log {
+ private static final Log _consoleLog = new ConsoleLog();
+ private static final Log _antLog = new AntLog();
+
+ public abstract void clear();
+ public abstract void append(String line);
+
+ public static Log getConsoleLog() {
+ return _consoleLog;
+ }
+
+ public static Log getAntLog() {
+ return _antLog;
+ }
+
+ public static Log getSwingLog(JTextArea textArea) {
+ return new SwingLog(textArea);
+ }
+}
+
+class ConsoleLog extends Log {
+ public void clear() {
+ System.out.println("\n");
+ }
+
+ public void append(String line) {
+ System.out.println("launch4j: " + line);
+ }
+}
+
+class AntLog extends Log {
+ public void clear() {
+ System.out.println("\n");
+ }
+
+ public void append(String line) {
+ System.out.println(line);
+ }
+}
+
+class SwingLog extends Log {
+ private final JTextArea _textArea;
+
+ public SwingLog(JTextArea textArea) {
+ _textArea = textArea;
+ }
+
+ public void clear() {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ _textArea.setText("");
+ }});
+ }
+
+ public void append(final String line) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ _textArea.append(line + "\n");
+ }});
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/Main.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/Main.java
new file mode 100755
index 000000000..45f84ad79
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/Main.java
@@ -0,0 +1,99 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2008 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 21, 2005
+ */
+package net.sf.launch4j;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Properties;
+
+import net.sf.launch4j.config.ConfigPersister;
+import net.sf.launch4j.formimpl.MainFrame;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Main {
+ private static String _name;
+ private static String _description;
+
+ public static void main(String[] args) {
+ try {
+ Properties props = new Properties();
+ InputStream in = Main.class.getClassLoader()
+ .getResourceAsStream("launch4j.properties");
+ props.load(in);
+ in.close();
+ setDescription(props);
+
+ if (args.length == 0) {
+ ConfigPersister.getInstance().createBlank();
+ MainFrame.createInstance();
+ } else if (args.length == 1 && !args[0].startsWith("-")) {
+ ConfigPersister.getInstance().load(new File(args[0]));
+ Builder b = new Builder(Log.getConsoleLog());
+ b.build();
+ } else {
+ System.out.println(_description
+ + Messages.getString("Main.usage")
+ + ": launch4j config.xml");
+ }
+ } catch (Exception e) {
+ Log.getConsoleLog().append(e.getMessage());
+ }
+ }
+
+ public static String getName() {
+ return _name;
+ }
+
+ public static String getDescription() {
+ return _description;
+ }
+
+ private static void setDescription(Properties props) {
+ _name = "Launch4j " + props.getProperty("version");
+ _description = _name +
+ " (http://launch4j.sourceforge.net/)\n" +
+ "Cross-platform Java application wrapper" +
+ " for creating Windows native executables.\n\n" +
+ "Copyright (C) 2004, 2008 Grzegorz Kowal\n\n" +
+ "Launch4j comes with ABSOLUTELY NO WARRANTY.\n" +
+ "This is free software, licensed under the BSD License.\n" +
+ "This product includes software developed by the Apache Software Foundation" +
+ " (http://www.apache.org/).";
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/Messages.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/Messages.java
new file mode 100755
index 000000000..35d4c8950
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/Messages.java
@@ -0,0 +1,78 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "net.sf.launch4j.messages";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+ private static final MessageFormat FORMATTER = new MessageFormat("");
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ public static String getString(String key, String arg0) {
+ return getString(key, new Object[] {arg0});
+ }
+
+ public static String getString(String key, String arg0, String arg1) {
+ return getString(key, new Object[] {arg0, arg1});
+ }
+
+ public static String getString(String key, String arg0, String arg1, String arg2) {
+ return getString(key, new Object[] {arg0, arg1, arg2});
+ }
+
+ public static String getString(String key, Object[] args) {
+ try {
+ FORMATTER.applyPattern(RESOURCE_BUNDLE.getString(key));
+ return FORMATTER.format(args);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/OptionParser.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/OptionParser.java
new file mode 100755
index 000000000..bb2432c8e
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/OptionParser.java
@@ -0,0 +1,71 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2005-04-24
+ */
+package net.sf.launch4j;
+
+//import net.sf.launch4j.config.Config;
+
+//import org.apache.commons.cli.CommandLine;
+//import org.apache.commons.cli.CommandLineParser;
+//import org.apache.commons.cli.HelpFormatter;
+//import org.apache.commons.cli.Options;
+//import org.apache.commons.cli.ParseException;
+//import org.apache.commons.cli.PosixParser;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class OptionParser {
+
+// private final Options _options;
+//
+// public OptionParser() {
+// _options = new Options();
+// _options.addOption("h", "header", true, "header");
+// }
+//
+// public Config parse(Config c, String[] args) throws ParseException {
+// CommandLineParser parser = new PosixParser();
+// CommandLine cl = parser.parse(_options, args);
+// c.setJar(getFile(props, Config.JAR));
+// c.setOutfile(getFile(props, Config.OUTFILE));
+// }
+//
+// public void printHelp() {
+// HelpFormatter formatter = new HelpFormatter();
+// formatter.printHelp("launch4j", _options);
+// }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/RcBuilder.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/RcBuilder.java
new file mode 100755
index 000000000..f8885e3e6
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/RcBuilder.java
@@ -0,0 +1,340 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2005-04-24
+ */
+package net.sf.launch4j;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.config.ConfigPersister;
+import net.sf.launch4j.config.Jre;
+import net.sf.launch4j.config.Msg;
+import net.sf.launch4j.config.Splash;
+import net.sf.launch4j.config.VersionInfo;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class RcBuilder {
+
+ // winnt.h
+ public static final int LANG_NEUTRAL = 0;
+ public static final int SUBLANG_NEUTRAL = 0;
+ public static final int SUBLANG_DEFAULT = 1;
+ public static final int SUBLANG_SYS_DEFAULT = 2;
+
+ // MANIFEST
+ public static final int MANIFEST = 1;
+
+ // ICON
+ public static final int APP_ICON = 1;
+
+ // BITMAP
+ public static final int SPLASH_BITMAP = 1;
+
+ // RCDATA
+ public static final int JRE_PATH = 1;
+ public static final int JAVA_MIN_VER = 2;
+ public static final int JAVA_MAX_VER = 3;
+ public static final int SHOW_SPLASH = 4;
+ public static final int SPLASH_WAITS_FOR_WINDOW = 5;
+ public static final int SPLASH_TIMEOUT = 6;
+ public static final int SPLASH_TIMEOUT_ERR = 7;
+ public static final int CHDIR = 8;
+ public static final int SET_PROC_NAME = 9;
+ public static final int ERR_TITLE = 10;
+ public static final int GUI_HEADER_STAYS_ALIVE = 11;
+ public static final int JVM_OPTIONS = 12;
+ public static final int CMD_LINE = 13;
+ public static final int JAR = 14;
+ public static final int MAIN_CLASS = 15;
+ public static final int CLASSPATH = 16;
+ public static final int WRAPPER = 17;
+ public static final int JDK_PREFERENCE = 18;
+ public static final int ENV_VARIABLES = 19;
+ public static final int PRIORITY_CLASS = 20;
+ public static final int DOWNLOAD_URL = 21;
+ public static final int SUPPORT_URL = 22;
+ public static final int MUTEX_NAME = 23;
+ public static final int INSTANCE_WINDOW_TITLE = 24;
+ public static final int INITIAL_HEAP_SIZE = 25;
+ public static final int INITIAL_HEAP_PERCENT = 26;
+ public static final int MAX_HEAP_SIZE = 27;
+ public static final int MAX_HEAP_PERCENT = 28;
+
+ public static final int STARTUP_ERR = 101;
+ public static final int BUNDLED_JRE_ERR = 102;
+ public static final int JRE_VERSION_ERR = 103;
+ public static final int LAUNCHER_ERR = 104;
+ public static final int INSTANCE_ALREADY_EXISTS_MSG = 105;
+
+ private final StringBuffer _sb = new StringBuffer();
+
+ public String getContent() {
+ return _sb.toString();
+ }
+
+ public String getLine(int line) {
+ return _sb.toString().split("\n")[line - 1];
+ }
+
+ public File build(Config c) throws IOException {
+ _sb.append("LANGUAGE ");
+ _sb.append(LANG_NEUTRAL);
+ _sb.append(", ");
+ _sb.append(SUBLANG_DEFAULT);
+ _sb.append('\n');
+ addVersionInfo(c.getVersionInfo());
+ addJre(c.getJre());
+ addManifest(MANIFEST, c.getManifest());
+ addIcon(APP_ICON, c.getIcon());
+ addText(ERR_TITLE, c.getErrTitle());
+ addText(DOWNLOAD_URL, c.getDownloadUrl());
+ addText(SUPPORT_URL, c.getSupportUrl());
+ addText(CMD_LINE, c.getCmdLine());
+ addWindowsPath(CHDIR, c.getChdir());
+ addText(PRIORITY_CLASS, String.valueOf(c.getPriorityClass()));
+ addTrue(SET_PROC_NAME, c.isCustomProcName());
+ addTrue(GUI_HEADER_STAYS_ALIVE, c.isStayAlive());
+ addSplash(c.getSplash());
+ addMessages(c);
+
+ if (c.getSingleInstance() != null) {
+ addText(MUTEX_NAME, c.getSingleInstance().getMutexName());
+ addText(INSTANCE_WINDOW_TITLE, c.getSingleInstance().getWindowTitle());
+ }
+
+ if (c.getVariables() != null && !c.getVariables().isEmpty()) {
+ StringBuffer vars = new StringBuffer();
+ append(vars, c.getVariables(), "\t");
+ addText(ENV_VARIABLES, vars.toString());
+ }
+
+ // MAIN_CLASS / JAR
+ addTrue(WRAPPER, !c.isDontWrapJar());
+ if (c.getClassPath() != null) {
+ addText(MAIN_CLASS, c.getClassPath().getMainClass());
+ addWindowsPath(CLASSPATH, c.getClassPath().getPathsString());
+ }
+ if (c.isDontWrapJar() && c.getJar() != null) {
+ addWindowsPath(JAR, c.getJar().getPath());
+ }
+
+ File f = Util.createTempFile("rc");
+ BufferedWriter w = new BufferedWriter(new FileWriter(f));
+ w.write(_sb.toString());
+ w.close();
+ return f;
+ }
+
+ private void addVersionInfo(VersionInfo v) {
+ if (v == null) {
+ return;
+ }
+ _sb.append("1 VERSIONINFO\n");
+ _sb.append("FILEVERSION ");
+ _sb.append(v.getFileVersion().replaceAll("\\.", ", "));
+ _sb.append("\nPRODUCTVERSION ");
+ _sb.append(v.getProductVersion().replaceAll("\\.", ", "));
+ _sb.append("\nFILEFLAGSMASK 0\n" +
+ "FILEOS 0x40000\n" +
+ "FILETYPE 1\n" +
+ "{\n" +
+ " BLOCK \"StringFileInfo\"\n" +
+ " {\n" +
+ " BLOCK \"040904E4\"\n" + // English
+ " {\n");
+ addVerBlockValue("CompanyName", v.getCompanyName());
+ addVerBlockValue("FileDescription", v.getFileDescription());
+ addVerBlockValue("FileVersion", v.getTxtFileVersion());
+ addVerBlockValue("InternalName", v.getInternalName());
+ addVerBlockValue("LegalCopyright", v.getCopyright());
+ addVerBlockValue("OriginalFilename", v.getOriginalFilename());
+ addVerBlockValue("ProductName", v.getProductName());
+ addVerBlockValue("ProductVersion", v.getTxtProductVersion());
+ _sb.append(" }\n }\nBLOCK \"VarFileInfo\"\n{\nVALUE \"Translation\", 0x0409, 0x04E4\n}\n}");
+ }
+
+ private void addJre(Jre jre) {
+ addWindowsPath(JRE_PATH, jre.getPath());
+ addText(JAVA_MIN_VER, jre.getMinVersion());
+ addText(JAVA_MAX_VER, jre.getMaxVersion());
+ addText(JDK_PREFERENCE, String.valueOf(jre.getJdkPreferenceIndex()));
+ addInteger(INITIAL_HEAP_SIZE, jre.getInitialHeapSize());
+ addInteger(INITIAL_HEAP_PERCENT, jre.getInitialHeapPercent());
+ addInteger(MAX_HEAP_SIZE, jre.getMaxHeapSize());
+ addInteger(MAX_HEAP_PERCENT, jre.getMaxHeapPercent());
+
+ StringBuffer options = new StringBuffer();
+ if (jre.getOptions() != null && !jre.getOptions().isEmpty()) {
+ addSpace(options);
+ append(options, jre.getOptions(), " ");
+ }
+ addText(JVM_OPTIONS, options.toString());
+ }
+
+ private void addSplash(Splash splash) {
+ if (splash == null) {
+ return;
+ }
+ addTrue(SHOW_SPLASH, true);
+ addTrue(SPLASH_WAITS_FOR_WINDOW, splash.getWaitForWindow());
+ addText(SPLASH_TIMEOUT, String.valueOf(splash.getTimeout()));
+ addTrue(SPLASH_TIMEOUT_ERR, splash.isTimeoutErr());
+ addBitmap(SPLASH_BITMAP, splash.getFile());
+ }
+
+ private void addMessages(Config c) {
+ Msg msg = c.getMessages();
+ if (msg == null) {
+ msg = new Msg();
+ }
+ addText(STARTUP_ERR, msg.getStartupErr());
+ addText(BUNDLED_JRE_ERR, msg.getBundledJreErr());
+ addText(JRE_VERSION_ERR, msg.getJreVersionErr());
+ addText(LAUNCHER_ERR, msg.getLauncherErr());
+ if (c.getSingleInstance() != null) {
+ addText(INSTANCE_ALREADY_EXISTS_MSG, msg.getInstanceAlreadyExistsMsg());
+ }
+ }
+
+ private void append(StringBuffer sb, List list, String separator) {
+ for (int i = 0; i < list.size(); i++) {
+ sb.append(list.get(i));
+ if (i < list.size() - 1) {
+ sb.append(separator);
+ }
+ }
+ }
+
+ private void addText(int id, String text) {
+ if (text == null || text.equals("")) {
+ return;
+ }
+ _sb.append(id);
+ _sb.append(" RCDATA BEGIN \"");
+ _sb.append(escape(text));
+ _sb.append("\\0\" END\n");
+ }
+
+ private void addTrue(int id, boolean value) {
+ if (value) {
+ addText(id, "true");
+ }
+ }
+
+ private void addInteger(int id, Integer value) {
+ if (value != null) {
+ addText(id, value.toString());
+ }
+ }
+
+ /**
+ * Stores path in Windows format with '\' separators.
+ */
+ private void addWindowsPath(int id, String path) {
+ if (path == null || path.equals("")) {
+ return;
+ }
+ _sb.append(id);
+ _sb.append(" RCDATA BEGIN \"");
+ _sb.append(path.replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll("/", "\\\\\\\\"));
+ _sb.append("\\0\" END\n");
+ }
+
+ private void addManifest(int id, File manifest) {
+ if (manifest == null || manifest.getPath().equals("")) {
+ return;
+ }
+ _sb.append(id);
+ _sb.append(" 24 \"");
+ _sb.append(getPath(Util.getAbsoluteFile(
+ ConfigPersister.getInstance().getConfigPath(), manifest)));
+ _sb.append("\"\n");
+ }
+
+ private void addIcon(int id, File icon) {
+ if (icon == null || icon.getPath().equals("")) {
+ return;
+ }
+ _sb.append(id);
+ _sb.append(" ICON DISCARDABLE \"");
+ _sb.append(getPath(Util.getAbsoluteFile(
+ ConfigPersister.getInstance().getConfigPath(), icon)));
+ _sb.append("\"\n");
+ }
+
+ private void addBitmap(int id, File bitmap) {
+ if (bitmap == null) {
+ return;
+ }
+ _sb.append(id);
+ _sb.append(" BITMAP \"");
+ _sb.append(getPath(Util.getAbsoluteFile(
+ ConfigPersister.getInstance().getConfigPath(), bitmap)));
+ _sb.append("\"\n");
+ }
+
+ private String getPath(File f) {
+ return f.getPath().replaceAll("\\\\", "\\\\\\\\");
+ }
+
+ private void addSpace(StringBuffer sb) {
+ int len = sb.length();
+ if (len-- > 0 && sb.charAt(len) != ' ') {
+ sb.append(' ');
+ }
+ }
+
+ private void addVerBlockValue(String key, String value) {
+ _sb.append(" VALUE \"");
+ _sb.append(key);
+ _sb.append("\", \"");
+ if (value != null) {
+ _sb.append(escape(value));
+ }
+ _sb.append("\"\n");
+ }
+
+ private String escape(String text) {
+ return text.replaceAll("\"", "\"\"");
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/Util.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/Util.java
new file mode 100755
index 000000000..f3bf2456d
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/Util.java
@@ -0,0 +1,197 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2005-04-24
+ */
+package net.sf.launch4j;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Util {
+ public static final boolean WINDOWS_OS = System.getProperty("os.name")
+ .toLowerCase().startsWith("windows");
+
+ private Util() {}
+
+ public static File createTempFile(String suffix) throws IOException {
+ String tmpdir = System.getProperty("launch4j.tmpdir");
+ if (tmpdir != null) {
+ if (tmpdir.indexOf(' ') != -1) {
+ throw new IOException(Messages.getString("Util.tmpdir"));
+ }
+ return File.createTempFile("launch4j", suffix, new File(tmpdir));
+ } else {
+ return File.createTempFile("launch4j", suffix);
+ }
+ }
+
+ /**
+ * Returns the base directory of a jar file or null if the class is a standalone file.
+ * @return System specific path
+ *
+ * Based on a patch submitted by Josh Elsasser
+ */
+ public static File getJarBasedir() {
+ String url = Util.class.getClassLoader()
+ .getResource(Util.class.getName().replace('.', '/') + ".class")
+ .getFile()
+ .replaceAll("%20", " ");
+ if (url.startsWith("file:")) {
+ String jar = url.substring(5, url.lastIndexOf('!'));
+ int x = jar.lastIndexOf('/');
+ if (x == -1) {
+ x = jar.lastIndexOf('\\');
+ }
+ String basedir = jar.substring(0, x + 1);
+ return new File(basedir);
+ } else {
+ return new File(".");
+ }
+ }
+
+ public static File getAbsoluteFile(File basepath, File f) {
+ return f.isAbsolute() ? f : new File(basepath, f.getPath());
+ }
+
+ public static String getExtension(File f) {
+ String name = f.getName();
+ int x = name.lastIndexOf('.');
+ if (x != -1) {
+ return name.substring(x);
+ } else {
+ return "";
+ }
+ }
+
+ public static void exec(String[] cmd, Log log) throws ExecException {
+ BufferedReader is = null;
+ try {
+ if (WINDOWS_OS) {
+ for (int i = 0; i < cmd.length; i++) {
+ cmd[i] = cmd[i].replaceAll("/", "\\\\");
+ }
+ }
+ Process p = Runtime.getRuntime().exec(cmd);
+ is = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+ String line;
+ int errLine = -1;
+ Pattern pattern = Pattern.compile(":\\d+:");
+ while ((line = is.readLine()) != null) {
+ log.append(line);
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.find()) {
+ errLine = Integer.valueOf(
+ line.substring(matcher.start() + 1, matcher.end() - 1))
+ .intValue();
+ if (line.matches("(?i).*unrecognized escape sequence")) {
+ log.append(Messages.getString("Util.use.double.backslash"));
+ }
+ break;
+ }
+ }
+ is.close();
+ p.waitFor();
+ if (errLine != -1) {
+ throw new ExecException(Messages.getString("Util.exec.failed")
+ + ": " + cmd, errLine);
+ }
+ if (p.exitValue() != 0) {
+ throw new ExecException(Messages.getString("Util.exec.failed")
+ + "(" + p.exitValue() + "): " + cmd);
+ }
+ } catch (IOException e) {
+ close(is);
+ throw new ExecException(e);
+ } catch (InterruptedException e) {
+ close(is);
+ throw new ExecException(e);
+ }
+ }
+
+ public static void close(final InputStream o) {
+ if (o != null) {
+ try {
+ o.close();
+ } catch (IOException e) {
+ System.err.println(e); // XXX log
+ }
+ }
+ }
+
+ public static void close(final OutputStream o) {
+ if (o != null) {
+ try {
+ o.close();
+ } catch (IOException e) {
+ System.err.println(e); // XXX log
+ }
+ }
+ }
+
+ public static void close(final Reader o) {
+ if (o != null) {
+ try {
+ o.close();
+ } catch (IOException e) {
+ System.err.println(e); // XXX log
+ }
+ }
+ }
+
+ public static void close(final Writer o) {
+ if (o != null) {
+ try {
+ o.close();
+ } catch (IOException e) {
+ System.err.println(e); // XXX log
+ }
+ }
+ }
+
+ public static boolean delete(File f) {
+ return (f != null) ? f.delete() : false;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntClassPath.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntClassPath.java
new file mode 100755
index 000000000..a67bab91f
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntClassPath.java
@@ -0,0 +1,61 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jul 19, 2006
+ */
+package net.sf.launch4j.ant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.launch4j.config.ClassPath;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class AntClassPath extends ClassPath {
+ private final List wrappedPaths = new ArrayList();
+
+ public void setCp(String cp){
+ wrappedPaths.add(cp);
+ }
+
+ public void addCp(StringWrapper cp) {
+ wrappedPaths.add(cp);
+ }
+
+ public void unwrap() {
+ setPaths(StringWrapper.unwrap(wrappedPaths));
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntConfig.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntConfig.java
new file mode 100755
index 000000000..4482436a9
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntConfig.java
@@ -0,0 +1,129 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 24, 2005
+ */
+package net.sf.launch4j.ant;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tools.ant.BuildException;
+
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.config.Msg;
+import net.sf.launch4j.config.SingleInstance;
+import net.sf.launch4j.config.Splash;
+import net.sf.launch4j.config.VersionInfo;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class AntConfig extends Config {
+ private final List wrappedHeaderObjects = new ArrayList();
+ private final List wrappedLibs = new ArrayList();
+ private final List wrappedVariables = new ArrayList();
+
+ public void setJarPath(String path) {
+ setJar(new File(path));
+ }
+
+ public void addObj(StringWrapper obj) {
+ wrappedHeaderObjects.add(obj);
+ }
+
+ public void addLib(StringWrapper lib) {
+ wrappedLibs.add(lib);
+ }
+
+ public void addVar(StringWrapper var) {
+ wrappedVariables.add(var);
+ }
+
+ // __________________________________________________________________________________
+
+ public void addSingleInstance(SingleInstance singleInstance) {
+ checkNull(getSingleInstance(), "singleInstance");
+ setSingleInstance(singleInstance);
+ }
+
+ public void addClassPath(AntClassPath classPath) {
+ checkNull(getClassPath(), "classPath");
+ setClassPath(classPath);
+ }
+
+ public void addJre(AntJre jre) {
+ checkNull(getJre(), "jre");
+ setJre(jre);
+ }
+
+ public void addSplash(Splash splash) {
+ checkNull(getSplash(), "splash");
+ setSplash(splash);
+ }
+
+ public void addVersionInfo(VersionInfo versionInfo) {
+ checkNull(getVersionInfo(), "versionInfo");
+ setVersionInfo(versionInfo);
+ }
+
+ public void addMessages(Msg messages) {
+ checkNull(getMessages(), "messages");
+ setMessages(messages);
+ }
+
+ // __________________________________________________________________________________
+
+ public void unwrap() {
+ setHeaderObjects(StringWrapper.unwrap(wrappedHeaderObjects));
+ setLibs(StringWrapper.unwrap(wrappedLibs));
+ setVariables(StringWrapper.unwrap(wrappedVariables));
+ if (getClassPath() != null) {
+ ((AntClassPath) getClassPath()).unwrap();
+ }
+ if (getJre() != null) {
+ ((AntJre) getJre()).unwrap();
+ }
+ }
+
+ private void checkNull(Object o, String name) {
+ if (o != null) {
+ throw new BuildException(
+ Messages.getString("AntConfig.duplicate.element")
+ + ": "
+ + name);
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntJre.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntJre.java
new file mode 100755
index 000000000..b83e3ee02
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/AntJre.java
@@ -0,0 +1,69 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jul 18, 2006
+ */
+package net.sf.launch4j.ant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.launch4j.config.Jre;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class AntJre extends Jre {
+ private final List wrappedOptions = new ArrayList();
+
+ public void addOpt(StringWrapper opt) {
+ wrappedOptions.add(opt);
+ }
+
+ public void unwrap() {
+ setOptions(StringWrapper.unwrap(wrappedOptions));
+ }
+
+ /**
+ * For backwards compatibility.
+ */
+ public void setDontUsePrivateJres(boolean dontUse) {
+ if (dontUse) {
+ setJdkPreference(JDK_PREFERENCE_JRE_ONLY);
+ }
+ else {
+ setJdkPreference(JDK_PREFERENCE_PREFER_JRE);
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/Launch4jTask.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/Launch4jTask.java
new file mode 100755
index 000000000..a28287698
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/Launch4jTask.java
@@ -0,0 +1,162 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 24, 2005
+ */
+package net.sf.launch4j.ant;
+
+import java.io.File;
+
+import net.sf.launch4j.Builder;
+import net.sf.launch4j.BuilderException;
+import net.sf.launch4j.Log;
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.config.ConfigPersister;
+import net.sf.launch4j.config.ConfigPersisterException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Launch4jTask extends Task {
+ private File _configFile;
+ private AntConfig _config;
+
+ // System properties
+ private File tmpdir; // launch4j.tmpdir
+ private File bindir; // launch4j.bindir
+
+ // Override configFile settings
+ private File jar;
+ private File outfile;
+ private String fileVersion;
+ private String txtFileVersion;
+ private String productVersion;
+ private String txtProductVersion;
+
+ public void execute() throws BuildException {
+ try {
+ if (tmpdir != null) {
+ System.setProperty("launch4j.tmpdir", tmpdir.getPath());
+ }
+ if (bindir != null) {
+ System.setProperty("launch4j.bindir", bindir.getPath());
+ }
+ if (_configFile != null && _config != null) {
+ throw new BuildException(
+ Messages.getString("Launch4jTask.specify.config"));
+ } else if (_configFile != null) {
+ ConfigPersister.getInstance().load(_configFile);
+ Config c = ConfigPersister.getInstance().getConfig();
+ if (jar != null) {
+ c.setJar(jar);
+ }
+ if (outfile != null) {
+ c.setOutfile(outfile);
+ }
+ if (fileVersion != null) {
+ c.getVersionInfo().setFileVersion(fileVersion);
+ }
+ if (txtFileVersion != null) {
+ c.getVersionInfo().setTxtFileVersion(txtFileVersion);
+ }
+ if (productVersion != null) {
+ c.getVersionInfo().setProductVersion(productVersion);
+ }
+ if (txtProductVersion != null) {
+ c.getVersionInfo().setTxtProductVersion(txtProductVersion);
+ }
+ } else if (_config != null) {
+ _config.unwrap();
+ ConfigPersister.getInstance().setAntConfig(_config,
+ getProject().getBaseDir());
+ } else {
+ throw new BuildException(
+ Messages.getString("Launch4jTask.specify.config"));
+ }
+ final Builder b = new Builder(Log.getAntLog());
+ b.build();
+ } catch (ConfigPersisterException e) {
+ throw new BuildException(e);
+ } catch (BuilderException e) {
+ throw new BuildException(e);
+ }
+ }
+
+ public void setConfigFile(File configFile) {
+ _configFile = configFile;
+ }
+
+ public void addConfig(AntConfig config) {
+ _config = config;
+ }
+
+ public void setBindir(File bindir) {
+ this.bindir = bindir;
+ }
+
+ public void setTmpdir(File tmpdir) {
+ this.tmpdir = tmpdir;
+ }
+
+ public void setFileVersion(String fileVersion) {
+ this.fileVersion = fileVersion;
+ }
+
+ public void setJar(File jar) {
+ this.jar = jar;
+ }
+
+ public void setJarPath(String path) {
+ this.jar = new File(path);
+ }
+
+ public void setOutfile(File outfile) {
+ this.outfile = outfile;
+ }
+
+ public void setProductVersion(String productVersion) {
+ this.productVersion = productVersion;
+ }
+
+ public void setTxtFileVersion(String txtFileVersion) {
+ this.txtFileVersion = txtFileVersion;
+ }
+
+ public void setTxtProductVersion(String txtProductVersion) {
+ this.txtProductVersion = txtProductVersion;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/Messages.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/Messages.java
new file mode 100755
index 000000000..0f823f7af
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/Messages.java
@@ -0,0 +1,55 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.ant;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "net.sf.launch4j.ant.messages";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/StringWrapper.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/StringWrapper.java
new file mode 100755
index 000000000..6d38af1a5
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/StringWrapper.java
@@ -0,0 +1,67 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jul 18, 2006
+ */
+package net.sf.launch4j.ant;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class StringWrapper {
+ private String text;
+
+ public static List unwrap(List wrappers) {
+ if (wrappers.isEmpty()) {
+ return null;
+ }
+ List strings = new ArrayList(wrappers.size());
+ for (Iterator iter = wrappers.iterator(); iter.hasNext();) {
+ strings.add(iter.next().toString());
+ }
+ return strings;
+ }
+
+ public void addText(String text) {
+ this.text = text;
+ }
+
+ public String toString() {
+ return text;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/messages.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/messages.properties
new file mode 100755
index 000000000..9666633c2
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/messages.properties
@@ -0,0 +1,35 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+Launch4jTask.specify.config=Specify configFile or config
+AntConfig.duplicate.element=Duplicate element
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/messages_es.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/messages_es.properties
new file mode 100755
index 000000000..9211e8e03
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/ant/messages_es.properties
@@ -0,0 +1,35 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal, Patricio Martínez Ros
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+Launch4jTask.specify.config=Specify configFile or config
+AntConfig.duplicate.element=Duplicate element
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Binding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Binding.java
new file mode 100755
index 000000000..49c9b45ff
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Binding.java
@@ -0,0 +1,62 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 30, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public interface Binding {
+ /** Used to mark components with invalid data. */
+ public final static Color INVALID_COLOR = Color.PINK;
+
+ /** Java Bean property bound to a component */
+ public String getProperty();
+ /** Clear component, set it to the default value */
+ public void clear(IValidatable bean);
+ /** Java Bean property -> Component */
+ public void put(IValidatable bean);
+ /** Component -> Java Bean property */
+ public void get(IValidatable bean);
+ /** Mark component as valid */
+ public void markValid();
+ /** Mark component as invalid */
+ public void markInvalid();
+ /** Enable or disable the component */
+ public void setEnabled(boolean enabled);
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/BindingException.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/BindingException.java
new file mode 100755
index 000000000..15dc10cc0
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/BindingException.java
@@ -0,0 +1,52 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 30, 2005
+ */
+package net.sf.launch4j.binding;
+
+/**
+ * Signals a runtime error, a missing property in a Java Bean for example.
+ *
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class BindingException extends RuntimeException {
+ public BindingException(Throwable t) {
+ super(t);
+ }
+
+ public BindingException(String msg) {
+ super(msg);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Bindings.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Bindings.java
new file mode 100755
index 000000000..73f507e49
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Bindings.java
@@ -0,0 +1,317 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 30, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JRadioButton;
+import javax.swing.JTextArea;
+import javax.swing.JToggleButton;
+import javax.swing.text.JTextComponent;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * Creates and handles bindings.
+ *
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Bindings implements PropertyChangeListener {
+ private final Map _bindings = new HashMap();
+ private final Map _optComponents = new HashMap();
+ private boolean _modified = false;
+
+ /**
+ * Used to track component modifications.
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ String prop = evt.getPropertyName();
+ if ("AccessibleValue".equals(prop)
+ || "AccessibleText".equals(prop)
+ || "AccessibleVisibleData".equals(prop)) {
+ _modified = true;
+ }
+ }
+
+ /**
+ * Any of the components modified?
+ */
+ public boolean isModified() {
+ return _modified;
+ }
+
+ public Binding getBinding(String property) {
+ return (Binding) _bindings.get(property);
+ }
+
+ private void registerPropertyChangeListener(JComponent c) {
+ c.getAccessibleContext().addPropertyChangeListener(this);
+ }
+
+ private void registerPropertyChangeListener(JComponent[] cs) {
+ for (int i = 0; i < cs.length; i++) {
+ cs[i].getAccessibleContext().addPropertyChangeListener(this);
+ }
+ }
+
+ private boolean isPropertyNull(IValidatable bean, Binding b) {
+ try {
+ for (Iterator iter = _optComponents.keySet().iterator(); iter.hasNext();) {
+ String property = (String) iter.next();
+ if (b.getProperty().startsWith(property)) {
+ return PropertyUtils.getProperty(bean, property) == null;
+ }
+ }
+ return false;
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ /**
+ * Enables or disables all components bound to properties that begin with given prefix.
+ */
+ public void setComponentsEnabled(String prefix, boolean enabled) {
+ for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
+ Binding b = (Binding) iter.next();
+ if (b.getProperty().startsWith(prefix)) {
+ b.setEnabled(enabled);
+ }
+ }
+ }
+
+ /**
+ * Clear all components, set them to their default values.
+ * Clears the _modified flag.
+ */
+ public void clear(IValidatable bean) {
+ for (Iterator iter = _optComponents.values().iterator(); iter.hasNext();) {
+ ((Binding) iter.next()).clear(bean);
+ }
+ for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
+ ((Binding) iter.next()).clear(bean);
+ }
+ _modified = false;
+ }
+
+ /**
+ * Copies data from the Java Bean to the UI components.
+ * Clears the _modified flag.
+ */
+ public void put(IValidatable bean) {
+ for (Iterator iter = _optComponents.values().iterator(); iter.hasNext();) {
+ ((Binding) iter.next()).put(bean);
+ }
+ for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
+ Binding b = (Binding) iter.next();
+ if (isPropertyNull(bean, b)) {
+ b.clear(null);
+ } else {
+ b.put(bean);
+ }
+ }
+ _modified = false;
+ }
+
+ /**
+ * Copies data from UI components to the Java Bean and checks it's class invariants.
+ * Clears the _modified flag.
+ * @throws InvariantViolationException
+ * @throws BindingException
+ */
+ public void get(IValidatable bean) {
+ try {
+ for (Iterator iter = _optComponents.values().iterator(); iter.hasNext();) {
+ ((Binding) iter.next()).get(bean);
+ }
+ for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
+ Binding b = (Binding) iter.next();
+ if (!isPropertyNull(bean, b)) {
+ b.get(bean);
+ }
+ }
+ bean.checkInvariants();
+ for (Iterator iter = _optComponents.keySet().iterator(); iter.hasNext();) {
+ String property = (String) iter.next();
+ IValidatable component = (IValidatable) PropertyUtils.getProperty(bean,
+ property);
+ if (component != null) {
+ component.checkInvariants();
+ }
+ }
+ _modified = false; // XXX
+ } catch (InvariantViolationException e) {
+ e.setBinding(getBinding(e.getProperty()));
+ throw e;
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ private Bindings add(Binding b) {
+ if (_bindings.containsKey(b.getProperty())) {
+ throw new BindingException(Messages.getString("Bindings.duplicate.binding"));
+ }
+ _bindings.put(b.getProperty(), b);
+ return this;
+ }
+
+ /**
+ * Add an optional (nullable) Java Bean component of type clazz.
+ */
+ public Bindings addOptComponent(String property, Class clazz, JToggleButton c,
+ boolean enabledByDefault) {
+ Binding b = new OptComponentBinding(this, property, clazz, c, enabledByDefault);
+ if (_optComponents.containsKey(property)) {
+ throw new BindingException(Messages.getString("Bindings.duplicate.binding"));
+ }
+ _optComponents.put(property, b);
+ return this;
+ }
+
+ /**
+ * Add an optional (nullable) Java Bean component of type clazz.
+ */
+ public Bindings addOptComponent(String property, Class clazz, JToggleButton c) {
+ return addOptComponent(property, clazz, c, false);
+ }
+
+ /**
+ * Handles JEditorPane, JTextArea, JTextField
+ */
+ public Bindings add(String property, JTextComponent c, String defaultValue) {
+ registerPropertyChangeListener(c);
+ return add(new JTextComponentBinding(property, c, defaultValue));
+ }
+
+ /**
+ * Handles JEditorPane, JTextArea, JTextField
+ */
+ public Bindings add(String property, JTextComponent c) {
+ registerPropertyChangeListener(c);
+ return add(new JTextComponentBinding(property, c, ""));
+ }
+
+ /**
+ * Handles JToggleButton, JCheckBox
+ */
+ public Bindings add(String property, JToggleButton c, boolean defaultValue) {
+ registerPropertyChangeListener(c);
+ return add(new JToggleButtonBinding(property, c, defaultValue));
+ }
+
+ /**
+ * Handles JToggleButton, JCheckBox
+ */
+ public Bindings add(String property, JToggleButton c) {
+ registerPropertyChangeListener(c);
+ return add(new JToggleButtonBinding(property, c, false));
+ }
+
+ /**
+ * Handles JRadioButton
+ */
+ public Bindings add(String property, JRadioButton[] cs, int defaultValue) {
+ registerPropertyChangeListener(cs);
+ return add(new JRadioButtonBinding(property, cs, defaultValue));
+ }
+
+ /**
+ * Handles JRadioButton
+ */
+ public Bindings add(String property, JRadioButton[] cs) {
+ registerPropertyChangeListener(cs);
+ return add(new JRadioButtonBinding(property, cs, 0));
+ }
+
+ /**
+ * Handles JTextArea
+ */
+ public Bindings add(String property, JTextArea textArea, String defaultValue) {
+ registerPropertyChangeListener(textArea);
+ return add(new JTextComponentBinding(property, textArea, defaultValue));
+ }
+
+ /**
+ * Handles JTextArea lists
+ */
+ public Bindings add(String property, JTextArea textArea) {
+ registerPropertyChangeListener(textArea);
+ return add(new JTextAreaBinding(property, textArea));
+ }
+
+ /**
+ * Handles Optional JTextArea lists
+ */
+ public Bindings add(String property, String stateProperty,
+ JToggleButton button, JTextArea textArea) {
+ registerPropertyChangeListener(button);
+ registerPropertyChangeListener(textArea);
+ return add(new OptJTextAreaBinding(property, stateProperty, button, textArea));
+ }
+
+ /**
+ * Handles JList
+ */
+ public Bindings add(String property, JList list) {
+ registerPropertyChangeListener(list);
+ return add(new JListBinding(property, list));
+ }
+
+ /**
+ * Handles JComboBox
+ */
+ public Bindings add(String property, JComboBox combo, int defaultValue) {
+ registerPropertyChangeListener(combo);
+ return add(new JComboBoxBinding(property, combo, defaultValue));
+ }
+
+ /**
+ * Handles JComboBox
+ */
+ public Bindings add(String property, JComboBox combo) {
+ registerPropertyChangeListener(combo);
+ return add(new JComboBoxBinding(property, combo, 0));
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/IValidatable.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/IValidatable.java
new file mode 100755
index 000000000..fe0dd4862
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/IValidatable.java
@@ -0,0 +1,44 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2004-01-30
+ */
+package net.sf.launch4j.binding;
+
+/**
+ * @author Copyright (C) 2004 Grzegorz Kowal
+ */
+public interface IValidatable {
+ public void checkInvariants();
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/InvariantViolationException.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/InvariantViolationException.java
new file mode 100755
index 000000000..2f7f88b1d
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/InvariantViolationException.java
@@ -0,0 +1,67 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jun 23, 2003
+ */
+package net.sf.launch4j.binding;
+
+/**
+ * @author Copyright (C) 2003 Grzegorz Kowal
+ */
+public class InvariantViolationException extends RuntimeException {
+ private final String _property;
+ private Binding _binding;
+
+ public InvariantViolationException(String msg) {
+ super(msg);
+ _property = null;
+ }
+
+ public InvariantViolationException(String property, String msg) {
+ super(msg);
+ _property = property;
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public Binding getBinding() {
+ return _binding;
+ }
+
+ public void setBinding(Binding binding) {
+ _binding = binding;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JComboBoxBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JComboBoxBinding.java
new file mode 100755
index 000000000..81d6ff28e
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JComboBoxBinding.java
@@ -0,0 +1,119 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2007 Ian Roberts
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 10, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+
+import javax.swing.JComboBox;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * @author Copyright (C) 2007 Ian Roberts
+ */
+public class JComboBoxBinding implements Binding {
+ private final String _property;
+ private final JComboBox _combo;
+ private final int _defaultValue;
+ private final Color _validColor;
+
+ public JComboBoxBinding(String property, JComboBox combo, int defaultValue) {
+ if (property == null || combo == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")
+ || combo.getItemCount() == 0
+ || defaultValue < 0 || defaultValue >= combo.getItemCount()) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _combo = combo;
+ _defaultValue = defaultValue;
+ _validColor = combo.getBackground();
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ select(_defaultValue);
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ Integer i = (Integer) PropertyUtils.getProperty(bean, _property);
+ if (i == null) {
+ throw new BindingException(
+ Messages.getString("JComboBoxBinding.property.null"));
+ }
+ select(i.intValue());
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ PropertyUtils.setProperty(bean, _property, new Integer(_combo.getSelectedIndex()));
+ return;
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ private void select(int index) {
+ if (index < 0 || index >= _combo.getItemCount()) {
+ throw new BindingException(
+ Messages.getString("JComboBoxBinding.index.out.of.bounds"));
+ }
+ _combo.setSelectedIndex(index);
+ }
+
+ public void markValid() {
+ _combo.setBackground(_validColor);
+ _combo.requestFocusInWindow();
+ }
+
+ public void markInvalid() {
+ _combo.setBackground(Binding.INVALID_COLOR);
+ }
+
+ public void setEnabled(boolean enabled) {
+ _combo.setEnabled(enabled);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JListBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JListBinding.java
new file mode 100755
index 000000000..31dec58c1
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JListBinding.java
@@ -0,0 +1,118 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class JListBinding implements Binding {
+ private final String _property;
+ private final JList _list;
+ private final Color _validColor;
+
+ public JListBinding(String property, JList list) {
+ if (property == null || list == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _list = list;
+ _validColor = _list.getBackground();
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ _list.setModel(new DefaultListModel());
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ DefaultListModel model = new DefaultListModel();
+ List list = (List) PropertyUtils.getProperty(bean, _property);
+ if (list != null) {
+ for (Iterator iter = list.iterator(); iter.hasNext();) {
+ model.addElement(iter.next());
+ }
+ }
+ _list.setModel(model);
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ DefaultListModel model = (DefaultListModel) _list.getModel();
+ final int size = model.getSize();
+ List list = new ArrayList(size);
+ for (int i = 0; i < size; i++) {
+ list.add(model.get(i));
+ }
+ PropertyUtils.setProperty(bean, _property, list);
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void markValid() {
+ _list.setBackground(_validColor);
+ _list.requestFocusInWindow();
+ }
+
+ public void markInvalid() {
+ _list.setBackground(Binding.INVALID_COLOR);
+ }
+
+ public void setEnabled(boolean enabled) {
+ _list.setEnabled(enabled);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JRadioButtonBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JRadioButtonBinding.java
new file mode 100755
index 000000000..9d922bedf
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JRadioButtonBinding.java
@@ -0,0 +1,146 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 10, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+
+import javax.swing.JRadioButton;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class JRadioButtonBinding implements Binding {
+ private final String _property;
+ private final JRadioButton[] _buttons;
+ private final int _defaultValue;
+ private final Color _validColor;
+
+ public JRadioButtonBinding(String property, JRadioButton[] buttons, int defaultValue) {
+ if (property == null || buttons == null) {
+ throw new NullPointerException();
+ }
+ for (int i = 0; i < buttons.length; i++) {
+ if (buttons[i] == null) {
+ throw new NullPointerException();
+ }
+ }
+ if (property.equals("")
+ || buttons.length == 0
+ || defaultValue < 0 || defaultValue >= buttons.length) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _buttons = buttons;
+ _defaultValue = defaultValue;
+ _validColor = buttons[0].getBackground();
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ select(_defaultValue);
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ Integer i = (Integer) PropertyUtils.getProperty(bean, _property);
+ if (i == null) {
+ throw new BindingException(
+ Messages.getString("JRadioButtonBinding.property.null"));
+ }
+ select(i.intValue());
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ for (int i = 0; i < _buttons.length; i++) {
+ if (_buttons[i].isSelected()) {
+ PropertyUtils.setProperty(bean, _property, new Integer(i));
+ return;
+ }
+ }
+ throw new BindingException(
+ Messages.getString("JRadioButtonBinding.nothing.selected"));
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ private void select(int index) {
+ if (index < 0 || index >= _buttons.length) {
+ throw new BindingException(
+ Messages.getString("JRadioButtonBinding.index.out.of.bounds"));
+ }
+ _buttons[index].setSelected(true);
+ }
+
+ public void markValid() {
+ for (int i = 0; i < _buttons.length; i++) {
+ if (_buttons[i].isSelected()) {
+ _buttons[i].setBackground(_validColor);
+ _buttons[i].requestFocusInWindow();
+ return;
+ }
+ }
+ throw new BindingException(
+ Messages.getString("JRadioButtonBinding.nothing.selected"));
+ }
+
+ public void markInvalid() {
+ for (int i = 0; i < _buttons.length; i++) {
+ if (_buttons[i].isSelected()) {
+ _buttons[i].setBackground(Binding.INVALID_COLOR);
+ return;
+ }
+ }
+ throw new BindingException(
+ Messages.getString("JRadioButtonBinding.nothing.selected"));
+ }
+
+ public void setEnabled(boolean enabled) {
+ for (int i = 0; i < _buttons.length; i++) {
+ _buttons[i].setEnabled(enabled);
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JTextAreaBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JTextAreaBinding.java
new file mode 100755
index 000000000..d4e8a2c65
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JTextAreaBinding.java
@@ -0,0 +1,123 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jun 14, 2006
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JTextArea;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class JTextAreaBinding implements Binding {
+ private final String _property;
+ private final JTextArea _textArea;
+ private final Color _validColor;
+
+ public JTextAreaBinding(String property, JTextArea textArea) {
+ if (property == null || textArea == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _textArea = textArea;
+ _validColor = _textArea.getBackground();
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ put(bean);
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ List list = (List) PropertyUtils.getProperty(bean, _property);
+ StringBuffer sb = new StringBuffer();
+ if (list != null) {
+ for (int i = 0; i < list.size(); i++) {
+ sb.append(list.get(i));
+ if (i < list.size() - 1) {
+ sb.append("\n");
+ }
+ }
+ }
+ _textArea.setText(sb.toString());
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ String text = _textArea.getText();
+ if (!text.equals("")) {
+ String[] items = text.split("\n");
+ List list = new ArrayList();
+ for (int i = 0; i < items.length; i++) {
+ list.add(items[i]);
+ }
+ PropertyUtils.setProperty(bean, _property, list);
+ } else {
+ PropertyUtils.setProperty(bean, _property, null);
+ }
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void markValid() {
+ _textArea.setBackground(_validColor);
+ _textArea.requestFocusInWindow();
+ }
+
+ public void markInvalid() {
+ _textArea.setBackground(Binding.INVALID_COLOR);
+ }
+
+ public void setEnabled(boolean enabled) {
+ _textArea.setEnabled(enabled);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JTextComponentBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JTextComponentBinding.java
new file mode 100755
index 000000000..6b0dd1b0b
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JTextComponentBinding.java
@@ -0,0 +1,108 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 30, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+
+import javax.swing.text.JTextComponent;
+
+import org.apache.commons.beanutils.BeanUtils;
+
+/**
+ * Handles JEditorPane, JTextArea, JTextField
+ *
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class JTextComponentBinding implements Binding {
+ private final String _property;
+ private final JTextComponent _textComponent;
+ private final String _defaultValue;
+ private final Color _validColor;
+
+ public JTextComponentBinding(String property, JTextComponent textComponent,
+ String defaultValue) {
+ if (property == null || textComponent == null || defaultValue == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _textComponent = textComponent;
+ _defaultValue = defaultValue;
+ _validColor = _textComponent.getBackground();
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ _textComponent.setText(_defaultValue);
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ String s = BeanUtils.getProperty(bean, _property);
+ // XXX displays zeros as blank
+ _textComponent.setText(s != null && !s.equals("0") ? s : "");
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ BeanUtils.setProperty(bean, _property, _textComponent.getText());
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void markValid() {
+ _textComponent.setBackground(_validColor);
+ _textComponent.requestFocusInWindow();
+ }
+
+ public void markInvalid() {
+ _textComponent.setBackground(Binding.INVALID_COLOR);
+ }
+
+ public void setEnabled(boolean enabled) {
+ _textComponent.setEnabled(enabled);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JToggleButtonBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JToggleButtonBinding.java
new file mode 100755
index 000000000..a7055cccc
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/JToggleButtonBinding.java
@@ -0,0 +1,108 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 30, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+
+import javax.swing.JToggleButton;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * Handles JToggleButton, JCheckBox
+ *
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class JToggleButtonBinding implements Binding {
+ private final String _property;
+ private final JToggleButton _button;
+ private final boolean _defaultValue;
+ private final Color _validColor;
+
+ public JToggleButtonBinding(String property, JToggleButton button,
+ boolean defaultValue) {
+ if (property == null || button == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _button = button;
+ _defaultValue = defaultValue;
+ _validColor = _button.getBackground();
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ _button.setSelected(_defaultValue);
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ Boolean b = (Boolean) PropertyUtils.getProperty(bean, _property);
+ _button.setSelected(b != null && b.booleanValue());
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ PropertyUtils.setProperty(bean, _property,
+ Boolean.valueOf(_button.isSelected()));
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void markValid() {
+ _button.setBackground(_validColor);
+ _button.requestFocusInWindow();
+ }
+
+ public void markInvalid() {
+ _button.setBackground(Binding.INVALID_COLOR);
+ }
+
+ public void setEnabled(boolean enabled) {
+ _button.setEnabled(enabled);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Messages.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Messages.java
new file mode 100755
index 000000000..91ddff2b1
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Messages.java
@@ -0,0 +1,78 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.binding;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "net.sf.launch4j.binding.messages";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+ private static final MessageFormat FORMATTER = new MessageFormat("");
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ public static String getString(String key, String arg0) {
+ return getString(key, new Object[] {arg0});
+ }
+
+ public static String getString(String key, String arg0, String arg1) {
+ return getString(key, new Object[] {arg0, arg1});
+ }
+
+ public static String getString(String key, String arg0, String arg1, String arg2) {
+ return getString(key, new Object[] {arg0, arg1, arg2});
+ }
+
+ public static String getString(String key, Object[] args) {
+ try {
+ FORMATTER.applyPattern(RESOURCE_BUNDLE.getString(key));
+ return FORMATTER.format(args);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/OptComponentBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/OptComponentBinding.java
new file mode 100755
index 000000000..b573da628
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/OptComponentBinding.java
@@ -0,0 +1,119 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 11, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+
+import javax.swing.JToggleButton;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class OptComponentBinding implements Binding, ActionListener {
+ private final Bindings _bindings;
+ private final String _property;
+ private final Class _clazz;
+ private final JToggleButton _button;
+ private final boolean _enabledByDefault;
+
+ public OptComponentBinding(Bindings bindings, String property, Class clazz,
+ JToggleButton button, boolean enabledByDefault) {
+ if (property == null || clazz == null || button == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")) {
+ throw new IllegalArgumentException();
+ }
+ if (!Arrays.asList(clazz.getInterfaces()).contains(IValidatable.class)) {
+ throw new IllegalArgumentException(
+ Messages.getString("OptComponentBinding.must.implement")
+ + IValidatable.class);
+ }
+ _bindings = bindings;
+ _property = property;
+ _clazz = clazz;
+ _button = button;
+ _button.addActionListener(this);
+ _enabledByDefault = enabledByDefault;
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ _button.setSelected(_enabledByDefault);
+ updateComponents();
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ Object component = PropertyUtils.getProperty(bean, _property);
+ _button.setSelected(component != null);
+ updateComponents();
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ PropertyUtils.setProperty(bean, _property, _button.isSelected()
+ ? _clazz.newInstance() : null);
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void markValid() {}
+
+ public void markInvalid() {}
+
+ public void setEnabled(boolean enabled) {} // XXX implement?
+
+ public void actionPerformed(ActionEvent e) {
+ updateComponents();
+ }
+
+ private void updateComponents() {
+ _bindings.setComponentsEnabled(_property, _button.isSelected());
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/OptJTextAreaBinding.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/OptJTextAreaBinding.java
new file mode 100755
index 000000000..3cea776d7
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/OptJTextAreaBinding.java
@@ -0,0 +1,141 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Sep 3, 2005
+ */
+package net.sf.launch4j.binding;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JTextArea;
+import javax.swing.JToggleButton;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class OptJTextAreaBinding implements Binding, ActionListener {
+ private final String _property;
+ private final String _stateProperty;
+ private final JToggleButton _button;
+ private final JTextArea _textArea;
+ private final Color _validColor;
+
+ public OptJTextAreaBinding(String property, String stateProperty,
+ JToggleButton button, JTextArea textArea) {
+ if (property == null || button == null || textArea == null) {
+ throw new NullPointerException();
+ }
+ if (property.equals("")) {
+ throw new IllegalArgumentException();
+ }
+ _property = property;
+ _stateProperty = stateProperty;
+ _button = button;
+ _textArea = textArea;
+ _validColor = _textArea.getBackground();
+ button.addActionListener(this);
+ }
+
+ public String getProperty() {
+ return _property;
+ }
+
+ public void clear(IValidatable bean) {
+ put(bean);
+ }
+
+ public void put(IValidatable bean) {
+ try {
+ boolean selected = "true".equals(BeanUtils.getProperty(bean,
+ _stateProperty));
+ _button.setSelected(selected);
+ _textArea.setEnabled(selected);
+ List list = (List) PropertyUtils.getProperty(bean, _property);
+ StringBuffer sb = new StringBuffer();
+ if (list != null) {
+ for (int i = 0; i < list.size(); i++) {
+ sb.append(list.get(i));
+ if (i < list.size() - 1) {
+ sb.append("\n");
+ }
+ }
+ }
+ _textArea.setText(sb.toString());
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void get(IValidatable bean) {
+ try {
+ String text = _textArea.getText();
+ if (_button.isSelected() && !text.equals("")) {
+ String[] items = text.split("\n");
+ List list = new ArrayList();
+ for (int i = 0; i < items.length; i++) {
+ list.add(items[i]);
+ }
+ PropertyUtils.setProperty(bean, _property, list);
+ } else {
+ PropertyUtils.setProperty(bean, _property, null);
+ }
+ } catch (Exception e) {
+ throw new BindingException(e);
+ }
+ }
+
+ public void markValid() {
+ _textArea.setBackground(_validColor);
+ _textArea.requestFocusInWindow();
+ }
+
+ public void markInvalid() {
+ _textArea.setBackground(Binding.INVALID_COLOR);
+ }
+
+ public void setEnabled(boolean enabled) {
+ _textArea.setEnabled(enabled);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ _textArea.setEnabled(_button.isSelected());
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Validator.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Validator.java
new file mode 100755
index 000000000..88ea67c33
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/Validator.java
@@ -0,0 +1,259 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2004-01-30
+ */
+package net.sf.launch4j.binding;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sf.launch4j.Util;
+import net.sf.launch4j.config.ConfigPersister;
+
+/**
+ * @author Copyright (C) 2004 Grzegorz Kowal
+ */
+public class Validator {
+ public static final String ALPHANUMERIC_PATTERN = "[\\w]*?";
+ public static final String ALPHA_PATTERN = "[\\w&&\\D]*?";
+ public static final String NUMERIC_PATTERN = "[\\d]*?";
+ public static final String PATH_PATTERN = "[\\w|[ .,:\\-/\\\\]]*?";
+
+ public static final int MAX_STR = 128;
+ public static final int MAX_PATH = 260;
+ public static final int MAX_BIG_STR = 8192; // or 16384;
+ public static final int MAX_ARGS = 32767 - 2048;
+
+ private Validator() {}
+
+ public static boolean isEmpty(String s) {
+ return s == null || s.equals("");
+ }
+
+ public static void checkNotNull(Object o, String property, String name) {
+ if (o == null) {
+ signalViolation(property,
+ Messages.getString("Validator.empty.field", name));
+ }
+ }
+
+ public static void checkString(String s, int maxLength, String property,
+ String name) {
+ if (s == null || s.length() == 0) {
+ signalViolation(property,
+ Messages.getString("Validator.empty.field", name));
+ }
+ if (s.length() > maxLength) {
+ signalLengthViolation(property, name, maxLength);
+ }
+ }
+
+ public static void checkOptStrings(List strings, int maxLength, int totalMaxLength,
+ String property, String name) {
+ if (strings == null) {
+ return;
+ }
+ int totalLength = 0;
+ for (Iterator iter = strings.iterator(); iter.hasNext();) {
+ String s = (String) iter.next();
+ checkString(s, maxLength, property, name);
+ totalLength += s.length();
+ if (totalLength > totalMaxLength) {
+ signalLengthViolation(property, name, totalMaxLength);
+ }
+ }
+ }
+
+ public static void checkString(String s, int maxLength, String pattern,
+ String property, String name) {
+ checkString(s, maxLength, property, name);
+ if (!s.matches(pattern)) {
+ signalViolation(property,
+ Messages.getString("Validator.invalid.data", name));
+ }
+ }
+
+ public static void checkOptStrings(List strings, int maxLength, int totalMaxLength,
+ String pattern, String property, String name, String msg) {
+ if (strings == null) {
+ return;
+ }
+ int totalLength = 0;
+ for (Iterator iter = strings.iterator(); iter.hasNext();) {
+ String s = (String) iter.next();
+ checkString(s, maxLength, property, name);
+ if (!s.matches(pattern)) {
+ signalViolation(property, msg != null
+ ? msg
+ : Messages.getString("Validator.invalid.data", name));
+ }
+ totalLength += s.length();
+ if (totalLength > totalMaxLength) {
+ signalLengthViolation(property, name, totalMaxLength);
+ }
+ }
+ }
+
+ public static void checkOptString(String s, int maxLength, String property,
+ String name) {
+ if (s == null || s.length() == 0) {
+ return;
+ }
+ if (s.length() > maxLength) {
+ signalLengthViolation(property, name, maxLength);
+ }
+ }
+
+ public static void checkOptString(String s, int maxLength, String pattern,
+ String property, String name) {
+ if (s == null || s.length() == 0) {
+ return;
+ }
+ if (s.length() > maxLength) {
+ signalLengthViolation(property, name, maxLength);
+ }
+ if (!s.matches(pattern)) {
+ signalViolation(property,
+ Messages.getString("Validator.invalid.data", name));
+ }
+ }
+
+ public static void checkRange(int value, int min, int max,
+ String property, String name) {
+ if (value < min || value > max) {
+ signalViolation(property,
+ Messages.getString("Validator.must.be.in.range", name,
+ String.valueOf(min), String.valueOf(max)));
+ }
+ }
+
+ public static void checkRange(char value, char min, char max,
+ String property, String name) {
+ if (value < min || value > max) {
+ signalViolation(property, Messages.getString("Validator.must.be.in.range",
+ name, String.valueOf(min), String.valueOf(max)));
+ }
+ }
+
+ public static void checkMin(int value, int min, String property, String name) {
+ if (value < min) {
+ signalViolation(property,
+ Messages.getString("Validator.must.be.at.least", name,
+ String.valueOf(min)));
+ }
+ }
+
+ public static void checkIn(String s, String[] strings, String property,
+ String name) {
+ if (isEmpty(s)) {
+ signalViolation(property,
+ Messages.getString("Validator.empty.field", name));
+ }
+ List list = Arrays.asList(strings);
+ if (!list.contains(s)) {
+ signalViolation(property,
+ Messages.getString("Validator.invalid.option", name, list.toString()));
+ }
+ }
+
+ public static void checkTrue(boolean condition, String property, String msg) {
+ if (!condition) {
+ signalViolation(property, msg);
+ }
+ }
+
+ public static void checkFalse(boolean condition, String property, String msg) {
+ if (condition) {
+ signalViolation(property, msg);
+ }
+ }
+
+ public static void checkElementsNotNullUnique(Collection c, String property,
+ String msg) {
+ if (c.contains(null)
+ || new HashSet(c).size() != c.size()) {
+ signalViolation(property,
+ Messages.getString("Validator.already.exists", msg));
+ }
+ }
+
+ public static void checkElementsUnique(Collection c, String property, String msg) {
+ if (new HashSet(c).size() != c.size()) {
+ signalViolation(property,
+ Messages.getString("Validator.already.exists", msg));
+ }
+ }
+
+ public static void checkFile(File f, String property, String fileDescription) {
+ File cfgPath = ConfigPersister.getInstance().getConfigPath();
+ if (f == null
+ || f.getPath().equals("")
+ || (!f.exists() && !Util.getAbsoluteFile(cfgPath, f).exists())) {
+ signalViolation(property,
+ Messages.getString("Validator.doesnt.exist", fileDescription));
+ }
+ }
+
+ public static void checkOptFile(File f, String property, String fileDescription) {
+ if (f != null && f.getPath().length() > 0) {
+ checkFile(f, property, fileDescription);
+ }
+ }
+
+ public static void checkRelativeWinPath(String path, String property, String msg) {
+ if (path == null
+ || path.equals("")
+ || path.startsWith("/")
+ || path.startsWith("\\")
+ || path.indexOf(':') != -1) {
+ signalViolation(property, msg);
+ }
+ }
+
+ public static void signalLengthViolation(String property, String name,
+ int maxLength) {
+ signalViolation(property,
+ Messages.getString("Validator.exceeds.max.length", name,
+ String.valueOf(maxLength)));
+ }
+
+ public static void signalViolation(String property, String msg) {
+ throw new InvariantViolationException(property, msg);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/messages.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/messages.properties
new file mode 100755
index 000000000..adb5a8886
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/messages.properties
@@ -0,0 +1,52 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+OptComponentBinding.must.implement=Optional component must implement
+
+Validator.empty.field=Enter: {0}
+Validator.invalid.data=Invalid data: {0}
+Validator.must.be.in.range={0} must be in range [{1}-{2}]
+Validator.must.be.at.least={0} must be at least
+Validator.already.exists={0} already exists.
+Validator.doesnt.exist={0} doesn''t exist.
+Validator.exceeds.max.length={0} exceeds the maximum length of {1} characters.
+Validator.invalid.option={0} must be one of [{1}]
+
+Bindings.duplicate.binding=Duplicate binding
+
+JRadioButtonBinding.property.null=Property is null
+JRadioButtonBinding.nothing.selected=Nothing selected
+JRadioButtonBinding.index.out.of.bounds=Button index out of bounds
+
+JComboBoxBinding.property.null=Property is null
+JComboBoxBinding.index.out.of.bounds=Combo box index out of bounds
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/messages_es.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/messages_es.properties
new file mode 100755
index 000000000..e2e50fcb4
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/binding/messages_es.properties
@@ -0,0 +1,51 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal, Patricio Martínez Ros
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+OptComponentBinding.must.implement=El componente opcional debe ser implementado
+
+Validator.empty.field=Introduzca: {0}
+Validator.invalid.data=Dato no válido: {0}
+Validator.must.be.in.range={0} debe estar en el rango [{1}-{2}]
+Validator.must.be.at.least={0} deb ser al menos
+Validator.already.exists={0} ya existe.
+Validator.doesnt.exist={0} no existe.
+Validator.exceeds.max.length={0} excede la longitud máxima de {1} caracteres.
+Validator.invalid.option={0} must be one of [{1}]
+
+Bindings.duplicate.binding=Binding duplicado
+
+JRadioButtonBinding.property.null=La propiedad es nula
+JRadioButtonBinding.nothing.selected=Nada seleccionado
+JRadioButtonBinding.index.out.of.bounds=Índice de botón fuera de límite
+JComboBoxBinding.property.null=Property is null
+JComboBoxBinding.index.out.of.bounds=Combo box index out of bounds
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ClassPath.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ClassPath.java
new file mode 100755
index 000000000..da7dbd6c4
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ClassPath.java
@@ -0,0 +1,87 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.config;
+
+import java.util.List;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class ClassPath implements IValidatable {
+ private String mainClass;
+ private List paths;
+
+ public void checkInvariants() {
+ Validator.checkString(mainClass, Validator.MAX_PATH, "mainClass",
+ Messages.getString("ClassPath.mainClass"));
+ Validator.checkOptStrings(paths,
+ Validator.MAX_PATH,
+ Validator.MAX_BIG_STR,
+ "paths",
+ Messages.getString("ClassPath.path"));
+ }
+
+ public String getMainClass() {
+ return mainClass;
+ }
+
+ public void setMainClass(String mainClass) {
+ this.mainClass = mainClass;
+ }
+
+ public List getPaths() {
+ return paths;
+ }
+
+ public void setPaths(List paths) {
+ this.paths = paths;
+ }
+
+ public String getPathsString() {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < paths.size(); i++) {
+ sb.append(paths.get(i));
+ if (i < paths.size() - 1) {
+ sb.append(';');
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Config.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Config.java
new file mode 100755
index 000000000..27633bfb4
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Config.java
@@ -0,0 +1,396 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 21, 2005
+ */
+package net.sf.launch4j.config;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Config implements IValidatable {
+
+ // 1.x config properties_____________________________________________________________
+ public static final String HEADER = "header";
+ public static final String JAR = "jar";
+ public static final String OUTFILE = "outfile";
+ public static final String ERR_TITLE = "errTitle";
+ public static final String JAR_ARGS = "jarArgs";
+ public static final String CHDIR = "chdir";
+ public static final String CUSTOM_PROC_NAME = "customProcName";
+ public static final String STAY_ALIVE = "stayAlive";
+ public static final String ICON = "icon";
+
+ // __________________________________________________________________________________
+ public static final String DOWNLOAD_URL = "http://java.com/download";
+
+ public static final String GUI_HEADER = "gui";
+ public static final String CONSOLE_HEADER = "console";
+
+ private static final String[] HEADER_TYPES = new String[] { GUI_HEADER,
+ CONSOLE_HEADER };
+
+ private static final String[] PRIORITY_CLASS_NAMES = new String[] { "normal",
+ "idle",
+ "high" };
+
+ private static final int[] PRIORITY_CLASSES = new int[] { 0x00000020,
+ 0x00000040,
+ 0x00000080 };
+
+ private boolean dontWrapJar;
+ private String headerType = GUI_HEADER;
+ private List headerObjects;
+ private List libs;
+ private File jar;
+ private File outfile;
+
+ // Runtime header configuration
+ private String errTitle;
+ private String cmdLine;
+ private String chdir;
+ private String priority;
+ private String downloadUrl;
+ private String supportUrl;
+ private boolean customProcName;
+ private boolean stayAlive;
+ private File manifest;
+ private File icon;
+ private List variables;
+ private SingleInstance singleInstance;
+ private ClassPath classPath;
+ private Jre jre;
+ private Splash splash;
+ private VersionInfo versionInfo;
+ private Msg messages;
+
+ public void checkInvariants() {
+ Validator.checkTrue(outfile != null && outfile.getPath().endsWith(".exe"),
+ "outfile", Messages.getString("Config.specify.output.exe"));
+ if (dontWrapJar) {
+ if (jar != null && !jar.getPath().equals("")) {
+ Validator.checkRelativeWinPath(jar.getPath(), "jar",
+ Messages.getString("Config.application.jar.path"));
+ } else {
+ Validator.checkTrue(classPath != null, "classPath",
+ Messages.getString("ClassPath.or.jar"));
+ }
+ } else {
+ Validator.checkFile(jar, "jar",
+ Messages.getString("Config.application.jar"));
+ }
+ if (!Validator.isEmpty(chdir)) {
+ Validator.checkRelativeWinPath(chdir, "chdir",
+ Messages.getString("Config.chdir.relative"));
+ Validator.checkFalse(chdir.toLowerCase().equals("true")
+ || chdir.toLowerCase().equals("false"),
+ "chdir", Messages.getString("Config.chdir.path"));
+ }
+ Validator.checkOptFile(manifest, "manifest", Messages.getString("Config.manifest"));
+ Validator.checkOptFile(icon, "icon", Messages.getString("Config.icon"));
+ Validator.checkOptString(cmdLine, Validator.MAX_BIG_STR, "jarArgs",
+ Messages.getString("Config.jar.arguments"));
+ Validator.checkOptString(errTitle, Validator.MAX_STR, "errTitle",
+ Messages.getString("Config.error.title"));
+ Validator.checkOptString(downloadUrl, 256,
+ "downloadUrl", Messages.getString("Config.download.url"));
+ Validator.checkOptString(supportUrl, 256,
+ "supportUrl", Messages.getString("Config.support.url"));
+ Validator.checkIn(getHeaderType(), HEADER_TYPES, "headerType",
+ Messages.getString("Config.header.type"));
+ Validator.checkFalse(getHeaderType().equals(CONSOLE_HEADER) && splash != null,
+ "headerType",
+ Messages.getString("Config.splash.not.impl.by.console.hdr"));
+ Validator.checkOptStrings(variables,
+ Validator.MAX_ARGS,
+ Validator.MAX_ARGS,
+ "[^=%\t]+=[^=\t]+",
+ "variables",
+ Messages.getString("Config.variables"),
+ Messages.getString("Config.variables.err"));
+ Validator.checkIn(getPriority(), PRIORITY_CLASS_NAMES, "priority",
+ Messages.getString("Config.priority"));
+ jre.checkInvariants();
+ }
+
+ public void validate() {
+ checkInvariants();
+ if (classPath != null) {
+ classPath.checkInvariants();
+ }
+ if (splash != null) {
+ splash.checkInvariants();
+ }
+ if (versionInfo != null) {
+ versionInfo.checkInvariants();
+ }
+ }
+
+ /** Change current directory to EXE location. */
+ public String getChdir() {
+ return chdir;
+ }
+
+ public void setChdir(String chdir) {
+ this.chdir = chdir;
+ }
+
+ /** Constant command line arguments passed to the application. */
+ public String getCmdLine() {
+ return cmdLine;
+ }
+
+ public void setCmdLine(String cmdLine) {
+ this.cmdLine = cmdLine;
+ }
+
+ /** Optional, error message box title. */
+ public String getErrTitle() {
+ return errTitle;
+ }
+
+ public void setErrTitle(String errTitle) {
+ this.errTitle = errTitle;
+ }
+
+ /** launch4j header file. */
+ public String getHeaderType() {
+ return headerType.toLowerCase();
+ }
+
+ public void setHeaderType(String headerType) {
+ this.headerType = headerType;
+ }
+
+ /** launch4j header file index - used by GUI. */
+ public int getHeaderTypeIndex() {
+ int x = Arrays.asList(HEADER_TYPES).indexOf(getHeaderType());
+ return x != -1 ? x : 0;
+ }
+
+ public void setHeaderTypeIndex(int headerTypeIndex) {
+ headerType = HEADER_TYPES[headerTypeIndex];
+ }
+
+ public boolean isCustomHeaderObjects() {
+ return headerObjects != null && !headerObjects.isEmpty();
+ }
+
+ public List getHeaderObjects() {
+ return isCustomHeaderObjects() ? headerObjects
+ : getHeaderType().equals(GUI_HEADER)
+ ? LdDefaults.GUI_HEADER_OBJECTS
+ : LdDefaults.CONSOLE_HEADER_OBJECTS;
+ }
+
+ public void setHeaderObjects(List headerObjects) {
+ this.headerObjects = headerObjects;
+ }
+
+ public boolean isCustomLibs() {
+ return libs != null && !libs.isEmpty();
+ }
+
+ public List getLibs() {
+ return isCustomLibs() ? libs : LdDefaults.LIBS;
+ }
+
+ public void setLibs(List libs) {
+ this.libs = libs;
+ }
+
+ /** Wrapper's manifest for User Account Control. */
+ public File getManifest() {
+ return manifest;
+ }
+
+ public void setManifest(File manifest) {
+ this.manifest = manifest;
+ }
+
+ /** ICO file. */
+ public File getIcon() {
+ return icon;
+ }
+
+ public void setIcon(File icon) {
+ this.icon = icon;
+ }
+
+ /** Jar to wrap. */
+ public File getJar() {
+ return jar;
+ }
+
+ public void setJar(File jar) {
+ this.jar = jar;
+ }
+
+ public List getVariables() {
+ return variables;
+ }
+
+ public void setVariables(List variables) {
+ this.variables = variables;
+ }
+
+ public ClassPath getClassPath() {
+ return classPath;
+ }
+
+ public void setClassPath(ClassPath classpath) {
+ this.classPath = classpath;
+ }
+
+ /** JRE configuration */
+ public Jre getJre() {
+ return jre;
+ }
+
+ public void setJre(Jre jre) {
+ this.jre = jre;
+ }
+
+ /** Output EXE file. */
+ public File getOutfile() {
+ return outfile;
+ }
+
+ public void setOutfile(File outfile) {
+ this.outfile = outfile;
+ }
+
+ /** Custom process name as the output EXE file name. */
+ public boolean isCustomProcName() {
+ return customProcName;
+ }
+
+ public void setCustomProcName(boolean customProcName) {
+ this.customProcName = customProcName;
+ }
+
+ /** Splash screen configuration. */
+ public Splash getSplash() {
+ return splash;
+ }
+
+ public void setSplash(Splash splash) {
+ this.splash = splash;
+ }
+
+ /** Stay alive after launching the application. */
+ public boolean isStayAlive() {
+ return stayAlive;
+ }
+
+ public void setStayAlive(boolean stayAlive) {
+ this.stayAlive = stayAlive;
+ }
+
+ public VersionInfo getVersionInfo() {
+ return versionInfo;
+ }
+
+ public void setVersionInfo(VersionInfo versionInfo) {
+ this.versionInfo = versionInfo;
+ }
+
+ public boolean isDontWrapJar() {
+ return dontWrapJar;
+ }
+
+ public void setDontWrapJar(boolean dontWrapJar) {
+ this.dontWrapJar = dontWrapJar;
+ }
+
+ public int getPriorityIndex() {
+ int x = Arrays.asList(PRIORITY_CLASS_NAMES).indexOf(getPriority());
+ return x != -1 ? x : 0;
+ }
+
+ public void setPriorityIndex(int x) {
+ priority = PRIORITY_CLASS_NAMES[x];
+ }
+
+ public String getPriority() {
+ return Validator.isEmpty(priority) ? PRIORITY_CLASS_NAMES[0] : priority;
+ }
+
+ public void setPriority(String priority) {
+ this.priority = priority;
+ }
+
+ public int getPriorityClass() {
+ return PRIORITY_CLASSES[getPriorityIndex()];
+ }
+
+ public String getDownloadUrl() {
+ return downloadUrl == null ? DOWNLOAD_URL : downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getSupportUrl() {
+ return supportUrl;
+ }
+
+ public void setSupportUrl(String supportUrl) {
+ this.supportUrl = supportUrl;
+ }
+
+ public Msg getMessages() {
+ return messages;
+ }
+
+ public void setMessages(Msg messages) {
+ this.messages = messages;
+ }
+
+ public SingleInstance getSingleInstance() {
+ return singleInstance;
+ }
+
+ public void setSingleInstance(SingleInstance singleInstance) {
+ this.singleInstance = singleInstance;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ConfigPersister.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ConfigPersister.java
new file mode 100755
index 000000000..43daf8681
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ConfigPersister.java
@@ -0,0 +1,249 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 22, 2005
+ */
+package net.sf.launch4j.config;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import net.sf.launch4j.Util;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class ConfigPersister {
+
+ private static final ConfigPersister _instance = new ConfigPersister();
+
+ private final XStream _xstream;
+ private Config _config;
+ private File _configPath;
+
+ private ConfigPersister() {
+ _xstream = new XStream(new DomDriver());
+ _xstream.alias("launch4jConfig", Config.class);
+ _xstream.alias("classPath", ClassPath.class);
+ _xstream.alias("jre", Jre.class);
+ _xstream.alias("splash", Splash.class);
+ _xstream.alias("versionInfo", VersionInfo.class);
+
+ _xstream.addImplicitCollection(Config.class, "headerObjects", "obj",
+ String.class);
+ _xstream.addImplicitCollection(Config.class, "libs", "lib", String.class);
+ _xstream.addImplicitCollection(Config.class, "variables", "var", String.class);
+ _xstream.addImplicitCollection(ClassPath.class, "paths", "cp", String.class);
+ _xstream.addImplicitCollection(Jre.class, "options", "opt", String.class);
+ }
+
+ public static ConfigPersister getInstance() {
+ return _instance;
+ }
+
+ public Config getConfig() {
+ return _config;
+ }
+
+ public File getConfigPath() {
+ return _configPath;
+ }
+
+ public File getOutputPath() throws IOException {
+ if (_config.getOutfile().isAbsolute()) {
+ return _config.getOutfile().getParentFile();
+ }
+ File parent = _config.getOutfile().getParentFile();
+ return (parent != null) ? new File(_configPath, parent.getPath()) : _configPath;
+ }
+
+ public File getOutputFile() throws IOException {
+ return _config.getOutfile().isAbsolute()
+ ? _config.getOutfile()
+ : new File(getOutputPath(), _config.getOutfile().getName());
+ }
+
+ public void createBlank() {
+ _config = new Config();
+ _config.setJre(new Jre());
+ _configPath = null;
+ }
+
+ public void setAntConfig(Config c, File basedir) {
+ _config = c;
+ _configPath = basedir;
+ }
+
+ public void load(File f) throws ConfigPersisterException {
+ try {
+ FileReader r = new FileReader(f);
+ char[] buf = new char[(int) f.length()];
+ r.read(buf);
+ r.close();
+ // Convert 2.x config to 3.x
+ String s = String.valueOf(buf)
+ .replaceAll("0<", "gui<")
+ .replaceAll("1<", "console<")
+ .replaceAll("jarArgs>", "cmdLine>")
+ .replaceAll("", "")
+ .replaceAll("args>", "opt>")
+ .replaceAll("", "")
+ .replaceAll("false",
+ "" + Jre.JDK_PREFERENCE_PREFER_JRE + "")
+ .replaceAll("true",
+ "" + Jre.JDK_PREFERENCE_JRE_ONLY + "")
+ .replaceAll("0", "")
+ .replaceAll("0", "");
+ _config = (Config) _xstream.fromXML(s);
+ setConfigPath(f);
+ } catch (Exception e) {
+ throw new ConfigPersisterException(e);
+ }
+ }
+
+ /**
+ * Imports launch4j 1.x.x config file.
+ */
+ public void loadVersion1(File f) throws ConfigPersisterException {
+ try {
+ Props props = new Props(f);
+ _config = new Config();
+ String header = props.getProperty(Config.HEADER);
+ _config.setHeaderType(header == null
+ || header.toLowerCase().equals("guihead.bin") ? Config.GUI_HEADER
+ : Config.CONSOLE_HEADER);
+ _config.setJar(props.getFile(Config.JAR));
+ _config.setOutfile(props.getFile(Config.OUTFILE));
+ _config.setJre(new Jre());
+ _config.getJre().setPath(props.getProperty(Jre.PATH));
+ _config.getJre().setMinVersion(props.getProperty(Jre.MIN_VERSION));
+ _config.getJre().setMaxVersion(props.getProperty(Jre.MAX_VERSION));
+ String args = props.getProperty(Jre.ARGS);
+ if (args != null) {
+ List jreOptions = new ArrayList();
+ jreOptions.add(args);
+ _config.getJre().setOptions(jreOptions);
+ }
+ _config.setCmdLine(props.getProperty(Config.JAR_ARGS));
+ _config.setChdir("true".equals(props.getProperty(Config.CHDIR))
+ ? "." : null);
+ _config.setCustomProcName("true".equals(
+ props.getProperty("setProcName"))); // 1.x
+ _config.setStayAlive("true".equals(props.getProperty(Config.STAY_ALIVE)));
+ _config.setErrTitle(props.getProperty(Config.ERR_TITLE));
+ _config.setIcon(props.getFile(Config.ICON));
+ File splashFile = props.getFile(Splash.SPLASH_FILE);
+ if (splashFile != null) {
+ _config.setSplash(new Splash());
+ _config.getSplash().setFile(splashFile);
+ String waitfor = props.getProperty("waitfor"); // 1.x
+ _config.getSplash().setWaitForWindow(waitfor != null
+ && !waitfor.equals(""));
+ String splashTimeout = props.getProperty(Splash.TIMEOUT);
+ if (splashTimeout != null) {
+ _config.getSplash().setTimeout(Integer.parseInt(splashTimeout));
+ }
+ _config.getSplash().setTimeoutErr("true".equals(
+ props.getProperty(Splash.TIMEOUT_ERR)));
+ } else {
+ _config.setSplash(null);
+ }
+ setConfigPath(f);
+ } catch (IOException e) {
+ throw new ConfigPersisterException(e);
+ }
+ }
+
+ public void save(File f) throws ConfigPersisterException {
+ try {
+ BufferedWriter w = new BufferedWriter(new FileWriter(f));
+ _xstream.toXML(_config, w);
+ w.close();
+ setConfigPath(f);
+ } catch (Exception e) {
+ throw new ConfigPersisterException(e);
+ }
+ }
+
+ private void setConfigPath(File configFile) {
+ _configPath = configFile.getAbsoluteFile().getParentFile();
+ }
+
+ private class Props {
+ final Properties _properties = new Properties();
+
+ public Props(File f) throws IOException {
+ FileInputStream is = null;
+ try {
+ is = new FileInputStream(f);
+ _properties.load(is);
+ } finally {
+ Util.close(is);
+ }
+ }
+
+ /**
+ * Get property and remove trailing # comments.
+ */
+ public String getProperty(String key) {
+ String p = _properties.getProperty(key);
+ if (p == null) {
+ return null;
+ }
+ int x = p.indexOf('#');
+ if (x == -1) {
+ return p;
+ }
+ do {
+ x--;
+ } while (x > 0 && (p.charAt(x) == ' ' || p.charAt(x) == '\t'));
+ return (x == 0) ? "" : p.substring(0, x + 1);
+ }
+
+ public File getFile(String key) {
+ String value = getProperty(key);
+ return value != null ? new File(value) : null;
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ConfigPersisterException.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ConfigPersisterException.java
new file mode 100755
index 000000000..29940b945
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/ConfigPersisterException.java
@@ -0,0 +1,51 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 22, 2005
+ */
+package net.sf.launch4j.config;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class ConfigPersisterException extends Exception {
+
+ public ConfigPersisterException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+ public ConfigPersisterException(Throwable t) {
+ super(t);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Jre.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Jre.java
new file mode 100755
index 000000000..0df45bb84
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Jre.java
@@ -0,0 +1,235 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 21, 2005
+ */
+package net.sf.launch4j.config;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Jre implements IValidatable {
+
+ // 1.x config properties_____________________________________________________________
+ public static final String PATH = "jrepath";
+ public static final String MIN_VERSION = "javamin";
+ public static final String MAX_VERSION = "javamax";
+ public static final String ARGS = "jvmArgs";
+
+ // __________________________________________________________________________________
+ public static final String VERSION_PATTERN = "(\\d\\.){2}\\d(_\\d+)?";
+
+ public static final String JDK_PREFERENCE_JRE_ONLY = "jreOnly";
+ public static final String JDK_PREFERENCE_PREFER_JRE = "preferJre";
+ public static final String JDK_PREFERENCE_PREFER_JDK = "preferJdk";
+ public static final String JDK_PREFERENCE_JDK_ONLY = "jdkOnly";
+
+ private static final String[] JDK_PREFERENCE_NAMES = new String[] {
+ JDK_PREFERENCE_JRE_ONLY,
+ JDK_PREFERENCE_PREFER_JRE,
+ JDK_PREFERENCE_PREFER_JDK,
+ JDK_PREFERENCE_JDK_ONLY };
+
+ public static final int DEFAULT_JDK_PREFERENCE_INDEX
+ = Arrays.asList(JDK_PREFERENCE_NAMES).indexOf(JDK_PREFERENCE_PREFER_JRE);
+
+ private String path;
+ private String minVersion;
+ private String maxVersion;
+ private String jdkPreference;
+ private Integer initialHeapSize;
+ private Integer initialHeapPercent;
+ private Integer maxHeapSize;
+ private Integer maxHeapPercent;
+ private List options;
+
+ public void checkInvariants() {
+ Validator.checkOptString(minVersion, 10, VERSION_PATTERN,
+ "jre.minVersion", Messages.getString("Jre.min.version"));
+ Validator.checkOptString(maxVersion, 10, VERSION_PATTERN,
+ "jre.maxVersion", Messages.getString("Jre.max.version"));
+ if (Validator.isEmpty(path)) {
+ Validator.checkFalse(Validator.isEmpty(minVersion),
+ "jre.minVersion", Messages.getString("Jre.specify.jre.min.version.or.path"));
+ } else {
+ Validator.checkString(path, Validator.MAX_PATH,
+ "jre.path", Messages.getString("Jre.bundled.path"));
+ }
+ if (!Validator.isEmpty(maxVersion)) {
+ Validator.checkFalse(Validator.isEmpty(minVersion),
+ "jre.minVersion", Messages.getString("Jre.specify.min.version"));
+ Validator.checkTrue(minVersion.compareTo(maxVersion) < 0,
+ "jre.maxVersion", Messages.getString("Jre.max.greater.than.min"));
+ }
+ Validator.checkTrue(initialHeapSize == null || maxHeapSize != null,
+ "jre.maxHeapSize", Messages.getString("Jre.initial.and.max.heap"));
+ Validator.checkTrue(initialHeapSize == null || initialHeapSize.intValue() > 0,
+ "jre.initialHeapSize", Messages.getString("Jre.initial.heap"));
+ Validator.checkTrue(maxHeapSize == null || (maxHeapSize.intValue()
+ >= ((initialHeapSize != null) ? initialHeapSize.intValue() : 1)),
+ "jre.maxHeapSize", Messages.getString("Jre.max.heap"));
+ Validator.checkTrue(initialHeapPercent == null || maxHeapPercent != null,
+ "jre.maxHeapPercent", Messages.getString("Jre.initial.and.max.heap"));
+ if (initialHeapPercent != null) {
+ Validator.checkRange(initialHeapPercent.intValue(), 1, 100,
+ "jre.initialHeapPercent",
+ Messages.getString("Jre.initial.heap.percent"));
+ }
+ if (maxHeapPercent != null) {
+ Validator.checkRange(maxHeapPercent.intValue(),
+ initialHeapPercent != null ? initialHeapPercent.intValue() : 1, 100,
+ "jre.maxHeapPercent",
+ Messages.getString("Jre.max.heap.percent"));
+ }
+ Validator.checkIn(getJdkPreference(), JDK_PREFERENCE_NAMES,
+ "jre.jdkPreference", Messages.getString("Jre.jdkPreference.invalid"));
+ Validator.checkOptStrings(options,
+ Validator.MAX_ARGS,
+ Validator.MAX_ARGS,
+ "[^\"]*|([^\"]*\"[^\"]*\"[^\"]*)*",
+ "jre.options",
+ Messages.getString("Jre.jvm.options"),
+ Messages.getString("Jre.jvm.options.unclosed.quotation"));
+
+ // Quoted variable references: "[^%]*|([^%]*\"([^%]*%[^%]+%[^%]*)+\"[^%]*)*"
+ Validator.checkOptStrings(options,
+ Validator.MAX_ARGS,
+ Validator.MAX_ARGS,
+ "[^%]*|([^%]*([^%]*%[^%]+%[^%]*)+[^%]*)*",
+ "jre.options",
+ Messages.getString("Jre.jvm.options"),
+ Messages.getString("Jre.jvm.options.variable"));
+ }
+
+ /** JVM options */
+ public List getOptions() {
+ return options;
+ }
+
+ public void setOptions(List options) {
+ this.options = options;
+ }
+
+ /** Max Java version (x.x.x) */
+ public String getMaxVersion() {
+ return maxVersion;
+ }
+
+ public void setMaxVersion(String maxVersion) {
+ this.maxVersion = maxVersion;
+ }
+
+ /** Min Java version (x.x.x) */
+ public String getMinVersion() {
+ return minVersion;
+ }
+
+ public void setMinVersion(String minVersion) {
+ this.minVersion = minVersion;
+ }
+
+ /** Preference for standalone JRE or JDK-private JRE */
+ public String getJdkPreference() {
+ return Validator.isEmpty(jdkPreference) ? JDK_PREFERENCE_PREFER_JRE
+ : jdkPreference;
+ }
+
+ public void setJdkPreference(String jdkPreference) {
+ this.jdkPreference = jdkPreference;
+ }
+
+ /** Preference for standalone JRE or JDK-private JRE */
+ public int getJdkPreferenceIndex() {
+ int x = Arrays.asList(JDK_PREFERENCE_NAMES).indexOf(getJdkPreference());
+ return x != -1 ? x : DEFAULT_JDK_PREFERENCE_INDEX;
+ }
+
+ public void setJdkPreferenceIndex(int x) {
+ jdkPreference = JDK_PREFERENCE_NAMES[x];
+ }
+
+ /** JRE path */
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ /** Initial heap size in MB */
+ public Integer getInitialHeapSize() {
+ return initialHeapSize;
+ }
+
+ public void setInitialHeapSize(Integer initialHeapSize) {
+ this.initialHeapSize = getInteger(initialHeapSize);
+ }
+
+ /** Max heap size in MB */
+ public Integer getMaxHeapSize() {
+ return maxHeapSize;
+ }
+
+ public void setMaxHeapSize(Integer maxHeapSize) {
+ this.maxHeapSize = getInteger(maxHeapSize);
+ }
+
+ public Integer getInitialHeapPercent() {
+ return initialHeapPercent;
+ }
+
+ public void setInitialHeapPercent(Integer initialHeapPercent) {
+ this.initialHeapPercent = getInteger(initialHeapPercent);
+ }
+
+ public Integer getMaxHeapPercent() {
+ return maxHeapPercent;
+ }
+
+ public void setMaxHeapPercent(Integer maxHeapPercent) {
+ this.maxHeapPercent = getInteger(maxHeapPercent);
+ }
+
+ /** Convert 0 to null */
+ private Integer getInteger(Integer i) {
+ return i != null && i.intValue() == 0 ? null : i;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/LdDefaults.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/LdDefaults.java
new file mode 100755
index 000000000..55f457cc3
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/LdDefaults.java
@@ -0,0 +1,62 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Sep 3, 2005
+ */
+package net.sf.launch4j.config;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class LdDefaults {
+
+ public static final List GUI_HEADER_OBJECTS = Arrays.asList(new String[] {
+ "w32api/crt2.o",
+ "head/guihead.o",
+ "head/head.o" });
+
+ public static final List CONSOLE_HEADER_OBJECTS = Arrays.asList(new String[] {
+ "w32api/crt2.o",
+ "head/consolehead.o",
+ "head/head.o"});
+
+ public static final List LIBS = Arrays.asList(new String[] {
+ "w32api/libmingw32.a",
+ "w32api/libgcc.a",
+ "w32api/libmsvcrt.a",
+ "w32api/libkernel32.a",
+ "w32api/libuser32.a",
+ "w32api/libadvapi32.a",
+ "w32api/libshell32.a" });
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Messages.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Messages.java
new file mode 100755
index 000000000..a3f344e59
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Messages.java
@@ -0,0 +1,78 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.config;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "net.sf.launch4j.config.messages";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+ private static final MessageFormat FORMATTER = new MessageFormat("");
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ public static String getString(String key, String arg0) {
+ return getString(key, new Object[] {arg0});
+ }
+
+ public static String getString(String key, String arg0, String arg1) {
+ return getString(key, new Object[] {arg0, arg1});
+ }
+
+ public static String getString(String key, String arg0, String arg1, String arg2) {
+ return getString(key, new Object[] {arg0, arg1, arg2});
+ }
+
+ public static String getString(String key, Object[] args) {
+ try {
+ FORMATTER.applyPattern(RESOURCE_BUNDLE.getString(key));
+ return FORMATTER.format(args);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Msg.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Msg.java
new file mode 100755
index 000000000..ea3acfa34
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Msg.java
@@ -0,0 +1,111 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Oct 8, 2006
+ */
+package net.sf.launch4j.config;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class Msg implements IValidatable {
+ private String startupErr;
+ private String bundledJreErr;
+ private String jreVersionErr;
+ private String launcherErr;
+ private String instanceAlreadyExistsMsg;
+
+ public void checkInvariants() {
+ Validator.checkOptString(startupErr, 1024, "startupErr",
+ Messages.getString("Msg.startupErr"));
+ Validator.checkOptString(bundledJreErr, 1024, "bundledJreErr",
+ Messages.getString("Msg.bundledJreErr"));
+ Validator.checkOptString(jreVersionErr, 1024, "jreVersionErr",
+ Messages.getString("Msg.jreVersionErr"));
+ Validator.checkOptString(launcherErr, 1024, "launcherErr",
+ Messages.getString("Msg.launcherErr"));
+ Validator.checkOptString(instanceAlreadyExistsMsg, 1024, "instanceAlreadyExistsMsg",
+ Messages.getString("Msg.instanceAlreadyExistsMsg"));
+ }
+
+ public String getStartupErr() {
+ return !Validator.isEmpty(startupErr) ? startupErr
+ : "An error occurred while starting the application.";
+ }
+
+ public void setStartupErr(String startupErr) {
+ this.startupErr = startupErr;
+ }
+
+ public String getBundledJreErr() {
+ return !Validator.isEmpty(bundledJreErr) ? bundledJreErr
+ : "This application was configured to use a bundled Java Runtime" +
+ " Environment but the runtime is missing or corrupted.";
+ }
+
+ public void setBundledJreErr(String bundledJreErr) {
+ this.bundledJreErr = bundledJreErr;
+ }
+
+ public String getJreVersionErr() {
+ return !Validator.isEmpty(jreVersionErr) ? jreVersionErr
+ : "This application requires a Java Runtime Environment";
+ }
+
+ public void setJreVersionErr(String jreVersionErr) {
+ this.jreVersionErr = jreVersionErr;
+ }
+
+ public String getLauncherErr() {
+ return !Validator.isEmpty(launcherErr) ? launcherErr
+ : "The registry refers to a nonexistent Java Runtime Environment" +
+ " installation or the runtime is corrupted.";
+ }
+
+ public void setLauncherErr(String launcherErr) {
+ this.launcherErr = launcherErr;
+ }
+
+ public String getInstanceAlreadyExistsMsg() {
+ return !Validator.isEmpty(instanceAlreadyExistsMsg) ? instanceAlreadyExistsMsg
+ : "An application instance is already running.";
+ }
+
+ public void setInstanceAlreadyExistsMsg(String instanceAlreadyExistsMsg) {
+ this.instanceAlreadyExistsMsg = instanceAlreadyExistsMsg;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/SingleInstance.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/SingleInstance.java
new file mode 100755
index 000000000..0ae340cd7
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/SingleInstance.java
@@ -0,0 +1,74 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * Created on 2007-09-16
+ */
+package net.sf.launch4j.config;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2007 Grzegorz Kowal
+ */
+public class SingleInstance implements IValidatable {
+
+ private String mutexName;
+ private String windowTitle;
+
+ public void checkInvariants() {
+ Validator.checkString(mutexName, Validator.MAX_STR,
+ "singleInstance.mutexName",
+ Messages.getString("SingleInstance.mutexName"));
+ Validator.checkOptString(windowTitle, Validator.MAX_STR,
+ "singleInstance.windowTitle",
+ Messages.getString("SingleInstance.windowTitle"));
+ }
+
+ public String getWindowTitle() {
+ return windowTitle;
+ }
+
+ public void setWindowTitle(String appWindowName) {
+ this.windowTitle = appWindowName;
+ }
+
+ public String getMutexName() {
+ return mutexName;
+ }
+
+ public void setMutexName(String mutexName) {
+ this.mutexName = mutexName;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Splash.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Splash.java
new file mode 100755
index 000000000..f736f8208
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/Splash.java
@@ -0,0 +1,103 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Apr 21, 2005
+ */
+package net.sf.launch4j.config;
+
+import java.io.File;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class Splash implements IValidatable {
+
+ // 1.x config properties_____________________________________________________________
+ public static final String SPLASH_FILE = "splash";
+ public static final String WAIT_FOR_TITLE = "waitForTitle";
+ public static final String TIMEOUT = "splashTimeout";
+ public static final String TIMEOUT_ERR = "splashTimeoutErr";
+
+ // __________________________________________________________________________________
+ private File file;
+ private boolean waitForWindow = true;
+ private int timeout = 60;
+ private boolean timeoutErr = true;
+
+ public void checkInvariants() {
+ Validator.checkFile(file, "splash.file",
+ Messages.getString("Splash.splash.file"));
+ Validator.checkRange(timeout, 1, 60 * 15, "splash.timeout",
+ Messages.getString("Splash.splash.timeout"));
+ }
+
+ /** Splash screen in BMP format. */
+ public File getFile() {
+ return file;
+ }
+
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ /** Splash timeout in seconds. */
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ /** Signal error on splash timeout. */
+ public boolean isTimeoutErr() {
+ return timeoutErr;
+ }
+
+ public void setTimeoutErr(boolean timeoutErr) {
+ this.timeoutErr = timeoutErr;
+ }
+
+ /** Hide splash screen when the child process displayes the first window. */
+ public boolean getWaitForWindow() {
+ return waitForWindow;
+ }
+
+ public void setWaitForWindow(boolean waitForWindow) {
+ this.waitForWindow = waitForWindow;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/VersionInfo.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/VersionInfo.java
new file mode 100755
index 000000000..d719460c2
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/VersionInfo.java
@@ -0,0 +1,168 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 21, 2005
+ */
+package net.sf.launch4j.config;
+
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.binding.Validator;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class VersionInfo implements IValidatable {
+ public static final String VERSION_PATTERN = "(\\d+\\.){3}\\d+";
+
+ private String fileVersion;
+ private String txtFileVersion;
+ private String fileDescription;
+ private String copyright;
+ private String productVersion;
+ private String txtProductVersion;
+ private String productName;
+ private String companyName;
+ private String internalName;
+ private String originalFilename;
+
+ public void checkInvariants() {
+ Validator.checkString(fileVersion, 20, VERSION_PATTERN,
+ "versionInfo.fileVersion",
+ Messages.getString("VersionInfo.file.version"));
+ Validator.checkString(txtFileVersion, 50, "versionInfo.txtFileVersion",
+ Messages.getString("VersionInfo.txt.file.version"));
+ Validator.checkString(fileDescription, 150, "versionInfo.fileDescription",
+ Messages.getString("VersionInfo.file.description"));
+ Validator.checkString(copyright, 150, "versionInfo.copyright",
+ Messages.getString("VersionInfo.copyright"));
+ Validator.checkString(productVersion, 20, VERSION_PATTERN,
+ "versionInfo.productVersion",
+ Messages.getString("VersionInfo.product.version"));
+ Validator.checkString(txtProductVersion, 50, "versionInfo.txtProductVersion",
+ Messages.getString("VersionInfo.txt.product.version"));
+ Validator.checkString(productName, 150, "versionInfo.productName",
+ Messages.getString("VersionInfo.product.name"));
+ Validator.checkOptString(companyName, 150, "versionInfo.companyName",
+ Messages.getString("VersionInfo.company.name"));
+ Validator.checkString(internalName, 50, "versionInfo.internalName",
+ Messages.getString("VersionInfo.internal.name"));
+ Validator.checkTrue(!internalName.endsWith(".exe"), "versionInfo.internalName",
+ Messages.getString("VersionInfo.internal.name.not.exe"));
+ Validator.checkString(originalFilename, 50, "versionInfo.originalFilename",
+ Messages.getString("VersionInfo.original.filename"));
+ Validator.checkTrue(originalFilename.endsWith(".exe"),
+ "versionInfo.originalFilename",
+ Messages.getString("VersionInfo.original.filename.exe"));
+ }
+
+ public String getCompanyName() {
+ return companyName;
+ }
+
+ public void setCompanyName(String companyName) {
+ this.companyName = companyName;
+ }
+
+ public String getCopyright() {
+ return copyright;
+ }
+
+ public void setCopyright(String copyright) {
+ this.copyright = copyright;
+ }
+
+ public String getFileDescription() {
+ return fileDescription;
+ }
+
+ public void setFileDescription(String fileDescription) {
+ this.fileDescription = fileDescription;
+ }
+
+ public String getFileVersion() {
+ return fileVersion;
+ }
+
+ public void setFileVersion(String fileVersion) {
+ this.fileVersion = fileVersion;
+ }
+
+ public String getInternalName() {
+ return internalName;
+ }
+
+ public void setInternalName(String internalName) {
+ this.internalName = internalName;
+ }
+
+ public String getOriginalFilename() {
+ return originalFilename;
+ }
+
+ public void setOriginalFilename(String originalFilename) {
+ this.originalFilename = originalFilename;
+ }
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public void setProductName(String productName) {
+ this.productName = productName;
+ }
+
+ public String getProductVersion() {
+ return productVersion;
+ }
+
+ public void setProductVersion(String productVersion) {
+ this.productVersion = productVersion;
+ }
+
+ public String getTxtFileVersion() {
+ return txtFileVersion;
+ }
+
+ public void setTxtFileVersion(String txtFileVersion) {
+ this.txtFileVersion = txtFileVersion;
+ }
+
+ public String getTxtProductVersion() {
+ return txtProductVersion;
+ }
+
+ public void setTxtProductVersion(String txtProductVersion) {
+ this.txtProductVersion = txtProductVersion;
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/messages.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/messages.properties
new file mode 100755
index 000000000..5753663f4
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/messages.properties
@@ -0,0 +1,93 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+Splash.splash.file=Splash file
+Splash.splash.timeout=Splash timeout
+
+Config.specify.output.exe=Specify output file with .exe extension.
+Config.application.jar=Application jar
+Config.application.jar.path=Specify runtime path of the jar relative to the executable.
+Config.chdir.relative='chdir' must be a path relative to the executable.
+Config.chdir.path='chdir' is now a path instead of a boolean, please check the docs.
+Config.manifest=Manifest
+Config.icon=Icon
+Config.jar.arguments=Jar arguments
+Config.error.title=Error title
+Config.download.url=Download URL
+Config.support.url=Support URL
+Config.header.type=Header type
+Config.splash.not.impl.by.console.hdr=Splash screen is not implemented by console header.
+Config.variables=Environment variables
+Config.variables.err=Environment variable assignment should have the form varname=[value][%varref%]...
+Config.priority=Process priority
+
+ClassPath.mainClass=Main class
+ClassPath.or.jar=Specify runtime path of a jar or the classpath.
+ClassPath.path=Classpath
+
+VersionInfo.file.version=File version, should be 'x.x.x.x'
+VersionInfo.txt.file.version=Free form file version
+VersionInfo.file.description=File description
+VersionInfo.copyright=Copyright
+VersionInfo.product.version=Product version, should be 'x.x.x.x'
+VersionInfo.txt.product.version=Free from product version
+VersionInfo.product.name=Product name
+VersionInfo.company.name=Company name
+VersionInfo.internal.name=Internal name
+VersionInfo.internal.name.not.exe=Internal name shouldn't have the .exe extension.
+VersionInfo.original.filename=Original filename
+VersionInfo.original.filename.exe=Original filename should end with the .exe extension.
+
+Jre.min.version=Minimum JRE version should be x.x.x[_xx]
+Jre.max.version=Maximum JRE version should be x.x.x[_xx]
+Jre.specify.jre.min.version.or.path=Specify minimum JRE version and/or bundled JRE path.
+Jre.bundled.path=Bundled JRE path
+Jre.specify.min.version=Specify minimum JRE version.
+Jre.max.greater.than.min=Maximum JRE version must be greater than the minimum.\nTo use a certain JRE version, you may set the min/max range to [1.4.2 - 1.4.2_10] for example.
+Jre.initial.and.max.heap=If you change the initial heap size please also specify the maximum size.
+Jre.initial.heap=Initial heap size must be greater than 0, leave the field blank to use the JVM default.
+Jre.max.heap=Maximum heap size cannot be less than the initial size, leave the field blank to use the JVM default.
+Jre.initial.heap.percent=Initial heap %
+Jre.max.heap.percent=Maximum heap %
+Jre.jdkPreference.invalid=Unrecognised value for JDK preference, should be between 0 and 3 inclusive.
+Jre.jvm.options=JVM arguments
+Jre.jvm.options.unclosed.quotation=JVM arguments contain an unclosed quotation.
+Jre.jvm.options.variable=Invalid environment variable reference.
+
+Msg.startupErr=Startup error message
+Msg.bundledJreErr=Bundled JRE error message
+Msg.jreVersionErr=JRE version error message
+Msg.launcherErr=Launcher error message
+
+SingleInstance.mutexName=Mutex name
+SingleInstance.windowTitle=Window title
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/config/messages_es.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/messages_es.properties
new file mode 100755
index 000000000..5e8659b1f
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/config/messages_es.properties
@@ -0,0 +1,75 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal, Patricio Martínez Ros
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+Splash.splash.file = Fichero de la pantalla de bienvenida
+Splash.splash.timeout = Tiempo de espera de la pantalla de bienvenida
+
+Config.specify.output.exe = Especifique el fichero de salida con extensi\u00F3n .exe.
+Config.application.jar = Aplicaci\u00F3n jar
+Config.application.jar.path = Especifique la ruta del jar relativa al ejecutable.
+Config.chdir.relative = 'Cambiar al directorio' debe ser una ruta relativa al ejecutable.
+Config.chdir.path = 'Cambiar al directorio' ahora es una ruta en lugar de un booleano, por favor consulte la documentaci\u00F3n.
+Config.icon = Icono
+Config.jar.arguments = Argumentos del jar
+Config.error.title = T\u00EDtulo de error
+Config.header.type = Tipo de cabecera
+Config.splash.not.impl.by.console.hdr = La pantalla de bienvenida no est\u00E1 implementada para la cabecera de tipo consola.
+
+VersionInfo.file.version = La versi\u00F3n del fichero, deber\u00EDa ser 'x.x.x.x'
+VersionInfo.txt.file.version = Forma libre de versi\u00F3n del fichero
+VersionInfo.file.description = Descripci\u00F3n del fichero
+VersionInfo.copyright = Copyright
+VersionInfo.product.version = Versi\u00F3n del producto, deber\u00EDa ser 'x.x.x.x'
+VersionInfo.txt.product.version = Forma libre de versi\u00F3n del producto
+VersionInfo.product.name = Nombre del producto
+VersionInfo.company.name = Nombre de la organizaci\u00F3n
+VersionInfo.internal.name = Nombre interno
+VersionInfo.internal.name.not.exe = El nombre interno no deber\u00EDa tener extensi\u00F3n .exe.
+VersionInfo.original.filename = Nombre original del fichero
+VersionInfo.original.filename.exe = El nombre original del fichero debe acabar con extensi\u00F3n .exe.
+Jre.min.version = La versi\u00F3n m\u00EDnima del JRE deber\u00EDa ser x.x.x[_xx]
+Jre.max.version = La versi\u00F3n m\u00E1xima del JRE deber\u00EDa ser x.x.x[_xx]
+Jre.specify.jre.min.version.or.path=Specify minimum JRE version and/or bundled JRE path.
+Jre.bundled.path.rel = La ruta del JRE debe ser relativa al ejecutable.
+Jre.specify.min.version = Especifique la versi\u00F3n m\u00EDnima del JRE.
+Jre.max.greater.than.min = La versi\u00F3n m\u00E1xima del JRE debe ser mayor que la m\u00EDnima.\nPara usar cierta versi\u00F3n del JRE, puede esyablecer el rango m\u00EDnimo/m\u00E1ximo a [1.4.2 - 1.4.2_10], por ejemplo.
+Jre.jvm.options = Argumentos de la JVM
+
+Msg.startupErr=Startup error message
+Msg.bundledJreErr=Bundled JRE error message
+Msg.jreVersionErr=JRE version error message
+Msg.launcherErr=Launcher error message
+
+SingleInstance.mutexName=Mutex name
+SingleInstance.windowTitle=Window title
+
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/BasicForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/BasicForm.java
new file mode 100755
index 000000000..4dadbb983
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/BasicForm.java
@@ -0,0 +1,283 @@
+package net.sf.launch4j.form;
+
+import com.jeta.forms.components.separator.TitledSeparator;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+public abstract class BasicForm extends JPanel
+{
+ protected final JButton _outfileButton = new JButton();
+ protected final JLabel _outfileLabel = new JLabel();
+ protected final JLabel _iconLabel = new JLabel();
+ protected final JLabel _jarLabel = new JLabel();
+ protected final JButton _jarButton = new JButton();
+ protected final JButton _iconButton = new JButton();
+ protected final JLabel _cmdLineLabel = new JLabel();
+ protected final JLabel _optionsLabel = new JLabel();
+ protected final JLabel _chdirLabel = new JLabel();
+ protected final JLabel _processPriorityLabel = new JLabel();
+ protected final JRadioButton _normalPriorityRadio = new JRadioButton();
+ protected final ButtonGroup _buttongroup1 = new ButtonGroup();
+ protected final JRadioButton _idlePriorityRadio = new JRadioButton();
+ protected final JRadioButton _highPriorityRadio = new JRadioButton();
+ protected final JCheckBox _customProcNameCheck = new JCheckBox();
+ protected final JCheckBox _stayAliveCheck = new JCheckBox();
+ protected final JTextField _cmdLineField = new JTextField();
+ protected final JTextField _chdirField = new JTextField();
+ protected final JTextField _iconField = new JTextField();
+ protected final JCheckBox _dontWrapJarCheck = new JCheckBox();
+ protected final JTextField _jarField = new JTextField();
+ protected final JTextField _outfileField = new JTextField();
+ protected final JLabel _errorTitleLabel = new JLabel();
+ protected final JTextField _errorTitleField = new JTextField();
+ protected final JLabel _downloadUrlLabel = new JLabel();
+ protected final JTextField _downloadUrlField = new JTextField();
+ protected final JLabel _supportUrlLabel = new JLabel();
+ protected final JTextField _supportUrlField = new JTextField();
+ protected final JTextField _manifestField = new JTextField();
+ protected final JButton _manifestButton = new JButton();
+
+ /**
+ * Default constructor
+ */
+ public BasicForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:DEFAULT:NONE,FILL:DEFAULT:GROW(1.0),FILL:3DLU:NONE,FILL:26PX:NONE,FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _outfileButton.setIcon(loadImage("images/open16.png"));
+ _outfileButton.setName("outfileButton");
+ jpanel1.add(_outfileButton,cc.xy(12,2));
+
+ _outfileLabel.setIcon(loadImage("images/asterix.gif"));
+ _outfileLabel.setName("outfileLabel");
+ _outfileLabel.setText(Messages.getString("outfile"));
+ jpanel1.add(_outfileLabel,cc.xy(2,2));
+
+ _iconLabel.setName("iconLabel");
+ _iconLabel.setText(Messages.getString("icon"));
+ jpanel1.add(_iconLabel,cc.xy(2,10));
+
+ _jarLabel.setIcon(loadImage("images/asterix.gif"));
+ _jarLabel.setName("jarLabel");
+ _jarLabel.setText(Messages.getString("jar"));
+ jpanel1.add(_jarLabel,cc.xy(2,4));
+
+ _jarButton.setIcon(loadImage("images/open16.png"));
+ _jarButton.setName("jarButton");
+ jpanel1.add(_jarButton,cc.xy(12,4));
+
+ _iconButton.setIcon(loadImage("images/open16.png"));
+ _iconButton.setName("iconButton");
+ jpanel1.add(_iconButton,cc.xy(12,10));
+
+ _cmdLineLabel.setName("cmdLineLabel");
+ _cmdLineLabel.setText(Messages.getString("cmdLine"));
+ _cmdLineLabel.setToolTipText("");
+ jpanel1.add(_cmdLineLabel,cc.xy(2,14));
+
+ _optionsLabel.setName("optionsLabel");
+ _optionsLabel.setText(Messages.getString("options"));
+ jpanel1.add(_optionsLabel,cc.xy(2,18));
+
+ _chdirLabel.setName("chdirLabel");
+ _chdirLabel.setText(Messages.getString("chdir"));
+ jpanel1.add(_chdirLabel,cc.xy(2,12));
+
+ _processPriorityLabel.setName("processPriorityLabel");
+ _processPriorityLabel.setText(Messages.getString("priority"));
+ jpanel1.add(_processPriorityLabel,cc.xy(2,16));
+
+ _normalPriorityRadio.setActionCommand(Messages.getString("normalPriority"));
+ _normalPriorityRadio.setName("normalPriorityRadio");
+ _normalPriorityRadio.setText(Messages.getString("normalPriority"));
+ _buttongroup1.add(_normalPriorityRadio);
+ jpanel1.add(_normalPriorityRadio,cc.xy(4,16));
+
+ _idlePriorityRadio.setActionCommand(Messages.getString("idlePriority"));
+ _idlePriorityRadio.setName("idlePriorityRadio");
+ _idlePriorityRadio.setText(Messages.getString("idlePriority"));
+ _buttongroup1.add(_idlePriorityRadio);
+ jpanel1.add(_idlePriorityRadio,cc.xy(6,16));
+
+ _highPriorityRadio.setActionCommand(Messages.getString("highPriority"));
+ _highPriorityRadio.setName("highPriorityRadio");
+ _highPriorityRadio.setText(Messages.getString("highPriority"));
+ _buttongroup1.add(_highPriorityRadio);
+ jpanel1.add(_highPriorityRadio,cc.xy(8,16));
+
+ _customProcNameCheck.setActionCommand("Custom process name");
+ _customProcNameCheck.setName("customProcNameCheck");
+ _customProcNameCheck.setText(Messages.getString("customProcName"));
+ jpanel1.add(_customProcNameCheck,cc.xywh(4,18,7,1));
+
+ _stayAliveCheck.setActionCommand("Stay alive after launching a GUI application");
+ _stayAliveCheck.setName("stayAliveCheck");
+ _stayAliveCheck.setText(Messages.getString("stayAlive"));
+ jpanel1.add(_stayAliveCheck,cc.xywh(4,20,7,1));
+
+ _cmdLineField.setName("cmdLineField");
+ _cmdLineField.setToolTipText(Messages.getString("cmdLineTip"));
+ jpanel1.add(_cmdLineField,cc.xywh(4,14,7,1));
+
+ _chdirField.setName("chdirField");
+ _chdirField.setToolTipText(Messages.getString("chdirTip"));
+ jpanel1.add(_chdirField,cc.xywh(4,12,7,1));
+
+ _iconField.setName("iconField");
+ _iconField.setToolTipText(Messages.getString("iconTip"));
+ jpanel1.add(_iconField,cc.xywh(4,10,7,1));
+
+ _dontWrapJarCheck.setActionCommand("Don't wrap the jar, launch it only");
+ _dontWrapJarCheck.setName("dontWrapJarCheck");
+ _dontWrapJarCheck.setText(Messages.getString("dontWrapJar"));
+ jpanel1.add(_dontWrapJarCheck,cc.xywh(4,6,7,1));
+
+ _jarField.setName("jarField");
+ _jarField.setToolTipText(Messages.getString("jarTip"));
+ jpanel1.add(_jarField,cc.xywh(4,4,7,1));
+
+ _outfileField.setName("outfileField");
+ _outfileField.setToolTipText(Messages.getString("outfileTip"));
+ jpanel1.add(_outfileField,cc.xywh(4,2,7,1));
+
+ TitledSeparator titledseparator1 = new TitledSeparator();
+ titledseparator1.setText(Messages.getString("downloadAndSupport"));
+ jpanel1.add(titledseparator1,cc.xywh(2,22,11,1));
+
+ _errorTitleLabel.setName("errorTitleLabel");
+ _errorTitleLabel.setText(Messages.getString("errorTitle"));
+ jpanel1.add(_errorTitleLabel,cc.xy(2,24));
+
+ _errorTitleField.setName("errorTitleField");
+ _errorTitleField.setToolTipText(Messages.getString("errorTitleTip"));
+ jpanel1.add(_errorTitleField,cc.xywh(4,24,7,1));
+
+ _downloadUrlLabel.setIcon(loadImage("images/asterix.gif"));
+ _downloadUrlLabel.setName("downloadUrlLabel");
+ _downloadUrlLabel.setText(Messages.getString("downloadUrl"));
+ jpanel1.add(_downloadUrlLabel,cc.xy(2,26));
+
+ _downloadUrlField.setName("downloadUrlField");
+ jpanel1.add(_downloadUrlField,cc.xywh(4,26,7,1));
+
+ _supportUrlLabel.setName("supportUrlLabel");
+ _supportUrlLabel.setText(Messages.getString("supportUrl"));
+ jpanel1.add(_supportUrlLabel,cc.xy(2,28));
+
+ _supportUrlField.setName("supportUrlField");
+ jpanel1.add(_supportUrlField,cc.xywh(4,28,7,1));
+
+ JLabel jlabel1 = new JLabel();
+ jlabel1.setText(Messages.getString("manifest"));
+ jpanel1.add(jlabel1,cc.xy(2,8));
+
+ _manifestField.setName("manifestField");
+ _manifestField.setToolTipText(Messages.getString("manifestTip"));
+ jpanel1.add(_manifestField,cc.xywh(4,8,7,1));
+
+ _manifestButton.setIcon(loadImage("images/open16.png"));
+ _manifestButton.setName("manifestButton");
+ jpanel1.add(_manifestButton,cc.xy(12,8));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm
new file mode 100755
index 000000000..1d8a9ad58
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ClassPathForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ClassPathForm.java
new file mode 100755
index 000000000..9f4f52471
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ClassPathForm.java
@@ -0,0 +1,193 @@
+package net.sf.launch4j.form;
+
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+
+public abstract class ClassPathForm extends JPanel
+{
+ protected final JTextField _classpathField = new JTextField();
+ protected final JLabel _classpathFieldLabel = new JLabel();
+ protected final JLabel _classpathListLabel = new JLabel();
+ protected final JList _classpathList = new JList();
+ protected final JLabel _mainclassLabel = new JLabel();
+ protected final JTextField _mainclassField = new JTextField();
+ protected final JButton _acceptClasspathButton = new JButton();
+ protected final JButton _removeClasspathButton = new JButton();
+ protected final JButton _importClasspathButton = new JButton();
+ protected final JButton _classpathUpButton = new JButton();
+ protected final JButton _classpathDownButton = new JButton();
+ protected final JCheckBox _classpathCheck = new JCheckBox();
+ protected final JButton _newClasspathButton = new JButton();
+
+ /**
+ * Default constructor
+ */
+ public ClassPathForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:3DLU:NONE,FILL:26PX:NONE,FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:DEFAULT:GROW(1.0),CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _classpathField.setName("classpathField");
+ jpanel1.add(_classpathField,cc.xywh(4,11,7,1));
+
+ _classpathFieldLabel.setIcon(loadImage("images/asterix.gif"));
+ _classpathFieldLabel.setName("classpathFieldLabel");
+ _classpathFieldLabel.setText(Messages.getString("editClassPath"));
+ jpanel1.add(_classpathFieldLabel,cc.xy(2,11));
+
+ _classpathListLabel.setName("classpathListLabel");
+ _classpathListLabel.setText(Messages.getString("classPath"));
+ jpanel1.add(_classpathListLabel,cc.xy(2,6));
+
+ _classpathList.setName("classpathList");
+ JScrollPane jscrollpane1 = new JScrollPane();
+ jscrollpane1.setViewportView(_classpathList);
+ jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane1,cc.xywh(4,6,7,4));
+
+ _mainclassLabel.setIcon(loadImage("images/asterix.gif"));
+ _mainclassLabel.setName("mainclassLabel");
+ _mainclassLabel.setText(Messages.getString("mainClass"));
+ jpanel1.add(_mainclassLabel,cc.xy(2,4));
+
+ _mainclassField.setName("mainclassField");
+ jpanel1.add(_mainclassField,cc.xywh(4,4,7,1));
+
+ _acceptClasspathButton.setActionCommand("Add");
+ _acceptClasspathButton.setIcon(loadImage("images/ok16.png"));
+ _acceptClasspathButton.setName("acceptClasspathButton");
+ _acceptClasspathButton.setText(Messages.getString("accept"));
+ jpanel1.add(_acceptClasspathButton,cc.xy(8,13));
+
+ _removeClasspathButton.setActionCommand("Remove");
+ _removeClasspathButton.setIcon(loadImage("images/cancel16.png"));
+ _removeClasspathButton.setName("removeClasspathButton");
+ _removeClasspathButton.setText(Messages.getString("remove"));
+ jpanel1.add(_removeClasspathButton,cc.xy(10,13));
+
+ _importClasspathButton.setIcon(loadImage("images/open16.png"));
+ _importClasspathButton.setName("importClasspathButton");
+ _importClasspathButton.setToolTipText(Messages.getString("importClassPath"));
+ jpanel1.add(_importClasspathButton,cc.xy(12,4));
+
+ _classpathUpButton.setIcon(loadImage("images/up16.png"));
+ _classpathUpButton.setName("classpathUpButton");
+ jpanel1.add(_classpathUpButton,cc.xy(12,6));
+
+ _classpathDownButton.setIcon(loadImage("images/down16.png"));
+ _classpathDownButton.setName("classpathDownButton");
+ jpanel1.add(_classpathDownButton,cc.xy(12,8));
+
+ _classpathCheck.setActionCommand("Custom classpath");
+ _classpathCheck.setName("classpathCheck");
+ _classpathCheck.setText(Messages.getString("customClassPath"));
+ jpanel1.add(_classpathCheck,cc.xy(4,2));
+
+ _newClasspathButton.setActionCommand("New");
+ _newClasspathButton.setIcon(loadImage("images/new16.png"));
+ _newClasspathButton.setName("newClasspathButton");
+ _newClasspathButton.setText(Messages.getString("new"));
+ jpanel1.add(_newClasspathButton,cc.xy(6,13));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ClassPathForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ClassPathForm.jfrm
new file mode 100755
index 000000000..764329d2b
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ClassPathForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ConfigForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ConfigForm.java
new file mode 100755
index 000000000..b3c6fffed
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ConfigForm.java
@@ -0,0 +1,132 @@
+package net.sf.launch4j.form;
+
+import com.jeta.forms.components.separator.TitledSeparator;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+
+public abstract class ConfigForm extends JPanel
+{
+ protected final JTextArea _logTextArea = new JTextArea();
+ protected final TitledSeparator _logSeparator = new TitledSeparator();
+ protected final JTabbedPane _tab = new JTabbedPane();
+
+ /**
+ * Default constructor
+ */
+ public ConfigForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:3DLU:NONE,FILL:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _logTextArea.setName("logTextArea");
+ JScrollPane jscrollpane1 = new JScrollPane();
+ jscrollpane1.setViewportView(_logTextArea);
+ jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane1,cc.xy(2,6));
+
+ _logSeparator.setName("logSeparator");
+ _logSeparator.setText(Messages.getString("log"));
+ jpanel1.add(_logSeparator,cc.xy(2,4));
+
+ _tab.setName("tab");
+ jpanel1.add(_tab,cc.xywh(1,2,3,1));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3 },new int[]{ 1,3,4,5,6,7 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ConfigForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ConfigForm.jfrm
new file mode 100755
index 000000000..2c6721e14
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/ConfigForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/EnvironmentVarsForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/EnvironmentVarsForm.java
new file mode 100755
index 000000000..f2b79e6e7
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/EnvironmentVarsForm.java
@@ -0,0 +1,127 @@
+package net.sf.launch4j.form;
+
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+public abstract class EnvironmentVarsForm extends JPanel
+{
+ protected final JTextArea _envVarsTextArea = new JTextArea();
+ protected final JLabel _envVarsLabel = new JLabel();
+
+ /**
+ * Default constructor
+ */
+ public EnvironmentVarsForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _envVarsTextArea.setName("envVarsTextArea");
+ JScrollPane jscrollpane1 = new JScrollPane();
+ jscrollpane1.setViewportView(_envVarsTextArea);
+ jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane1,cc.xy(4,2));
+
+ _envVarsLabel.setName("envVarsLabel");
+ _envVarsLabel.setText(Messages.getString("setVariables"));
+ jpanel1.add(_envVarsLabel,new CellConstraints(2,2,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5 },new int[]{ 1,2,3 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/EnvironmentVarsForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/EnvironmentVarsForm.jfrm
new file mode 100755
index 000000000..6e89ec4d1
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/EnvironmentVarsForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/HeaderForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/HeaderForm.java
new file mode 100755
index 000000000..91c40024a
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/HeaderForm.java
@@ -0,0 +1,171 @@
+package net.sf.launch4j.form;
+
+import com.jeta.forms.components.separator.TitledSeparator;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+public abstract class HeaderForm extends JPanel
+{
+ protected final JLabel _headerTypeLabel = new JLabel();
+ protected final JRadioButton _guiHeaderRadio = new JRadioButton();
+ protected final ButtonGroup _headerButtonGroup = new ButtonGroup();
+ protected final JRadioButton _consoleHeaderRadio = new JRadioButton();
+ protected final JTextArea _headerObjectsTextArea = new JTextArea();
+ protected final JTextArea _libsTextArea = new JTextArea();
+ protected final JCheckBox _headerObjectsCheck = new JCheckBox();
+ protected final JCheckBox _libsCheck = new JCheckBox();
+ protected final TitledSeparator _linkerOptionsSeparator = new TitledSeparator();
+
+ /**
+ * Default constructor
+ */
+ public HeaderForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,FILL:DEFAULT:GROW(0.2),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _headerTypeLabel.setName("headerTypeLabel");
+ _headerTypeLabel.setText(Messages.getString("headerType"));
+ jpanel1.add(_headerTypeLabel,cc.xy(2,2));
+
+ _guiHeaderRadio.setActionCommand("GUI");
+ _guiHeaderRadio.setName("guiHeaderRadio");
+ _guiHeaderRadio.setText(Messages.getString("gui"));
+ _headerButtonGroup.add(_guiHeaderRadio);
+ jpanel1.add(_guiHeaderRadio,cc.xy(4,2));
+
+ _consoleHeaderRadio.setActionCommand("Console");
+ _consoleHeaderRadio.setName("consoleHeaderRadio");
+ _consoleHeaderRadio.setText(Messages.getString("console"));
+ _headerButtonGroup.add(_consoleHeaderRadio);
+ jpanel1.add(_consoleHeaderRadio,cc.xy(6,2));
+
+ _headerObjectsTextArea.setName("headerObjectsTextArea");
+ JScrollPane jscrollpane1 = new JScrollPane();
+ jscrollpane1.setViewportView(_headerObjectsTextArea);
+ jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane1,cc.xywh(4,6,4,1));
+
+ _libsTextArea.setName("libsTextArea");
+ JScrollPane jscrollpane2 = new JScrollPane();
+ jscrollpane2.setViewportView(_libsTextArea);
+ jscrollpane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane2,cc.xywh(4,8,4,1));
+
+ _headerObjectsCheck.setActionCommand("Object files");
+ _headerObjectsCheck.setName("headerObjectsCheck");
+ _headerObjectsCheck.setText(Messages.getString("objectFiles"));
+ jpanel1.add(_headerObjectsCheck,new CellConstraints(2,6,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ _libsCheck.setActionCommand("w32api");
+ _libsCheck.setName("libsCheck");
+ _libsCheck.setText(Messages.getString("libs"));
+ jpanel1.add(_libsCheck,new CellConstraints(2,8,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ _linkerOptionsSeparator.setName("linkerOptionsSeparator");
+ _linkerOptionsSeparator.setText(Messages.getString("linkerOptions"));
+ jpanel1.add(_linkerOptionsSeparator,cc.xywh(2,4,6,1));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8 },new int[]{ 1,2,3,4,5,6,7,8,9 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm
new file mode 100755
index 000000000..a7cbed144
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/JreForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/JreForm.java
new file mode 100755
index 000000000..ed16c50b6
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/JreForm.java
@@ -0,0 +1,266 @@
+package net.sf.launch4j.form;
+
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+
+public abstract class JreForm extends JPanel
+{
+ protected final JLabel _jrePathLabel = new JLabel();
+ protected final JLabel _jreMinLabel = new JLabel();
+ protected final JLabel _jreMaxLabel = new JLabel();
+ protected final JLabel _jvmOptionsTextLabel = new JLabel();
+ protected final JTextField _jrePathField = new JTextField();
+ protected final JTextField _jreMinField = new JTextField();
+ protected final JTextField _jreMaxField = new JTextField();
+ protected final JTextArea _jvmOptionsTextArea = new JTextArea();
+ protected final JLabel _initialHeapSizeLabel = new JLabel();
+ protected final JLabel _maxHeapSizeLabel = new JLabel();
+ protected final JTextField _initialHeapSizeField = new JTextField();
+ protected final JTextField _maxHeapSizeField = new JTextField();
+ protected final JComboBox _varCombo = new JComboBox();
+ protected final JButton _propertyButton = new JButton();
+ protected final JButton _optionButton = new JButton();
+ protected final JButton _envPropertyButton = new JButton();
+ protected final JButton _envOptionButton = new JButton();
+ protected final JTextField _envVarField = new JTextField();
+ protected final JTextField _maxHeapPercentField = new JTextField();
+ protected final JTextField _initialHeapPercentField = new JTextField();
+ protected final JComboBox _jdkPreferenceCombo = new JComboBox();
+
+ /**
+ * Default constructor
+ */
+ public JreForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:60DLU:NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:60DLU:NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,FILL:50DLU:GROW(1.0),CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _jrePathLabel.setName("jrePathLabel");
+ _jrePathLabel.setText(Messages.getString("jrePath"));
+ jpanel1.add(_jrePathLabel,cc.xy(2,2));
+
+ _jreMinLabel.setName("jreMinLabel");
+ _jreMinLabel.setText(Messages.getString("jreMin"));
+ jpanel1.add(_jreMinLabel,cc.xy(2,4));
+
+ _jreMaxLabel.setName("jreMaxLabel");
+ _jreMaxLabel.setText(Messages.getString("jreMax"));
+ jpanel1.add(_jreMaxLabel,cc.xy(2,6));
+
+ _jvmOptionsTextLabel.setName("jvmOptionsTextLabel");
+ _jvmOptionsTextLabel.setText(Messages.getString("jvmOptions"));
+ jpanel1.add(_jvmOptionsTextLabel,new CellConstraints(2,12,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ _jrePathField.setName("jrePathField");
+ _jrePathField.setToolTipText(Messages.getString("jrePathTip"));
+ jpanel1.add(_jrePathField,cc.xywh(4,2,7,1));
+
+ _jreMinField.setName("jreMinField");
+ jpanel1.add(_jreMinField,cc.xy(4,4));
+
+ _jreMaxField.setName("jreMaxField");
+ jpanel1.add(_jreMaxField,cc.xy(4,6));
+
+ _jvmOptionsTextArea.setName("jvmOptionsTextArea");
+ _jvmOptionsTextArea.setToolTipText(Messages.getString("jvmOptionsTip"));
+ JScrollPane jscrollpane1 = new JScrollPane();
+ jscrollpane1.setViewportView(_jvmOptionsTextArea);
+ jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane1,cc.xywh(4,12,7,1));
+
+ _initialHeapSizeLabel.setName("initialHeapSizeLabel");
+ _initialHeapSizeLabel.setText(Messages.getString("initialHeapSize"));
+ jpanel1.add(_initialHeapSizeLabel,cc.xy(2,8));
+
+ _maxHeapSizeLabel.setName("maxHeapSizeLabel");
+ _maxHeapSizeLabel.setText(Messages.getString("maxHeapSize"));
+ jpanel1.add(_maxHeapSizeLabel,cc.xy(2,10));
+
+ JLabel jlabel1 = new JLabel();
+ jlabel1.setText("MB");
+ jpanel1.add(jlabel1,cc.xy(6,8));
+
+ JLabel jlabel2 = new JLabel();
+ jlabel2.setText("MB");
+ jpanel1.add(jlabel2,cc.xy(6,10));
+
+ _initialHeapSizeField.setName("initialHeapSizeField");
+ jpanel1.add(_initialHeapSizeField,cc.xy(4,8));
+
+ _maxHeapSizeField.setName("maxHeapSizeField");
+ jpanel1.add(_maxHeapSizeField,cc.xy(4,10));
+
+ jpanel1.add(createPanel1(),cc.xywh(2,14,9,1));
+ _maxHeapPercentField.setName("maxHeapPercentField");
+ jpanel1.add(_maxHeapPercentField,cc.xy(8,10));
+
+ _initialHeapPercentField.setName("initialHeapPercentField");
+ jpanel1.add(_initialHeapPercentField,cc.xy(8,8));
+
+ _jdkPreferenceCombo.setName("jdkPreferenceCombo");
+ jpanel1.add(_jdkPreferenceCombo,cc.xywh(8,4,3,1));
+
+ JLabel jlabel3 = new JLabel();
+ jlabel3.setText(Messages.getString("freeMemory"));
+ jpanel1.add(jlabel3,cc.xy(10,8));
+
+ JLabel jlabel4 = new JLabel();
+ jlabel4.setText(Messages.getString("freeMemory"));
+ jpanel1.add(jlabel4,cc.xy(10,10));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9,10,11 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 });
+ return jpanel1;
+ }
+
+ public JPanel createPanel1()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE","CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _varCombo.setName("varCombo");
+ jpanel1.add(_varCombo,cc.xy(3,1));
+
+ _propertyButton.setActionCommand("Add");
+ _propertyButton.setIcon(loadImage("images/edit_add16.png"));
+ _propertyButton.setName("propertyButton");
+ _propertyButton.setText(Messages.getString("property"));
+ _propertyButton.setToolTipText(Messages.getString("propertyTip"));
+ jpanel1.add(_propertyButton,cc.xy(5,1));
+
+ _optionButton.setActionCommand("Add");
+ _optionButton.setIcon(loadImage("images/edit_add16.png"));
+ _optionButton.setName("optionButton");
+ _optionButton.setText(Messages.getString("option"));
+ _optionButton.setToolTipText(Messages.getString("optionTip"));
+ jpanel1.add(_optionButton,cc.xy(7,1));
+
+ _envPropertyButton.setActionCommand("Add");
+ _envPropertyButton.setIcon(loadImage("images/edit_add16.png"));
+ _envPropertyButton.setName("envPropertyButton");
+ _envPropertyButton.setText(Messages.getString("property"));
+ _envPropertyButton.setToolTipText(Messages.getString("propertyTip"));
+ jpanel1.add(_envPropertyButton,cc.xy(5,3));
+
+ JLabel jlabel1 = new JLabel();
+ jlabel1.setText(Messages.getString("varsAndRegistry"));
+ jpanel1.add(jlabel1,cc.xy(1,1));
+
+ JLabel jlabel2 = new JLabel();
+ jlabel2.setIcon(loadImage("images/asterix.gif"));
+ jlabel2.setText(Messages.getString("envVar"));
+ jpanel1.add(jlabel2,cc.xy(1,3));
+
+ _envOptionButton.setActionCommand("Add");
+ _envOptionButton.setIcon(loadImage("images/edit_add16.png"));
+ _envOptionButton.setName("envOptionButton");
+ _envOptionButton.setText(Messages.getString("option"));
+ _envOptionButton.setToolTipText(Messages.getString("optionTip"));
+ jpanel1.add(_envOptionButton,cc.xy(7,3));
+
+ _envVarField.setName("envVarField");
+ jpanel1.add(_envVarField,cc.xy(3,3));
+
+ addFillComponents(jpanel1,new int[]{ 2,4,6 },new int[]{ 2 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/JreForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/JreForm.jfrm
new file mode 100755
index 000000000..1e61237e0
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/JreForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/Messages.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/Messages.java
new file mode 100755
index 000000000..aaf995f80
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/Messages.java
@@ -0,0 +1,55 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.form;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+class Messages {
+ private static final String BUNDLE_NAME = "net.sf.launch4j.form.messages";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/MessagesForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/MessagesForm.java
new file mode 100755
index 000000000..f2e8723da
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/MessagesForm.java
@@ -0,0 +1,183 @@
+package net.sf.launch4j.form;
+
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+public abstract class MessagesForm extends JPanel
+{
+ protected final JTextArea _startupErrTextArea = new JTextArea();
+ protected final JTextArea _bundledJreErrTextArea = new JTextArea();
+ protected final JTextArea _jreVersionErrTextArea = new JTextArea();
+ protected final JTextArea _launcherErrTextArea = new JTextArea();
+ protected final JCheckBox _messagesCheck = new JCheckBox();
+ protected final JTextArea _instanceAlreadyExistsMsgTextArea = new JTextArea();
+
+ /**
+ * Default constructor
+ */
+ public MessagesForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _startupErrTextArea.setName("startupErrTextArea");
+ JScrollPane jscrollpane1 = new JScrollPane();
+ jscrollpane1.setViewportView(_startupErrTextArea);
+ jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane1,cc.xy(4,4));
+
+ _bundledJreErrTextArea.setName("bundledJreErrTextArea");
+ JScrollPane jscrollpane2 = new JScrollPane();
+ jscrollpane2.setViewportView(_bundledJreErrTextArea);
+ jscrollpane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane2,cc.xy(4,6));
+
+ _jreVersionErrTextArea.setName("jreVersionErrTextArea");
+ _jreVersionErrTextArea.setToolTipText(Messages.getString("jreVersionErrTip"));
+ JScrollPane jscrollpane3 = new JScrollPane();
+ jscrollpane3.setViewportView(_jreVersionErrTextArea);
+ jscrollpane3.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane3.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane3,cc.xy(4,8));
+
+ _launcherErrTextArea.setName("launcherErrTextArea");
+ JScrollPane jscrollpane4 = new JScrollPane();
+ jscrollpane4.setViewportView(_launcherErrTextArea);
+ jscrollpane4.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane4.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane4,cc.xy(4,10));
+
+ JLabel jlabel1 = new JLabel();
+ jlabel1.setText(Messages.getString("startupErr"));
+ jpanel1.add(jlabel1,new CellConstraints(2,4,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ JLabel jlabel2 = new JLabel();
+ jlabel2.setText(Messages.getString("bundledJreErr"));
+ jpanel1.add(jlabel2,new CellConstraints(2,6,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ JLabel jlabel3 = new JLabel();
+ jlabel3.setText(Messages.getString("jreVersionErr"));
+ jpanel1.add(jlabel3,new CellConstraints(2,8,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ JLabel jlabel4 = new JLabel();
+ jlabel4.setText(Messages.getString("launcherErr"));
+ jpanel1.add(jlabel4,new CellConstraints(2,10,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ _messagesCheck.setActionCommand("Add version information");
+ _messagesCheck.setName("messagesCheck");
+ _messagesCheck.setText(Messages.getString("addMessages"));
+ jpanel1.add(_messagesCheck,cc.xy(4,2));
+
+ JLabel jlabel5 = new JLabel();
+ jlabel5.setText(Messages.getString("instanceAlreadyExistsMsg"));
+ jpanel1.add(jlabel5,new CellConstraints(2,12,1,1,CellConstraints.DEFAULT,CellConstraints.TOP));
+
+ _instanceAlreadyExistsMsgTextArea.setName("instanceAlreadyExistsMsgTextArea");
+ _instanceAlreadyExistsMsgTextArea.setToolTipText(Messages.getString("instanceAlreadyExistsMsgTip"));
+ JScrollPane jscrollpane5 = new JScrollPane();
+ jscrollpane5.setViewportView(_instanceAlreadyExistsMsgTextArea);
+ jscrollpane5.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ jscrollpane5.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jpanel1.add(jscrollpane5,cc.xy(4,12));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/MessagesForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/MessagesForm.jfrm
new file mode 100755
index 000000000..e8044dfd7
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/MessagesForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SingleInstanceForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SingleInstanceForm.java
new file mode 100755
index 000000000..2bfe724a6
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SingleInstanceForm.java
@@ -0,0 +1,141 @@
+package net.sf.launch4j.form;
+
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public abstract class SingleInstanceForm extends JPanel
+{
+ protected final JLabel _splashFileLabel = new JLabel();
+ protected final JTextField _mutexNameField = new JTextField();
+ protected final JCheckBox _singleInstanceCheck = new JCheckBox();
+ protected final JTextField _windowTitleField = new JTextField();
+ protected final JLabel _splashFileLabel1 = new JLabel();
+
+ /**
+ * Default constructor
+ */
+ public SingleInstanceForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:60DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _splashFileLabel.setIcon(loadImage("images/asterix.gif"));
+ _splashFileLabel.setName("splashFileLabel");
+ _splashFileLabel.setText(Messages.getString("mutexName"));
+ jpanel1.add(_splashFileLabel,cc.xy(2,4));
+
+ _mutexNameField.setName("mutexNameField");
+ _mutexNameField.setToolTipText(Messages.getString("mutexNameTip"));
+ jpanel1.add(_mutexNameField,cc.xywh(4,4,2,1));
+
+ _singleInstanceCheck.setActionCommand("Enable splash screen");
+ _singleInstanceCheck.setName("singleInstanceCheck");
+ _singleInstanceCheck.setText(Messages.getString("enableSingleInstance"));
+ jpanel1.add(_singleInstanceCheck,cc.xywh(4,2,2,1));
+
+ _windowTitleField.setName("windowTitleField");
+ _windowTitleField.setToolTipText(Messages.getString("windowTitleTip"));
+ jpanel1.add(_windowTitleField,cc.xywh(4,6,2,1));
+
+ _splashFileLabel1.setName("splashFileLabel");
+ _splashFileLabel1.setText(Messages.getString("windowTitle"));
+ jpanel1.add(_splashFileLabel1,cc.xy(2,6));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6 },new int[]{ 1,2,3,4,5,6,7 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SingleInstanceForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SingleInstanceForm.jfrm
new file mode 100755
index 000000000..c9d7ce28d
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SingleInstanceForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SplashForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SplashForm.java
new file mode 100755
index 000000000..22a0ed8a3
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SplashForm.java
@@ -0,0 +1,166 @@
+package net.sf.launch4j.form;
+
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public abstract class SplashForm extends JPanel
+{
+ protected final JLabel _splashFileLabel = new JLabel();
+ protected final JLabel _waitForWindowLabel = new JLabel();
+ protected final JLabel _timeoutLabel = new JLabel();
+ protected final JCheckBox _timeoutErrCheck = new JCheckBox();
+ protected final JTextField _splashFileField = new JTextField();
+ protected final JTextField _timeoutField = new JTextField();
+ protected final JButton _splashFileButton = new JButton();
+ protected final JCheckBox _splashCheck = new JCheckBox();
+ protected final JCheckBox _waitForWindowCheck = new JCheckBox();
+
+ /**
+ * Default constructor
+ */
+ public SplashForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:60DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:3DLU:NONE,FILL:26PX:NONE,FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _splashFileLabel.setIcon(loadImage("images/asterix.gif"));
+ _splashFileLabel.setName("splashFileLabel");
+ _splashFileLabel.setText(Messages.getString("splashFile"));
+ jpanel1.add(_splashFileLabel,cc.xy(2,4));
+
+ _waitForWindowLabel.setName("waitForWindowLabel");
+ _waitForWindowLabel.setText(Messages.getString("waitForWindow"));
+ jpanel1.add(_waitForWindowLabel,cc.xy(2,6));
+
+ _timeoutLabel.setIcon(loadImage("images/asterix.gif"));
+ _timeoutLabel.setName("timeoutLabel");
+ _timeoutLabel.setText(Messages.getString("timeout"));
+ jpanel1.add(_timeoutLabel,cc.xy(2,8));
+
+ _timeoutErrCheck.setActionCommand("Signal error on timeout");
+ _timeoutErrCheck.setName("timeoutErrCheck");
+ _timeoutErrCheck.setText(Messages.getString("timeoutErr"));
+ _timeoutErrCheck.setToolTipText(Messages.getString("timeoutErrTip"));
+ jpanel1.add(_timeoutErrCheck,cc.xywh(4,10,2,1));
+
+ _splashFileField.setName("splashFileField");
+ _splashFileField.setToolTipText(Messages.getString("splashFileTip"));
+ jpanel1.add(_splashFileField,cc.xywh(4,4,2,1));
+
+ _timeoutField.setName("timeoutField");
+ _timeoutField.setToolTipText(Messages.getString("timeoutTip"));
+ jpanel1.add(_timeoutField,cc.xy(4,8));
+
+ _splashFileButton.setIcon(loadImage("images/open16.png"));
+ _splashFileButton.setName("splashFileButton");
+ jpanel1.add(_splashFileButton,cc.xy(7,4));
+
+ _splashCheck.setActionCommand("Enable splash screen");
+ _splashCheck.setName("splashCheck");
+ _splashCheck.setText(Messages.getString("enableSplash"));
+ jpanel1.add(_splashCheck,cc.xywh(4,2,2,1));
+
+ _waitForWindowCheck.setActionCommand("Close splash screen when an application window appears");
+ _waitForWindowCheck.setName("waitForWindowCheck");
+ _waitForWindowCheck.setText(Messages.getString("waitForWindowText"));
+ jpanel1.add(_waitForWindowCheck,cc.xywh(4,6,2,1));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SplashForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SplashForm.jfrm
new file mode 100755
index 000000000..114f0e31d
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/SplashForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java
new file mode 100755
index 000000000..5a4d9440c
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java
@@ -0,0 +1,232 @@
+package net.sf.launch4j.form;
+
+import com.jeta.forms.components.separator.TitledSeparator;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public abstract class VersionInfoForm extends JPanel
+{
+ protected final JCheckBox _versionInfoCheck = new JCheckBox();
+ protected final JLabel _fileVersionLabel = new JLabel();
+ protected final JTextField _fileVersionField = new JTextField();
+ protected final TitledSeparator _addVersionInfoSeparator = new TitledSeparator();
+ protected final JLabel _productVersionLabel = new JLabel();
+ protected final JTextField _productVersionField = new JTextField();
+ protected final JLabel _fileDescriptionLabel = new JLabel();
+ protected final JTextField _fileDescriptionField = new JTextField();
+ protected final JLabel _copyrightLabel = new JLabel();
+ protected final JTextField _copyrightField = new JTextField();
+ protected final JLabel _txtFileVersionLabel = new JLabel();
+ protected final JTextField _txtFileVersionField = new JTextField();
+ protected final JLabel _txtProductVersionLabel = new JLabel();
+ protected final JTextField _txtProductVersionField = new JTextField();
+ protected final JLabel _productNameLabel = new JLabel();
+ protected final JTextField _productNameField = new JTextField();
+ protected final JLabel _originalFilenameLabel = new JLabel();
+ protected final JTextField _originalFilenameField = new JTextField();
+ protected final JLabel _internalNameLabel = new JLabel();
+ protected final JTextField _internalNameField = new JTextField();
+ protected final JLabel _companyNameLabel = new JLabel();
+ protected final JTextField _companyNameField = new JTextField();
+
+ /**
+ * Default constructor
+ */
+ public VersionInfoForm()
+ {
+ initializePanel();
+ }
+
+ /**
+ * Adds fill components to empty cells in the first row and first column of the grid.
+ * This ensures that the grid spacing will be the same as shown in the designer.
+ * @param cols an array of column indices in the first row where fill components should be added.
+ * @param rows an array of row indices in the first column where fill components should be added.
+ */
+ void addFillComponents( Container panel, int[] cols, int[] rows )
+ {
+ Dimension filler = new Dimension(10,10);
+
+ boolean filled_cell_11 = false;
+ CellConstraints cc = new CellConstraints();
+ if ( cols.length > 0 && rows.length > 0 )
+ {
+ if ( cols[0] == 1 && rows[0] == 1 )
+ {
+ /** add a rigid area */
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,1) );
+ filled_cell_11 = true;
+ }
+ }
+
+ for( int index = 0; index < cols.length; index++ )
+ {
+ if ( cols[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(cols[index],1) );
+ }
+
+ for( int index = 0; index < rows.length; index++ )
+ {
+ if ( rows[index] == 1 && filled_cell_11 )
+ {
+ continue;
+ }
+ panel.add( Box.createRigidArea( filler ), cc.xy(1,rows[index]) );
+ }
+
+ }
+
+ /**
+ * Helper method to load an image file from the CLASSPATH
+ * @param imageName the package and name of the file to load relative to the CLASSPATH
+ * @return an ImageIcon instance with the specified image file
+ * @throws IllegalArgumentException if the image resource cannot be loaded.
+ */
+ public ImageIcon loadImage( String imageName )
+ {
+ try
+ {
+ ClassLoader classloader = getClass().getClassLoader();
+ java.net.URL url = classloader.getResource( imageName );
+ if ( url != null )
+ {
+ ImageIcon icon = new ImageIcon( url );
+ return icon;
+ }
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+ throw new IllegalArgumentException( "Unable to load image: " + imageName );
+ }
+
+ public JPanel createPanel()
+ {
+ JPanel jpanel1 = new JPanel();
+ FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:60DLU:NONE,FILL:7DLU:NONE,RIGHT:DEFAULT:NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE");
+ CellConstraints cc = new CellConstraints();
+ jpanel1.setLayout(formlayout1);
+
+ _versionInfoCheck.setActionCommand("Add version information");
+ _versionInfoCheck.setName("versionInfoCheck");
+ _versionInfoCheck.setText(Messages.getString("addVersionInfo"));
+ jpanel1.add(_versionInfoCheck,cc.xywh(4,2,5,1));
+
+ _fileVersionLabel.setIcon(loadImage("images/asterix.gif"));
+ _fileVersionLabel.setName("fileVersionLabel");
+ _fileVersionLabel.setText(Messages.getString("fileVersion"));
+ jpanel1.add(_fileVersionLabel,cc.xy(2,4));
+
+ _fileVersionField.setName("fileVersionField");
+ _fileVersionField.setToolTipText(Messages.getString("fileVersionTip"));
+ jpanel1.add(_fileVersionField,cc.xy(4,4));
+
+ _addVersionInfoSeparator.setName("addVersionInfoSeparator");
+ _addVersionInfoSeparator.setText("Additional information");
+ jpanel1.add(_addVersionInfoSeparator,cc.xywh(2,10,7,1));
+
+ _productVersionLabel.setIcon(loadImage("images/asterix.gif"));
+ _productVersionLabel.setName("productVersionLabel");
+ _productVersionLabel.setText(Messages.getString("productVersion"));
+ jpanel1.add(_productVersionLabel,cc.xy(2,12));
+
+ _productVersionField.setName("productVersionField");
+ _productVersionField.setToolTipText(Messages.getString("productVersionTip"));
+ jpanel1.add(_productVersionField,cc.xy(4,12));
+
+ _fileDescriptionLabel.setIcon(loadImage("images/asterix.gif"));
+ _fileDescriptionLabel.setName("fileDescriptionLabel");
+ _fileDescriptionLabel.setText(Messages.getString("fileDescription"));
+ jpanel1.add(_fileDescriptionLabel,cc.xy(2,6));
+
+ _fileDescriptionField.setName("fileDescriptionField");
+ _fileDescriptionField.setToolTipText(Messages.getString("fileDescriptionTip"));
+ jpanel1.add(_fileDescriptionField,cc.xywh(4,6,5,1));
+
+ _copyrightLabel.setIcon(loadImage("images/asterix.gif"));
+ _copyrightLabel.setName("copyrightLabel");
+ _copyrightLabel.setText(Messages.getString("copyright"));
+ jpanel1.add(_copyrightLabel,cc.xy(2,8));
+
+ _copyrightField.setName("copyrightField");
+ jpanel1.add(_copyrightField,cc.xywh(4,8,5,1));
+
+ _txtFileVersionLabel.setIcon(loadImage("images/asterix.gif"));
+ _txtFileVersionLabel.setName("txtFileVersionLabel");
+ _txtFileVersionLabel.setText(Messages.getString("txtFileVersion"));
+ jpanel1.add(_txtFileVersionLabel,cc.xy(6,4));
+
+ _txtFileVersionField.setName("txtFileVersionField");
+ _txtFileVersionField.setToolTipText(Messages.getString("txtFileVersionTip"));
+ jpanel1.add(_txtFileVersionField,cc.xy(8,4));
+
+ _txtProductVersionLabel.setIcon(loadImage("images/asterix.gif"));
+ _txtProductVersionLabel.setName("txtProductVersionLabel");
+ _txtProductVersionLabel.setText(Messages.getString("txtProductVersion"));
+ jpanel1.add(_txtProductVersionLabel,cc.xy(6,12));
+
+ _txtProductVersionField.setName("txtProductVersionField");
+ _txtProductVersionField.setToolTipText(Messages.getString("txtProductVersionTip"));
+ jpanel1.add(_txtProductVersionField,cc.xy(8,12));
+
+ _productNameLabel.setIcon(loadImage("images/asterix.gif"));
+ _productNameLabel.setName("productNameLabel");
+ _productNameLabel.setText(Messages.getString("productName"));
+ jpanel1.add(_productNameLabel,cc.xy(2,14));
+
+ _productNameField.setName("productNameField");
+ jpanel1.add(_productNameField,cc.xywh(4,14,5,1));
+
+ _originalFilenameLabel.setIcon(loadImage("images/asterix.gif"));
+ _originalFilenameLabel.setName("originalFilenameLabel");
+ _originalFilenameLabel.setText(Messages.getString("originalFilename"));
+ jpanel1.add(_originalFilenameLabel,cc.xy(2,20));
+
+ _originalFilenameField.setName("originalFilenameField");
+ _originalFilenameField.setToolTipText(Messages.getString("originalFilenameTip"));
+ jpanel1.add(_originalFilenameField,cc.xywh(4,20,5,1));
+
+ _internalNameLabel.setIcon(loadImage("images/asterix.gif"));
+ _internalNameLabel.setName("internalNameLabel");
+ _internalNameLabel.setText(Messages.getString("internalName"));
+ jpanel1.add(_internalNameLabel,cc.xy(2,18));
+
+ _internalNameField.setName("internalNameField");
+ _internalNameField.setToolTipText(Messages.getString("internalNameTip"));
+ jpanel1.add(_internalNameField,cc.xywh(4,18,5,1));
+
+ _companyNameLabel.setName("companyNameLabel");
+ _companyNameLabel.setText(Messages.getString("companyName"));
+ jpanel1.add(_companyNameLabel,cc.xy(2,16));
+
+ _companyNameField.setName("companyNameField");
+ jpanel1.add(_companyNameField,cc.xywh(4,16,5,1));
+
+ addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21 });
+ return jpanel1;
+ }
+
+ /**
+ * Initializer
+ */
+ protected void initializePanel()
+ {
+ setLayout(new BorderLayout());
+ add(createPanel(), BorderLayout.CENTER);
+ }
+
+
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm
new file mode 100755
index 000000000..32eb136c8
Binary files /dev/null and b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm differ
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/messages.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/messages.properties
new file mode 100755
index 000000000..1be6c9584
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/messages.properties
@@ -0,0 +1,146 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+log=Log
+
+outfile=Output file:
+outfileTip=Output executable file.
+customProcName=Custom process name and XP style manifest
+stayAlive=Stay alive after launching a GUI application
+manifest=Manifest:
+manifestTip=Wrapper's manifest for User Account Control, will not enable XP styles!
+icon=Icon:
+iconTip=Application icon.
+jar=Jar:
+jarTip=Application jar.
+dontWrapJar=Dont't wrap the jar, launch only
+cmdLine=Command line args:
+cmdLineTip=Constant command line arguments passed to the application.
+options=Options:
+chdir=Change dir:
+chdirTip=Change current directory to a location relative to the executable. Empty field has no effect, . - changes directory to the exe location.
+priority=Process priority:
+normalPriority=Normal
+idlePriority=Idle
+highPriority=High
+downloadAndSupport=Java download and support
+errorTitle=Error title:
+errorTitleTip=Launch4j signals errors using a message box, you can set it's title to the application's name.
+downloadUrl=Java download URL:
+supportUrl=Support URL:
+
+new=New
+accept=Accept
+remove=Remove
+customClassPath=Custom classpath
+classPath=Classpath:
+mainClass=Main class:
+editClassPath=Edit item:
+importClassPath=Import attributes from a jar's manifest.
+
+headerType=Header type:
+gui=GUI
+console=Console
+objectFiles=Object files:
+libs=w32api:
+linkerOptions=Custom header - linker options
+
+enableSingleInstance=Allow only a single instance of the application
+mutexName=Mutex name
+mutexNameTip=Mutex name that will uniquely identify your application.
+windowTitle=Window title
+windowTitleTip=Title of the GUI application window to bring up on attempt to start a next instance.
+
+jrePath=Bundled JRE path:
+jrePathTip=Bundled JRE path relative to the executable or absolute.
+jreMin=Min JRE version:
+jreMax=Max JRE version:
+dontUsePrivateJres=Don't use private JREs
+jvmOptions=JVM options:
+jvmOptionsTip=Accepts everything you would normally pass to java/javaw launcher: assertion options, system properties and X options.
+initialHeapSize=Initial heap size:
+maxHeapSize=Max heap size:
+freeMemory=% of free memory
+jdkPreference=JDK/JRE preference:
+addVariables=Add variables:
+addVariablesTip=Add special variable or map environment variables to system properties.
+exeDirVarTip=Executable's runtime directory path.
+exeFileVarTip=Executable's runtime file path (directory and filename).
+varsAndRegistry=Variables / registry:
+envVar=Environment var:
+property=Property
+propertyTip=Map a variable to a system property.
+option=Option
+optionTip=Pass a JVM option using a variable.
+
+setVariables=Set variables:
+
+enableSplash=Enable splash screen
+splashFile=Splash file:
+splashFileTip=Splash screen file in BMP format.
+waitForWindow=Wait for window
+waitForWindowText=Close splash screen when an application window appears
+timeout=Timeout [s]:
+timeoutTip=Number of seconds after which the splash screen must close. Splash timeout may cause an error depending on splashTimeoutErr property.
+timeoutErr=Signal error on timeout
+timeoutErrTip=True signals an error on splash timeout, false closes the splash screen quietly.
+
+version=Version
+additionalInfo=Additional information
+addVersionInfo=Add version information
+fileVersion=File version:
+fileVersionTip=Version number 'x.x.x.x'
+productVersion=Product version:
+productVersionTip=Version number 'x.x.x.x'
+fileDescription=File description:
+fileDescriptionTip=File description presented to the user.
+copyright=Copyright:
+txtFileVersion=Free form:
+txtFileVersionTip=Free form file version, for example '1.20.RC1'.
+txtProductVersion=Free form:
+txtProductVersionTip=Free form product version, for example '1.20.RC1'.
+productName=Product name:
+originalFilename=Original filename:
+originalFilenameTip=Original name of the file without the path. Allows to determine whether a file has been renamed by a user.
+internalName=Internal name:
+internalNameTip=Internal name without extension, original filename or module name for example.
+companyName=Company name:
+
+addMessages=Add custom messages
+startupErr=Startup error:
+bundledJreErr=Bundled JRE error:
+jreVersionErr=JRE version error:
+jreVersionErrTip=Launch4j will append the required version number at the end of this message.
+launcherErr=Launcher error:
+instanceAlreadyExistsMsg=Inst. already exists:
+instanceAlreadyExistsMsgTip=Message displayed by single instance console applications if an instance already exists.
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/form/messages_es.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/messages_es.properties
new file mode 100755
index 000000000..50e2d7587
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/form/messages_es.properties
@@ -0,0 +1,118 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal, Patricio Martínez Ros
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+log = Registro
+
+outfile = Fichero de salida
+outfileTip = Fichero ejecutable de salida.
+errorTitle = T\u00EDtulo de error
+errorTitleTip = Launch4j indica los errores usando una ventana de mensaje, usted puede ponerle el nombre de la aplicaci\u00F3n a esta ventana.
+customProcName = Nombre personalizado del proceso
+stayAlive = Mantener abierto despu\u00E9s de lanzar una aplicaci\u00F3n GUI
+icon = Icono
+iconTip = Icono de la aplicaci\u00F3n.
+jar = Jar
+jarTip = Jar de la aplicaci\u00F3n.
+dontWrapJar = No empaquetar el jar, s\u00F3lo lanzar
+cmdLine = Argumentos del jar
+cmdLine = Argumentos de l\u00EDnea de \u00F3rdenes pasados a la aplicaci\u00F3n.
+options = Opciones
+chdir = Cambiar al directorio
+chdirTip = Cambia el directorio actual a la localizaci\u00F3n relativa al ejecutable. Si el campo se deja vac\u00EDo, no tiene efecto, . - cambia el directorio a la localizaci\u00F3n del exe.
+headerType = Tipo de cabecera
+gui = GUI
+console = Consola
+objectFiles = Ficheros objeto
+libs = w32api
+linkerOptions = Cabecera personalizada - opciones del enlazador
+jrePath = Ruta del JRE
+jrePathTip = Ruta relativa al ejecutable del JRE.
+jreMin = Versi\u00F3n m\u00EDnima del JRE
+jreMax = Versi\u00F3n m\u00E1xima del JRE
+jvmOptions = Argumentos de la JVM
+jvmOptionsTip = Acepta cualquier argumento que normalmente se le pasar\u00EDa al lanzador java/javaw\: opciones assertion, propiedades de sistema y opciones X.
+initialHeapSize = Tama\u00F1o inicial de la pila
+maxHeapSize = Tama\u00F1o m\u00E1ximo de la pila
+freeMemory=% of free memory
+addVariables = A\u00F1adir variables
+addVariablesTip = A\u00F1adir una variable especial o mapear variables de entorno a las propiedades del sistema.
+exeDirVarTip = Ruta del directorio del ejecutable.
+exeFileVarTip = Ruta del fichero ejecutable (directorio y nombre del fichero).
+other = Otra
+otherTip = Mapear una variable de entorno a una propiedad del sistema.
+otherVarTip = Variable de entorno que mapear.
+add = A\u00F1adir
+specifyVar = Especificar variable de entorno que a\u00F1adir.
+enableSplash = Activar pantalla de bienvenida
+splashFile = Imagen
+splashFileTip = Imagen en formato BMP para la pantalla de bienvenida.
+waitForWindow = Esperar la ventana
+waitForWindowText = Cerrar la pantalla de bienvenida cuando aparezca una ventana de la aplicaci\u00F3n
+timeout = Tiempo de espera [s]
+timeoutTip = Numero de segundos despu\u00E9s de los que la pantalla de bienvenida se debe cerrar. Esta propiedad puede causar provocar un error dependiendo de la propiedad splashTimeoutErr.
+timeoutErr = Se\u00F1al de error asociada al tiempo de espera
+timeoutErrTip = Marcado (true) se\u00F1ala un error despu\u00E9s del tiempo de espera de la pantalla de bienvenida, no marcado (false) cierra la pantalla de bienvenida silenciosamente
+addVersionInfo = A\u00F1ade informaci\u00F3n sobre la versi\u00F3n
+fileVersion = Versi\u00F3n del fichero
+fileVersionTip = N\u00FAmero de versi\u00F3n 'x.x.x.x'
+additionalInfo = Informaci\u00F3n adicional
+productVersion = Versi\u00F3n del producto
+productVersionTip = N\u00FAmero de versi\u00F3n 'x.x.x.x'
+fileDescription = Descripci\u00F3n del fichero
+fileDescriptionTip = Descripci\u00F3n del fichero que se le muestra al usuario.
+copyright = Copyright
+txtFileVersion = Forma libre
+txtFileVersionTip = Forma libre de versi\u00F3n, por ejemplo '1.20.RC1'.
+txtProductVersion = Forma libre
+txtProductVersionTip = Forma libre del producto, por ejemplo '1.20.RC1'.
+productName = Nombre del producto
+originalFilename = Nombre original del fichero
+originalFilenameTip = Nombre original del fichero sin la ruta. Permite determinar si un fichero ha sido renombrado por un usuario.
+internalName = Nombre interno
+internalNameTip = Nombre interno sin extensi\u00F3n, el nombre original del fichero o el m\u00F3dulo, por ejemplo.
+companyName = Nombre de la organizaci\u00F3n
+
+addMessages=Add custom messages
+startupErr=Startup error:
+bundledJreErr=Bundled JRE error:
+jreVersionErr=JRE version error:
+jreVersionErrTip=Launch4j will append the required version number at the end of this message.
+launcherErr=Launcher error:
+instanceAlreadyExistsMsg=Inst. already exists:
+instanceAlreadyExistsMsgTip=Message displayed by single instance console applications if an instance already exists.
+
+enableSingleInstance=Allow only a single instance of the application
+mutexName=Mutex name
+mutexNameTip=Mutex name that will uniquely identify your application.
+windowTitle=Window title
+windowTitleTip=Title of the application window to bring up on attempt to start a next instance.
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/AbstractAcceptListener.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/AbstractAcceptListener.java
new file mode 100755
index 000000000..5265e6436
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/AbstractAcceptListener.java
@@ -0,0 +1,75 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import java.awt.Color;
+import java.awt.event.ActionListener;
+
+import javax.swing.JTextField;
+
+import net.sf.launch4j.binding.Binding;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public abstract class AbstractAcceptListener implements ActionListener {
+ final JTextField _field;
+
+ public AbstractAcceptListener(JTextField f, boolean listen) {
+ _field = f;
+ if (listen) {
+ _field.addActionListener(this);
+ }
+ }
+
+ protected String getText() {
+ return _field.getText();
+ }
+
+ protected void clear() {
+ _field.setText("");
+ _field.requestFocusInWindow();
+ }
+
+ protected void signalViolation(String msg) {
+ final Color bg = _field.getBackground();
+ _field.setBackground(Binding.INVALID_COLOR);
+ MainFrame.getInstance().warn(msg);
+ _field.setBackground(bg);
+ _field.requestFocusInWindow();
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/BasicFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/BasicFormImpl.java
new file mode 100755
index 000000000..01ebe8adf
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/BasicFormImpl.java
@@ -0,0 +1,101 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import javax.swing.JFileChooser;
+import javax.swing.JRadioButton;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import net.sf.launch4j.FileChooserFilter;
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.form.BasicForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class BasicFormImpl extends BasicForm {
+
+ public BasicFormImpl(Bindings bindings, JFileChooser fc) {
+ bindings.add("outfile", _outfileField)
+ .add("dontWrapJar", _dontWrapJarCheck)
+ .add("jar", _jarField)
+ .add("manifest", _manifestField)
+ .add("icon", _iconField)
+ .add("cmdLine", _cmdLineField)
+ .add("errTitle", _errorTitleField)
+ .add("downloadUrl", _downloadUrlField, Config.DOWNLOAD_URL)
+ .add("supportUrl", _supportUrlField)
+ .add("chdir", _chdirField)
+ .add("priorityIndex", new JRadioButton[] { _normalPriorityRadio,
+ _idlePriorityRadio,
+ _highPriorityRadio })
+ .add("customProcName", _customProcNameCheck)
+ .add("stayAlive", _stayAliveCheck);
+
+ _dontWrapJarCheck.addChangeListener(new DontWrapJarChangeListener());
+
+ _outfileButton.addActionListener(new BrowseActionListener(true, fc,
+ new FileChooserFilter("Windows executables (.exe)", ".exe"),
+ _outfileField));
+ _jarButton.addActionListener(new BrowseActionListener(false, fc,
+ new FileChooserFilter("Jar files", ".jar"), _jarField));
+ _manifestButton.addActionListener(new BrowseActionListener(false, fc,
+ new FileChooserFilter("Manifest files (.manifest)", ".manifest"),
+ _manifestField));
+ _iconButton.addActionListener(new BrowseActionListener(false, fc,
+ new FileChooserFilter("Icon files (.ico)", ".ico"), _iconField));
+ }
+
+ private class DontWrapJarChangeListener implements ChangeListener {
+
+ public void stateChanged(ChangeEvent e) {
+ boolean dontWrap = _dontWrapJarCheck.isSelected();
+ if (dontWrap) {
+ _jarLabel.setIcon(loadImage("images/asterix-o.gif"));
+ _jarLabel.setText(Messages.getString("jarPath"));
+ _jarField.setToolTipText(Messages.getString("jarPathTip"));
+ } else {
+ _jarLabel.setIcon(loadImage("images/asterix.gif"));
+ _jarLabel.setText(Messages.getString("jar"));
+ _jarField.setToolTipText(Messages.getString("jarTip"));
+ }
+ _jarButton.setEnabled(!dontWrap);
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/BrowseActionListener.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/BrowseActionListener.java
new file mode 100755
index 000000000..89a5017ee
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/BrowseActionListener.java
@@ -0,0 +1,79 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JFileChooser;
+import javax.swing.JTextField;
+
+import net.sf.launch4j.FileChooserFilter;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class BrowseActionListener implements ActionListener {
+ private final boolean _save;
+ private final JFileChooser _fileChooser;
+ private final FileChooserFilter _filter;
+ private final JTextField _field;
+
+ public BrowseActionListener(boolean save, JFileChooser fileChooser,
+ FileChooserFilter filter, JTextField field) {
+ _save = save;
+ _fileChooser = fileChooser;
+ _filter = filter;
+ _field = field;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (!_field.isEnabled()) {
+ return;
+ }
+ _fileChooser.setFileFilter(_filter);
+ _fileChooser.setSelectedFile(new File(""));
+ int result = _save
+ ? _fileChooser.showSaveDialog(MainFrame.getInstance())
+ : _fileChooser.showOpenDialog(MainFrame.getInstance());
+ if (result == JFileChooser.APPROVE_OPTION) {
+ _field.setText(_fileChooser.getSelectedFile().getPath());
+ }
+ _fileChooser.removeChoosableFileFilter(_filter);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/ClassPathFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/ClassPathFormImpl.java
new file mode 100755
index 000000000..65d82096e
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/ClassPathFormImpl.java
@@ -0,0 +1,222 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JFileChooser;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import net.sf.launch4j.FileChooserFilter;
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.binding.Validator;
+import net.sf.launch4j.config.ClassPath;
+import net.sf.launch4j.form.ClassPathForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class ClassPathFormImpl extends ClassPathForm {
+ private final JFileChooser _fileChooser;
+ private final FileChooserFilter _filter
+ = new FileChooserFilter("Executable jar", ".jar");
+
+ public ClassPathFormImpl(Bindings bindings, JFileChooser fc) {
+ bindings.addOptComponent("classPath", ClassPath.class, _classpathCheck)
+ .add("classPath.mainClass", _mainclassField)
+ .add("classPath.paths", _classpathList);
+ _fileChooser = fc;
+
+ ClasspathCheckListener cpl = new ClasspathCheckListener();
+ _classpathCheck.addChangeListener(cpl);
+ cpl.stateChanged(null);
+
+ _classpathList.setModel(new DefaultListModel());
+ _classpathList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ _classpathList.addListSelectionListener(new ClasspathSelectionListener());
+
+ _newClasspathButton.addActionListener(new NewClasspathListener());
+ _acceptClasspathButton.addActionListener(
+ new AcceptClasspathListener(_classpathField));
+ _removeClasspathButton.addActionListener(new RemoveClasspathListener());
+ _importClasspathButton.addActionListener(new ImportClasspathListener());
+ _classpathUpButton.addActionListener(new MoveUpListener());
+ _classpathDownButton.addActionListener(new MoveDownListener());
+ }
+
+ private class ClasspathCheckListener implements ChangeListener {
+ public void stateChanged(ChangeEvent e) {
+ boolean on = _classpathCheck.isSelected();
+ _importClasspathButton.setEnabled(on);
+ _classpathUpButton.setEnabled(on);
+ _classpathDownButton.setEnabled(on);
+ _classpathField.setEnabled(on);
+ _newClasspathButton.setEnabled(on);
+ _acceptClasspathButton.setEnabled(on);
+ _removeClasspathButton.setEnabled(on);
+ }
+ }
+
+ private class NewClasspathListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ _classpathList.clearSelection();
+ _classpathField.setText("");
+ _classpathField.requestFocusInWindow();
+ }
+ }
+
+ private class AcceptClasspathListener extends AbstractAcceptListener {
+ public AcceptClasspathListener(JTextField f) {
+ super(f, true);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String cp = getText();
+ if (Validator.isEmpty(cp)) {
+ signalViolation(Messages.getString("specifyClassPath"));
+ return;
+ }
+ DefaultListModel model = (DefaultListModel) _classpathList.getModel();
+ if (_classpathList.isSelectionEmpty()) {
+ model.addElement(cp);
+ clear();
+ } else {
+ model.setElementAt(cp, _classpathList.getSelectedIndex());
+ }
+ }
+ }
+
+ private class ClasspathSelectionListener implements ListSelectionListener {
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting()) {
+ return;
+ }
+ if (_classpathList.isSelectionEmpty()) {
+ _classpathField.setText("");
+ } else {
+ _classpathField.setText((String) _classpathList.getSelectedValue());
+ }
+ _classpathField.requestFocusInWindow();
+ }
+ }
+
+ private class RemoveClasspathListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ if (_classpathList.isSelectionEmpty()
+ || !MainFrame.getInstance().confirm(
+ Messages.getString("confirmClassPathRemoval"))) {
+ return;
+ }
+ DefaultListModel model = (DefaultListModel) _classpathList.getModel();
+ while (!_classpathList.isSelectionEmpty()) {
+ model.remove(_classpathList.getSelectedIndex());
+ }
+ }
+ }
+
+ private class MoveUpListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ int x = _classpathList.getSelectedIndex();
+ if (x < 1) {
+ return;
+ }
+ DefaultListModel model = (DefaultListModel) _classpathList.getModel();
+ Object o = model.get(x - 1);
+ model.set(x - 1, model.get(x));
+ model.set(x, o);
+ _classpathList.setSelectedIndex(x - 1);
+ }
+ }
+
+ private class MoveDownListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ DefaultListModel model = (DefaultListModel) _classpathList.getModel();
+ int x = _classpathList.getSelectedIndex();
+ if (x == -1 || x >= model.getSize() - 1) {
+ return;
+ }
+ Object o = model.get(x + 1);
+ model.set(x + 1, model.get(x));
+ model.set(x, o);
+ _classpathList.setSelectedIndex(x + 1);
+ }
+ }
+
+ private class ImportClasspathListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ _fileChooser.setFileFilter(_filter);
+ _fileChooser.setSelectedFile(new File(""));
+ if (_fileChooser.showOpenDialog(MainFrame.getInstance())
+ == JFileChooser.APPROVE_OPTION) {
+ JarFile jar = new JarFile(_fileChooser.getSelectedFile());
+ if (jar.getManifest() == null) {
+ jar.close();
+ MainFrame.getInstance().info(Messages.getString("noManifest"));
+ return;
+ }
+ Attributes attr = jar.getManifest().getMainAttributes();
+ String mainClass = (String) attr.getValue("Main-Class");
+ String classPath = (String) attr.getValue("Class-Path");
+ jar.close();
+ _mainclassField.setText(mainClass != null ? mainClass : "");
+ DefaultListModel model = new DefaultListModel();
+ if (classPath != null) {
+ String[] paths = classPath.split(" ");
+ for (int i = 0; i < paths.length; i++) {
+ model.addElement(paths[i]);
+ }
+ }
+ _classpathList.setModel(model);
+ }
+ } catch (IOException ex) {
+ MainFrame.getInstance().warn(ex.getMessage());
+ }
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/ConfigFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/ConfigFormImpl.java
new file mode 100755
index 000000000..d29720642
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/ConfigFormImpl.java
@@ -0,0 +1,100 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 10, 2005
+ */
+package net.sf.launch4j.formimpl;
+
+import javax.swing.BorderFactory;
+import javax.swing.JFileChooser;
+import javax.swing.JTextArea;
+
+import net.sf.launch4j.binding.Binding;
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.binding.IValidatable;
+import net.sf.launch4j.form.ConfigForm;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class ConfigFormImpl extends ConfigForm {
+ private final Bindings _bindings = new Bindings();
+ private final JFileChooser _fileChooser = new FileChooser(ConfigFormImpl.class);
+
+ public ConfigFormImpl() {
+ _tab.setBorder(BorderFactory.createMatteBorder(0, -1, -1, -1, getBackground()));
+ _tab.addTab(Messages.getString("tab.basic"),
+ new BasicFormImpl(_bindings, _fileChooser));
+ _tab.addTab(Messages.getString("tab.classpath"),
+ new ClassPathFormImpl(_bindings, _fileChooser));
+ _tab.addTab(Messages.getString("tab.header"),
+ new HeaderFormImpl(_bindings));
+ _tab.addTab(Messages.getString("tab.singleInstance"),
+ new SingleInstanceFormImpl(_bindings));
+ _tab.addTab(Messages.getString("tab.jre"),
+ new JreFormImpl(_bindings, _fileChooser));
+ _tab.addTab(Messages.getString("tab.envVars"),
+ new EnvironmentVarsFormImpl(_bindings));
+ _tab.addTab(Messages.getString("tab.splash"),
+ new SplashFormImpl(_bindings, _fileChooser));
+ _tab.addTab(Messages.getString("tab.version"),
+ new VersionInfoFormImpl(_bindings, _fileChooser));
+ _tab.addTab(Messages.getString("tab.messages"),
+ new MessagesFormImpl(_bindings));
+ }
+
+ public void clear(IValidatable bean) {
+ _bindings.clear(bean);
+ }
+
+ public void put(IValidatable bean) {
+ _bindings.put(bean);
+ }
+
+ public void get(IValidatable bean) {
+ _bindings.get(bean);
+ }
+
+ public boolean isModified() {
+ return _bindings.isModified();
+ }
+
+ public JTextArea getLogTextArea() {
+ return _logTextArea;
+ }
+
+ public Binding getBinding(String property) {
+ return _bindings.getBinding(property);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/EnvironmentVarsFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/EnvironmentVarsFormImpl.java
new file mode 100755
index 000000000..2f325fe3c
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/EnvironmentVarsFormImpl.java
@@ -0,0 +1,50 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jun 10, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.form.EnvironmentVarsForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class EnvironmentVarsFormImpl extends EnvironmentVarsForm {
+
+ public EnvironmentVarsFormImpl(Bindings bindings) {
+ bindings.add("variables", _envVarsTextArea);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/FileChooser.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/FileChooser.java
new file mode 100755
index 000000000..c1b984e58
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/FileChooser.java
@@ -0,0 +1,65 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Jul 19, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import java.io.File;
+import java.util.prefs.Preferences;
+
+import javax.swing.JFileChooser;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class FileChooser extends JFileChooser {
+ private final Preferences _prefs;
+ private final String _key;
+
+ public FileChooser(Class clazz) {
+ _prefs = Preferences.userNodeForPackage(clazz);
+ _key = "currentDir-"
+ + clazz.getName().substring(clazz.getName().lastIndexOf('.') + 1);
+ String path = _prefs.get(_key, null);
+ if (path != null) {
+ setCurrentDirectory(new File(path));
+ }
+ }
+
+ public void approveSelection() {
+ _prefs.put(_key, getCurrentDirectory().getPath());
+ super.approveSelection();
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/GlassPane.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/GlassPane.java
new file mode 100755
index 000000000..c1b1d8dd4
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/GlassPane.java
@@ -0,0 +1,67 @@
+package net.sf.launch4j.formimpl;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.AWTEventListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+
+/**
+ * This is the glass pane class that intercepts screen interactions during
+ * system busy states.
+ *
+ * Based on JavaWorld article by Yexin Chen.
+ */
+public class GlassPane extends JComponent implements AWTEventListener {
+ private final Window _window;
+
+ public GlassPane(Window w) {
+ _window = w;
+ addMouseListener(new MouseAdapter() {});
+ addKeyListener(new KeyAdapter() {});
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ }
+
+ /**
+ * Receives all key events in the AWT and processes the ones that originated
+ * from the current window with the glass pane.
+ *
+ * @param event
+ * the AWTEvent that was fired
+ */
+ public void eventDispatched(AWTEvent event) {
+ Object source = event.getSource();
+ if (event instanceof KeyEvent
+ && source instanceof Component) {
+ /*
+ * If the event originated from the window w/glass pane,
+ * consume the event.
+ */
+ if ((SwingUtilities.windowForComponent((Component) source) == _window)) {
+ ((KeyEvent) event).consume();
+ }
+ }
+ }
+
+ /**
+ * Sets the glass pane as visible or invisible. The mouse cursor will be set
+ * accordingly.
+ */
+ public void setVisible(boolean visible) {
+ if (visible) {
+ // Start receiving all events and consume them if necessary
+ Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
+ } else {
+ // Stop receiving all events
+ Toolkit.getDefaultToolkit().removeAWTEventListener(this);
+ }
+ super.setVisible(visible);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java
new file mode 100755
index 000000000..accfaa9de
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java
@@ -0,0 +1,102 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JRadioButton;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import net.sf.launch4j.binding.Binding;
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.config.ConfigPersister;
+import net.sf.launch4j.form.HeaderForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class HeaderFormImpl extends HeaderForm {
+ private final Bindings _bindings;
+
+ public HeaderFormImpl(Bindings bindings) {
+ _bindings = bindings;
+ _bindings.add("headerTypeIndex", new JRadioButton[] { _guiHeaderRadio,
+ _consoleHeaderRadio })
+ .add("headerObjects", "customHeaderObjects", _headerObjectsCheck,
+ _headerObjectsTextArea)
+ .add("libs", "customLibs", _libsCheck, _libsTextArea);
+
+ _guiHeaderRadio.addChangeListener(new HeaderTypeChangeListener());
+ _headerObjectsCheck.addActionListener(new HeaderObjectsActionListener());
+ _libsCheck.addActionListener(new LibsActionListener());
+ }
+
+ private class HeaderTypeChangeListener implements ChangeListener {
+ public void stateChanged(ChangeEvent e) {
+ Config c = ConfigPersister.getInstance().getConfig();
+ c.setHeaderType(_guiHeaderRadio.isSelected() ? Config.GUI_HEADER
+ : Config.CONSOLE_HEADER);
+ if (!_headerObjectsCheck.isSelected()) {
+ Binding b = _bindings.getBinding("headerObjects");
+ b.put(c);
+ }
+ }
+ }
+
+ private class HeaderObjectsActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ if (!_headerObjectsCheck.isSelected()) {
+ ConfigPersister.getInstance().getConfig().setHeaderObjects(null);
+ Binding b = _bindings.getBinding("headerObjects");
+ b.put(ConfigPersister.getInstance().getConfig());
+ }
+ }
+ }
+
+ private class LibsActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ if (!_libsCheck.isSelected()) {
+ ConfigPersister.getInstance().getConfig().setLibs(null);
+ Binding b = _bindings.getBinding("libs");
+ b.put(ConfigPersister.getInstance().getConfig());
+ }
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/JreFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/JreFormImpl.java
new file mode 100755
index 000000000..48a2f18e8
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/JreFormImpl.java
@@ -0,0 +1,166 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JFileChooser;
+import javax.swing.JTextField;
+
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.binding.Validator;
+import net.sf.launch4j.form.JreForm;
+import net.sf.launch4j.config.Jre;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class JreFormImpl extends JreForm {
+
+ public JreFormImpl(Bindings bindings, JFileChooser fc) {
+ _jdkPreferenceCombo.setModel(new DefaultComboBoxModel(new String[] {
+ Messages.getString("jdkPreference.jre.only"),
+ Messages.getString("jdkPreference.prefer.jre"),
+ Messages.getString("jdkPreference.prefer.jdk"),
+ Messages.getString("jdkPreference.jdk.only")}));
+ bindings.add("jre.path", _jrePathField)
+ .add("jre.minVersion", _jreMinField)
+ .add("jre.maxVersion", _jreMaxField)
+ .add("jre.jdkPreferenceIndex", _jdkPreferenceCombo,
+ Jre.DEFAULT_JDK_PREFERENCE_INDEX)
+ .add("jre.initialHeapSize", _initialHeapSizeField)
+ .add("jre.initialHeapPercent", _initialHeapPercentField)
+ .add("jre.maxHeapSize", _maxHeapSizeField)
+ .add("jre.maxHeapPercent", _maxHeapPercentField)
+ .add("jre.options", _jvmOptionsTextArea);
+
+ _varCombo.setModel(new DefaultComboBoxModel(new String[] {
+ "EXEDIR", "EXEFILE", "PWD", "OLDPWD",
+ "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE",
+ "HKEY_USERS", "HKEY_CURRENT_CONFIG" }));
+
+ _varCombo.addActionListener(new VarComboActionListener());
+ _varCombo.setSelectedIndex(0);
+
+ _propertyButton.addActionListener(new PropertyActionListener());
+ _optionButton.addActionListener(new OptionActionListener());
+
+ _envPropertyButton.addActionListener(new EnvPropertyActionListener(_envVarField));
+ _envOptionButton.addActionListener(new EnvOptionActionListener(_envVarField));
+ }
+
+ private class VarComboActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ _optionButton.setEnabled(((String) _varCombo.getSelectedItem())
+ .startsWith("HKEY_"));
+ }
+ }
+
+ private class PropertyActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ final int pos = _jvmOptionsTextArea.getCaretPosition();
+ final String var = (String) _varCombo.getSelectedItem();
+ if (var.startsWith("HKEY_")) {
+ _jvmOptionsTextArea.insert("-Dreg.key=\"%"
+ + var + "\\\\...%\"\n", pos);
+ } else {
+ _jvmOptionsTextArea.insert("-Dlaunch4j." + var.toLowerCase()
+ + "=\"%" + var + "%\"\n", pos);
+ }
+ }
+ }
+
+ private class OptionActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ final int pos = _jvmOptionsTextArea.getCaretPosition();
+ final String var = (String) _varCombo.getSelectedItem();
+ if (var.startsWith("HKEY_")) {
+ _jvmOptionsTextArea.insert("%" + var + "\\\\...%\n", pos);
+ } else {
+ _jvmOptionsTextArea.insert("%" + var + "%\n", pos);
+ }
+ }
+ }
+
+ private abstract class EnvActionListener extends AbstractAcceptListener {
+ public EnvActionListener(JTextField f, boolean listen) {
+ super(f, listen);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ final int pos = _jvmOptionsTextArea.getCaretPosition();
+ final String var = getText()
+ .replaceAll("\"", "")
+ .replaceAll("%", "");
+ if (Validator.isEmpty(var)) {
+ signalViolation(Messages.getString("specifyVar"));
+ return;
+ }
+ add(var, pos);
+ clear();
+ }
+
+ protected abstract void add(String var, int pos);
+ }
+
+ private class EnvPropertyActionListener extends EnvActionListener {
+ public EnvPropertyActionListener(JTextField f) {
+ super(f, true);
+ }
+
+ protected void add(String var, int pos) {
+ final String prop = var
+ .replaceAll(" ", ".")
+ .replaceAll("_", ".")
+ .toLowerCase();
+ _jvmOptionsTextArea.insert("-Denv." + prop + "=\"%" + var
+ + "%\"\n", pos);
+ }
+ }
+
+ private class EnvOptionActionListener extends EnvActionListener {
+ public EnvOptionActionListener(JTextField f) {
+ super(f, false);
+ }
+
+ protected void add(String var, int pos) {
+ _jvmOptionsTextArea.insert("%" + var + "%\n", pos);
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java
new file mode 100755
index 000000000..4a2cc8715
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java
@@ -0,0 +1,358 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on 2005-05-09
+ */
+package net.sf.launch4j.formimpl;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JToolBar;
+import javax.swing.UIManager;
+
+import com.jgoodies.looks.Options;
+import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
+
+import foxtrot.Task;
+import foxtrot.Worker;
+
+import net.sf.launch4j.Builder;
+import net.sf.launch4j.BuilderException;
+import net.sf.launch4j.ExecException;
+import net.sf.launch4j.FileChooserFilter;
+import net.sf.launch4j.Log;
+import net.sf.launch4j.Main;
+import net.sf.launch4j.Util;
+import net.sf.launch4j.binding.Binding;
+import net.sf.launch4j.binding.BindingException;
+import net.sf.launch4j.binding.InvariantViolationException;
+import net.sf.launch4j.config.Config;
+import net.sf.launch4j.config.ConfigPersister;
+import net.sf.launch4j.config.ConfigPersisterException;
+
+/**
+ * @author Copyright (C) 2005 Grzegorz Kowal
+ */
+public class MainFrame extends JFrame {
+ private static MainFrame _instance;
+
+ private final JToolBar _toolBar;
+ private final JButton _runButton;
+ private final ConfigFormImpl _configForm;
+ private final JFileChooser _fileChooser = new FileChooser(MainFrame.class);
+ private File _outfile;
+ private boolean _saved = false;
+
+ public static void createInstance() {
+ try {
+ Toolkit.getDefaultToolkit().setDynamicLayout(true);
+ System.setProperty("sun.awt.noerasebackground","true");
+
+ // JGoodies
+ Options.setDefaultIconSize(new Dimension(16, 16)); // menu icons
+ Options.setUseNarrowButtons(false);
+ Options.setPopupDropShadowEnabled(true);
+
+ UIManager.setLookAndFeel(new PlasticXPLookAndFeel());
+ _instance = new MainFrame();
+ } catch (Exception e) {
+ System.err.println(e);
+ }
+ }
+
+ public static MainFrame getInstance() {
+ return _instance;
+ }
+
+ public MainFrame() {
+ showConfigName(null);
+ setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ addWindowListener(new MainFrameListener());
+ setGlassPane(new GlassPane(this));
+ _fileChooser.setFileFilter(new FileChooserFilter(
+ Messages.getString("MainFrame.config.files"),
+ new String[] {".xml", ".cfg"}));
+
+ _toolBar = new JToolBar();
+ _toolBar.setFloatable(false);
+ _toolBar.setRollover(true);
+ addButton("images/new.png", Messages.getString("MainFrame.new.config"),
+ new NewActionListener());
+ addButton("images/open.png", Messages.getString("MainFrame.open.config"),
+ new OpenActionListener());
+ addButton("images/save.png", Messages.getString("MainFrame.save.config"),
+ new SaveActionListener());
+ _toolBar.addSeparator();
+ addButton("images/build.png", Messages.getString("MainFrame.build.wrapper"),
+ new BuildActionListener());
+ _runButton = addButton("images/run.png",
+ Messages.getString("MainFrame.test.wrapper"),
+ new RunActionListener());
+ setRunEnabled(false);
+ _toolBar.addSeparator();
+ addButton("images/info.png", Messages.getString("MainFrame.about.launch4j"),
+ new AboutActionListener());
+
+ _configForm = new ConfigFormImpl();
+ getContentPane().setLayout(new BorderLayout());
+ getContentPane().add(_toolBar, BorderLayout.NORTH);
+ getContentPane().add(_configForm, BorderLayout.CENTER);
+ pack();
+ Dimension scr = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension fr = getSize();
+ fr.width += 25;
+ fr.height += 100;
+ setBounds((scr.width - fr.width) / 2, (scr.height - fr.height) / 2,
+ fr.width, fr.height);
+ setVisible(true);
+ }
+
+ private JButton addButton(String iconPath, String tooltip, ActionListener l) {
+ ImageIcon icon = new ImageIcon(MainFrame.class.getClassLoader()
+ .getResource(iconPath));
+ JButton b = new JButton(icon);
+ b.setToolTipText(tooltip);
+ b.addActionListener(l);
+ _toolBar.add(b);
+ return b;
+ }
+
+ public void info(String text) {
+ JOptionPane.showMessageDialog(this,
+ text,
+ Main.getName(),
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ public void warn(String text) {
+ JOptionPane.showMessageDialog(this,
+ text,
+ Main.getName(),
+ JOptionPane.WARNING_MESSAGE);
+ }
+
+ public void warn(InvariantViolationException e) {
+ Binding b = e.getBinding();
+ if (b != null) {
+ b.markInvalid();
+ }
+ warn(e.getMessage());
+ if (b != null) {
+ e.getBinding().markValid();
+ }
+ }
+
+ public boolean confirm(String text) {
+ return JOptionPane.showConfirmDialog(MainFrame.this,
+ text,
+ Messages.getString("MainFrame.confirm"),
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
+ }
+
+ private boolean isModified() {
+ return (!_configForm.isModified())
+ || confirm(Messages.getString("MainFrame.discard.changes"));
+ }
+
+ private boolean save() {
+ // XXX
+ try {
+ _configForm.get(ConfigPersister.getInstance().getConfig());
+ if (_fileChooser.showSaveDialog(MainFrame.this) == JOptionPane.YES_OPTION) {
+ File f = _fileChooser.getSelectedFile();
+ if (!f.getPath().endsWith(".xml")) {
+ f = new File(f.getPath() + ".xml");
+ }
+ ConfigPersister.getInstance().save(f);
+ _saved = true;
+ showConfigName(f);
+ return true;
+ }
+ return false;
+ } catch (InvariantViolationException ex) {
+ warn(ex);
+ return false;
+ } catch (BindingException ex) {
+ warn(ex.getMessage());
+ return false;
+ } catch (ConfigPersisterException ex) {
+ warn(ex.getMessage());
+ return false;
+ }
+ }
+
+ private void showConfigName(File config) {
+ setTitle(Main.getName() + " - " + (config != null ? config.getName()
+ : Messages.getString("MainFrame.untitled")));
+ }
+
+ private void setRunEnabled(boolean enabled) {
+ if (!enabled) {
+ _outfile = null;
+ }
+ _runButton.setEnabled(enabled);
+ }
+
+ private void clearConfig() {
+ ConfigPersister.getInstance().createBlank();
+ _configForm.clear(ConfigPersister.getInstance().getConfig());
+ }
+
+ private class MainFrameListener extends WindowAdapter {
+ public void windowOpened(WindowEvent e) {
+ clearConfig();
+ }
+
+ public void windowClosing(WindowEvent e) {
+ if (isModified()) {
+ System.exit(0);
+ }
+ }
+ }
+
+ private class NewActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ if (isModified()) {
+ clearConfig();
+ }
+ _saved = false;
+ showConfigName(null);
+ setRunEnabled(false);
+ }
+ }
+
+ private class OpenActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ if (isModified() && _fileChooser.showOpenDialog(MainFrame.this)
+ == JOptionPane.YES_OPTION) {
+ final File f = _fileChooser.getSelectedFile();
+ if (f.getPath().endsWith(".xml")) {
+ ConfigPersister.getInstance().load(f);
+ _saved = true;
+ } else {
+ ConfigPersister.getInstance().loadVersion1(f);
+ _saved = false;
+ }
+ _configForm.put(ConfigPersister.getInstance().getConfig());
+ showConfigName(f);
+ setRunEnabled(false);
+ }
+ } catch (ConfigPersisterException ex) {
+ warn(ex.getMessage());
+ } catch (BindingException ex) {
+ warn(ex.getMessage());
+ }
+ }
+ }
+
+ private class SaveActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ save();
+ }
+ }
+
+ private class BuildActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ final Log log = Log.getSwingLog(_configForm.getLogTextArea());
+ try {
+ if ((!_saved || _configForm.isModified())
+ && !save()) {
+ return;
+ }
+ log.clear();
+ ConfigPersister.getInstance().getConfig().checkInvariants();
+ Builder b = new Builder(log);
+ _outfile = b.build();
+ setRunEnabled(ConfigPersister.getInstance().getConfig()
+ .getHeaderType() == Config.GUI_HEADER // TODO fix console app test
+ && (Util.WINDOWS_OS || !ConfigPersister.getInstance()
+ .getConfig().isDontWrapJar()));
+ } catch (InvariantViolationException ex) {
+ setRunEnabled(false);
+ ex.setBinding(_configForm.getBinding(ex.getProperty()));
+ warn(ex);
+ } catch (BuilderException ex) {
+ setRunEnabled(false);
+ log.append(ex.getMessage());
+ }
+ }
+ }
+
+ private class RunActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ getGlassPane().setVisible(true);
+ Worker.post(new Task() {
+ public Object run() throws ExecException {
+ Log log = Log.getSwingLog(_configForm.getLogTextArea());
+ log.clear();
+ String path = _outfile.getPath();
+ if (Util.WINDOWS_OS) {
+ log.append(Messages.getString("MainFrame.executing") + path);
+ Util.exec(new String[] { path }, log);
+ } else {
+ log.append(Messages.getString("MainFrame.jar.integrity.test")
+ + path);
+ Util.exec(new String[] { "java", "-jar", path }, log);
+ }
+ return null;
+ }
+ });
+ } catch (Exception ex) {
+ // XXX errors logged by exec
+ } finally {
+ getGlassPane().setVisible(false);
+ }
+ };
+ }
+
+ private class AboutActionListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ info(Main.getDescription());
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/Messages.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/Messages.java
new file mode 100755
index 000000000..5e1c64110
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/Messages.java
@@ -0,0 +1,55 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package net.sf.launch4j.formimpl;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "net.sf.launch4j.formimpl.messages";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/MessagesFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/MessagesFormImpl.java
new file mode 100755
index 000000000..c05d7f047
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/MessagesFormImpl.java
@@ -0,0 +1,58 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on Oct 7, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.config.Msg;
+import net.sf.launch4j.form.MessagesForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class MessagesFormImpl extends MessagesForm {
+
+ public MessagesFormImpl(Bindings bindings) {
+ Msg m = new Msg();
+ bindings.addOptComponent("messages", Msg.class, _messagesCheck)
+ .add("messages.startupErr", _startupErrTextArea, m.getStartupErr())
+ .add("messages.bundledJreErr", _bundledJreErrTextArea, m.getBundledJreErr())
+ .add("messages.jreVersionErr", _jreVersionErrTextArea, m.getJreVersionErr())
+ .add("messages.launcherErr", _launcherErrTextArea, m.getLauncherErr())
+ .add("messages.instanceAlreadyExistsMsg", _instanceAlreadyExistsMsgTextArea,
+ m.getInstanceAlreadyExistsMsg());
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/SingleInstanceFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/SingleInstanceFormImpl.java
new file mode 100755
index 000000000..c916a9184
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/SingleInstanceFormImpl.java
@@ -0,0 +1,54 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * Created on 2007-09-22
+ */
+package net.sf.launch4j.formimpl;
+
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.config.SingleInstance;
+import net.sf.launch4j.form.SingleInstanceForm;
+
+/**
+ * @author Copyright (C) 2007 Grzegorz Kowal
+ */
+public class SingleInstanceFormImpl extends SingleInstanceForm {
+
+ public SingleInstanceFormImpl(Bindings bindings) {
+ bindings.addOptComponent("singleInstance", SingleInstance.class,
+ _singleInstanceCheck)
+ .add("singleInstance.mutexName", _mutexNameField)
+ .add("singleInstance.windowTitle", _windowTitleField);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/SplashFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/SplashFormImpl.java
new file mode 100755
index 000000000..7413d4a21
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/SplashFormImpl.java
@@ -0,0 +1,61 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import javax.swing.JFileChooser;
+
+import net.sf.launch4j.FileChooserFilter;
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.config.Splash;
+import net.sf.launch4j.form.SplashForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class SplashFormImpl extends SplashForm {
+
+ public SplashFormImpl(Bindings bindings, JFileChooser fc) {
+ bindings.addOptComponent("splash", Splash.class, _splashCheck)
+ .add("splash.file", _splashFileField)
+ .add("splash.waitForWindow", _waitForWindowCheck, true)
+ .add("splash.timeout", _timeoutField, "60")
+ .add("splash.timeoutErr", _timeoutErrCheck, true);
+
+ _splashFileButton.addActionListener(new BrowseActionListener(false, fc,
+ new FileChooserFilter("Bitmap files (.bmp)", ".bmp"), _splashFileField));
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java
new file mode 100755
index 000000000..c2f60d1d3
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java
@@ -0,0 +1,63 @@
+/*
+ Launch4j (http://launch4j.sourceforge.net/)
+ Cross-platform Java application wrapper for creating Windows native executables.
+
+ Copyright (c) 2004, 2007 Grzegorz Kowal
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Launch4j nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Created on May 1, 2006
+ */
+package net.sf.launch4j.formimpl;
+
+import javax.swing.JFileChooser;
+
+import net.sf.launch4j.binding.Bindings;
+import net.sf.launch4j.config.VersionInfo;
+import net.sf.launch4j.form.VersionInfoForm;
+
+/**
+ * @author Copyright (C) 2006 Grzegorz Kowal
+ */
+public class VersionInfoFormImpl extends VersionInfoForm {
+
+ public VersionInfoFormImpl(Bindings bindings, JFileChooser fc) {
+ bindings.addOptComponent("versionInfo", VersionInfo.class, _versionInfoCheck)
+ .add("versionInfo.fileVersion", _fileVersionField)
+ .add("versionInfo.productVersion", _productVersionField)
+ .add("versionInfo.fileDescription", _fileDescriptionField)
+ .add("versionInfo.internalName", _internalNameField)
+ .add("versionInfo.originalFilename", _originalFilenameField)
+ .add("versionInfo.productName", _productNameField)
+ .add("versionInfo.txtFileVersion", _txtFileVersionField)
+ .add("versionInfo.txtProductVersion", _txtProductVersionField)
+ .add("versionInfo.companyName", _companyNameField)
+ .add("versionInfo.copyright", _copyrightField);
+ }
+}
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/messages.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/messages.properties
new file mode 100755
index 000000000..53a2442a8
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/messages.properties
@@ -0,0 +1,74 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+tab.basic=Basic
+tab.classpath=Classpath
+tab.header=Header
+tab.singleInstance=Single instance
+tab.jre=JRE
+tab.envVars=Set env. variables
+tab.splash=Splash
+tab.version=Version Info
+tab.messages=Messages
+
+# Basic
+jar=Jar:
+jarPath=Jar runtime path:
+jarTip=Application jar.
+jarPathTip=Optional runtime path of the jar relative to the executable. For example, if the executable launcher and the application jar named calc.exe and calc.jar are in the same directory, it would be: calc.jar.
+
+# Classpath
+specifyClassPath=Specify classpath item to add.
+confirmClassPathRemoval=Remove selected classpath items?
+noManifest=The selected jar does not have a manifest.
+
+# JRE
+specifyVar=Specify environment variable to add.
+otherVar=Other var
+jdkPreference.jre.only=Only use public JREs
+jdkPreference.prefer.jre=Prefer public JRE, but use JDK runtime if newer
+jdkPreference.prefer.jdk=Prefer JDK runtime, but use public JRE if newer
+jdkPreference.jdk.only=Only use private JDK runtimes
+
+MainFrame.config.files=launch4j config files (.xml, .cfg)
+MainFrame.new.config=New configuration
+MainFrame.open.config=Open configuration or import 1.x
+MainFrame.save.config=Save configuration
+MainFrame.build.wrapper=Build wrapper
+MainFrame.test.wrapper=Test wrapper
+MainFrame.about.launch4j=About launch4j
+MainFrame.discard.changes=Discard changes?
+MainFrame.confirm=Confirm
+MainFrame.untitled=untitled
+MainFrame.executing=Executing:
+MainFrame.jar.integrity.test=Jar integrity test, executing:
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/messages_es.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/messages_es.properties
new file mode 100755
index 000000000..1d2fac25f
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/formimpl/messages_es.properties
@@ -0,0 +1,56 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal, Patricio Martínez Ros
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+tab.basic = B\u00E1sico
+tab.header = Cabecera
+tab.jre = JRE
+tab.splash = Pantalla de bienvenida
+tab.version = Informaci\u00F3n de la versi\u00F3n
+
+jar = Jar
+jarPath = Ruta del jar
+jarTip = Jar de la aplicaci\u00F3n.
+jarPathTip = Ruta del jar relativa al ejecutable. Por ejemplo, si el lanzador ejecutable y el jar de la aplicaci\u00F3n, llamados calc.exe y calc.jar respectivamente, est\u00E1n en el mismo directorio, ser\u00EDa\: calc.jar.
+
+MainFrame.config.files = Ficheros de configuraci\u00F3n de launch4j (.xml, .cfg)
+MainFrame.new.config = Nueva configuraci\u00F3n
+MainFrame.open.config = Abrir configuraci\u00F3n o importar 1.x
+MainFrame.save.config = Guardar configuraci\u00F3n
+MainFrame.build.wrapper = Construir el empaquetador
+MainFrame.test.wrapper = Comprobar el empaquetador
+MainFrame.about.launch4j = Acerca de launch4j
+MainFrame.discard.changes = \u00BFDescartar cambios?
+MainFrame.confirm = Confirmar
+MainFrame.untitled = Sin nombre
+MainFrame.executing = Ejecutando\:
+MainFrame.jar.integrity.test = Prueba de integridad jar, ejecutando\:
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/messages.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/messages.properties
new file mode 100755
index 000000000..cf28d15af
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/messages.properties
@@ -0,0 +1,45 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+Main.usage=usage
+
+Builder.compiling.resources=Compiling resources
+Builder.linking=Linking
+Builder.wrapping=Wrapping
+Builder.success=Successfully created
+Builder.generated.resource.file=Generated resource file...\n
+Builder.line.has.errors=Line {0} has errors...
+
+Util.exec.failed=Exec failed
+Util.tmpdir=Temporary file directory path (launch4j.tmpdir) cannot contain spaces.
+Util.use.double.backslash=Use \\\\ to code Windows paths in fields that don't represent files or paths!
diff --git a/build/windows/launcher/launch4j/src/net/sf/launch4j/messages_es.properties b/build/windows/launcher/launch4j/src/net/sf/launch4j/messages_es.properties
new file mode 100755
index 000000000..b179d9bd5
--- /dev/null
+++ b/build/windows/launcher/launch4j/src/net/sf/launch4j/messages_es.properties
@@ -0,0 +1,45 @@
+#
+# Launch4j (http://launch4j.sourceforge.net/)
+# Cross-platform Java application wrapper for creating Windows native executables.
+#
+# Copyright (c) 2004, 2007 Grzegorz Kowal, Patricio Martínez Ros
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the Launch4j nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+Main.usage=Uso
+
+Builder.compiling.resources=Compilando recursos
+Builder.linking=Enlazando
+Builder.wrapping=Empaquetando
+Builder.success=Creado con \ufffdxito
+Builder.generated.resource.file=Fichero de recursos generado...\n
+Builder.line.has.errors=Line {0} has errors...
+
+Util.exec.failed=Fallo en la ejecuci\ufffd
+Util.tmpdir=Temporary file directory path (launch4j.tmpdir) cannot contain spaces.
+Util.use.double.backslash=Use \\\\ to code Windows paths in fields that don't represent files or paths!
\ No newline at end of file
diff --git a/build/windows/launcher/launch4j/w32api/MinGW.LICENSE.txt b/build/windows/launcher/launch4j/w32api/MinGW.LICENSE.txt
new file mode 100755
index 000000000..141412dd9
--- /dev/null
+++ b/build/windows/launcher/launch4j/w32api/MinGW.LICENSE.txt
@@ -0,0 +1,25 @@
+MinGW - Licensing Terms
+
+Various pieces distributed with MinGW come with its own copyright and license:
+
+Basic MinGW runtime
+ MinGW base runtime package is uncopyrighted and placed in the public domain.
+ This basically means that you can do what you want with the code.
+
+w32api
+ You are free to use, modify and copy this package.
+ No restrictions are imposed on programs or object files compiled with this library.
+ You may not restrict the the usage of this library.
+ You may distribute this library as part of another package or as a modified package
+ if and only if you do not restrict the usage of the portions consisting
+ of this (optionally modified) library.
+ If distributed as a modified package then this file must be included.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+MinGW profiling code
+ MinGW profiling code is distributed under the GNU General Public License.
+
+The development tools such as GCC, GDB, GNU Make, etc all covered by GNU General Public License.
diff --git a/build/windows/launcher/launch4j/w32api/crt2.o b/build/windows/launcher/launch4j/w32api/crt2.o
new file mode 100755
index 000000000..f81f836cf
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/crt2.o differ
diff --git a/build/windows/launcher/launch4j/w32api/libadvapi32.a b/build/windows/launcher/launch4j/w32api/libadvapi32.a
new file mode 100755
index 000000000..c471853c7
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libadvapi32.a differ
diff --git a/build/windows/launcher/launch4j/w32api/libgcc.a b/build/windows/launcher/launch4j/w32api/libgcc.a
new file mode 100755
index 000000000..d3f89479e
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libgcc.a differ
diff --git a/build/windows/launcher/launch4j/w32api/libkernel32.a b/build/windows/launcher/launch4j/w32api/libkernel32.a
new file mode 100755
index 000000000..5d3eb074f
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libkernel32.a differ
diff --git a/build/windows/launcher/launch4j/w32api/libmingw32.a b/build/windows/launcher/launch4j/w32api/libmingw32.a
new file mode 100755
index 000000000..d1f7888d8
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libmingw32.a differ
diff --git a/build/windows/launcher/launch4j/w32api/libmsvcrt.a b/build/windows/launcher/launch4j/w32api/libmsvcrt.a
new file mode 100755
index 000000000..6714146b6
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libmsvcrt.a differ
diff --git a/build/windows/launcher/launch4j/w32api/libshell32.a b/build/windows/launcher/launch4j/w32api/libshell32.a
new file mode 100755
index 000000000..d35fbdaf3
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libshell32.a differ
diff --git a/build/windows/launcher/launch4j/w32api/libuser32.a b/build/windows/launcher/launch4j/w32api/libuser32.a
new file mode 100755
index 000000000..387fb650d
Binary files /dev/null and b/build/windows/launcher/launch4j/w32api/libuser32.a differ
diff --git a/build/windows/launcher/launch4j/web/bullet.gif b/build/windows/launcher/launch4j/web/bullet.gif
new file mode 100755
index 000000000..f3f133bb8
Binary files /dev/null and b/build/windows/launcher/launch4j/web/bullet.gif differ
diff --git a/build/windows/launcher/launch4j/web/changelog.html b/build/windows/launcher/launch4j/web/changelog.html
new file mode 100755
index 000000000..83511a554
--- /dev/null
+++ b/build/windows/launcher/launch4j/web/changelog.html
@@ -0,0 +1,356 @@
+
+
+
+ Launch4j - Cross-platform Java executable wrapper
+
+
+
+
+
+
+
+
FR #1707827 Allow to prefer JDK private runtimes over JREs (Ian Roberts).
+
FR #1730245 Allow to run only a single aplication instance (Sylvain Mina).
+
FR #1391610 Added IBM JRE/JDK support.
+
Added environment variable expansion in bundled JRE path.
+
Fixed critical bug #1882524 JRE detection problem on 64-bit Windows.
+
Fixed bug #1758912 Vista elevation to full administrator privileges.
+
Fixed bug #1784341 Problems with spaces in paths under linux (Michael Piefel).
+
Fixed bug where /bin was appended to path environment variable instead of jre_path/bin.
+
+
+
Changed license to BSD, MIT (26-01-2008)
+
+
+ The upcoming Launch4j 3.0.0 release will be licensed under the much more
+ liberal new BSD license. The head subproject (the binary header attached to wrapped jars)
+ will be licensed under the similar MIT license.
+
+
+
+
Changes in version 3.0.0-pre2 (29-10-2006)
+
+
Enhanced GUI.
+
Redesigned error reporting.
+
Added custom error messages.
+
Added support website feature.
+
Added PWD and OLDPWD special variables and access to the registry.
+
Runtime ini file extension changed to .l4j.ini, added comments (#).
+
FR #1427811 Initial process priority.
+
FR #1547339 Added VarFileInfo structure to Version Info (Stephan Laertz).
+
FR #1584295 Updated documentation for --l4j-debug.
+
Fixed <jarArgs/> and <args/> config conversion bug (found by Dafe Simonek).
+
Fixed the Ant task exception reporting bug, added tmpdir and bindir attributes.
+
Fixed bug #1563415 Problem with launching application when ini file exists (found by mojomax).
+
Fixed bug #1527619 Console header wildcard expansion (found by erikjv).
+
Fixed bug #1544167 NPE when dontwrap and only classpath given (found by Hendrik Schreiber).
+
Fixed bug #1584264 Dropdown boxes get mixed up (found by Larsen).
Improved configuration file format and embedded Ant config.
+
Launch executable jars, regular jars and class files.
+
Added dynamic classpath resolution with environment variable references and wildcards.
+
Added option to set environment variables before launching the application.
+
New command line switches to change the compiled options.
+
Improved debug information.
+
Added support for XP visual style manifests.
+
Added option to disable use of private JREs.
+
Many small fixes and improvements...
+
+
+
Configuration file changes in 3.x
+
+
Previous formats (1.x and 2.x) are supported.
+
<headerType> accepts gui|console
+
<jarArgs> was changed to <cmdLine>
+
+ <launch4jConfig><headerObjects><file> was changed to
+ <launch4jConfig><obj>
+
+
+ <launch4jConfig><libs><file> was changed to
+ <launch4jConfig><lib>
+
+
+ <launch4jConfig><jre><args> was changed to multiple
+ <launch4jConfig><jre><opt>
+
+
+
+
Embedded Ant configuration changes in 3.x
+
+
+ <jre args="value"> was changed to
+ <jre><opt>value</opt></jre>
+
+
Now it's possible to define headerObjects, libs and classpath.
+
+
+
Changes in version 2.1.5 (21-07-2006)
+
+
Changed the Java download site to http://java.com/download.
+
Now it's possible to use absolute and relative paths to specify the bundled JRE.
+
+
+
Changes in version 2.1.4 (15-06-2006)
+
+
+ Fixed bug #1503996 Only the first wrapper instance had a custom process name
+ (found by Helge Böhme).
+
+
+
+
Changes in version 2.1.3 (31-05-2006)
+
+
+ Fixed bug #1497453 Ant task doesn't support relative jar path with '..'
+ (found by Aston, Pavel Moukhataev).
+
+
Jar argument size limit is now 16KB.
+
Environment variable size limit raised to 32KB.
+
Allow to concatenate multiple env. variables in one property (Maria D.)
+
Added launch4j.tmpdir property.
+
+
+
Changes in version 2.1.2 (03-04-2006)
+
+
Important bugfix: insufficient command line buffer size was increased to 32KB
+ (found by Sebastian Kopsan).
+
Added runtime JVM options from an .ini file.
+
Launch4j's bin directory is now configurable through launch4j.bindir
+ system property.
+
+
+
Changes in version 2.1.1 (25-01-2006)
+
+
Fixed bug #1402748. Validation error occurred when using an Ant task with
+ embedded config and dontWrapJar option (found by Chris Nokleberg).
+
+
+
Changes in version 2.1.0 (10-01-2006)
+
+
More features and smaller header: 18 KB!!
+
Added launcher mode, you can choose whether or not to wrap the jar.
+
Spanish translation of the website/docs and program messages
+ (Patricio MartÃnez Ros).
+
JRE's bin directory is appended to the Path environment variable
+ (Ianiv Schweber).
+
Added special variables EXEDIR and EXEFILE that hold the executable's
+ directory and full path.
+
Support for mapping environment variables to system properties.
+
Added debug launching mode - various information is displayed before
+ starting the Java application.
+
Fixed min/max JRE version checking, previous versions allowed these
+ to be equal (found by Ryan).
+
Bug fixed. Quotes in jar/JVM arguments were handled incorrectly (found by Juan Alvarez Ferrando).
+
A few other enhancements.
+
+
+
Changes in version 2.0.0 (31-10-2005)
+
+
Launch4j for Mac OS X is available thanks to Peter Centgraf.
+
Added support for custom headers.
+
Fixed bug #1343908, command line arguments with spaces were handled
+ incorrectly by the console header (found by Oliver Schaefer / Steve Alberty).
+
Fixed stdin redirection bug (found by Timo Santasalo).
+
+
+
Changes in version 2.0 RC3 (13-08-2005) - final RC
+
+
Correct handling of pathnames with spaces.
+
Fixed the '%20' pathname bug.
+
Fixed basedir bug (Richard Xing).
+
Splash screen can be closed when the application window becomes visible
+ with out specifying it's title (Martin Busik).
+ Update your config file: <waitForTitle>title</waitForTitle>
+ is now <waitForWindow>true</waitForWindow>.
+
+
Fixed build.bat files in demo directories.
+
+
+
Changes in version 2.0 RC2 (21-06-2005)
+
+
chdir allows to change the current directory to arbitrary paths
+ relative to the executable (FR #1144907). It's incompatible with
+ previous versions, update your config file:
+ <chdir>true</chdir>
+ is now <chdir>.</chdir>.
+
+
Bundled JRE path no longer depends on chdir function.
+
Fixed Ant task bug, build files outside launch4j's directory
+ wouldn't work. Josh Elsasser submitted a patch that works without
+ setting launch4j's home dir in the build file. Thanks!
+
+
Removed static edge from splash screen (Serge Baranov).
+
Program checks that the output file path doesn't contain spaces.
+
Fixed a NPE bug caused by a missing maxVersion property
+ (found by Morgan Schweers).
+
+
Fixed relative JRE path bug (found by Nili_).
+
Cleaned up the Builder class.
+
Fixed Ant task NPE where the config was entirely defined in the
+ build file (Josh Elsasser).
+
+
+
+
Changes in version 2.0 RC (07-06-2005)
+
+
Added an Ant task for better build integration.
+
Added 2.x documentation.
+
Updated the demo configuration files.
+
Fixed issues with relative paths in the configuration.
+
Removed the '-1' option in console mode.
+
Minor fixes.
+
+
+
Changes in version 2.0 beta2 (23-05-2005)
+
+
# comments are recognized when importing 1.x cfg files.
+
Added version information.
+
Resource file is displayed when a resource error occurs.
+
Fixed a bug found by Max, options on the first tab were always enabled.
+
+
+
Changes in version 2.0 beta1 (13-05-2005)
+
+
Completely new, cross-platform wrapper - create windows executables on Linux.
+
New .xml configuration file.
+
Application icon with multiple resolutions and color depths.
+
Swing GUI interface.
+
Header compiled with MinGW port of gcc instead of VC++.
+
+
+
Changes in version 1.4.2 (12-03-2005)
+
+
Fixed bug #1158143, stayAlive without a splash screen caused
+ an infinite loop (found by Gregory Kotsaftis).
+
+
+
+
Changes in version 1.4.1 (04-03-2005)
+
+
Fixed bug #1119040, buffer for reading config properties
+ was too short (found by Tom Jensen and Neil).
+
+
Added configurable splash timeout (FR #1102951).
+
Added option to disable the error message on splash timeout (FR #1109159).
+
Option to keep the gui launcher 'alive' after starting an application (FR #1124653).
+
Removed version info.
+
'waitfor' property is now optional.
+
+
+
Changes in version 1.4.0 (26-01-2005)
+
+
Removed .lch4j suffix from process name, now it has the
+ form of the executable filename. The temporary launchers are stored in
+ launch4j-tmp directory (suggested by Emmanuel).
+
+
Added support for console apps (FR #1050053).
+
+
+
Changes in version 1.3.1 (05-11-2004)
+
+
Fixed a bug where explorer window was opened instead of
+ launching the application when setProcName was set to false
+ (found by Rob Jones).
+
+
Fixed temporary launcher deletion bug.
+
+
+
Changes in version 1.3.0 (01-11-2004)
+
+
Now you can configure launch4j to:
+
+
Use a bundled JRE.
+
Search for java, show an error message if the
+ right version cannot be found and open the java download page.
+
And a feature you asked for: use bundled JRE, if
+ that fails search for java and bring up the java download page on error.
+
+
+
Enhanced code that sets the custom process name. In
+ case launch4j can't refresh the temporary launcher, bundled JRE on a
+ read only file system for example, it will use one created previously,
+ if it's present and has the correct size. If not, launching will still
+ continue, but with javaw.exe process name.Temporary launchers are
+ now created in the jre directory instead of jre/bin.
+
+
errTitle property allows to set the title of the error message box.
+
+
+
Changes in version 1.2.1 (25-09-2004)
+
+
Bugfix that allows launching from command line using short
+ name (#1026514 / found by Zach Del)
+
+
+
+
Changes in version 1.2.0 (10-09-2004)
+
+
Custom process name (myapp.lch4j.exe)
+
9 KB stub!
+
Jar arguments
+
Bugfix that allows launching from command line.
+
Hide splash on javaw error.
+
Easier configuration with case insensitive parameters + show unrecognized parameter.
+
12 KB demo application, 34 KB with splash screen.
+
Configuration parameter 'args' changed to 'jvmArgs'
+Run launch4j.exe or launch4j script without command
+line arguments to enter the GUI mode.
+
+
launch4j.exe
+
+To wrap a jar in console mode use launch4jc.exe and
+specify the configuration file.
+
+
launch4jc.exe config.xml
+
+On Linux use the launch4j script.
+
+
launch4j ./demo/l4j/config.xml
+
+
Configuration file
+Launch4j requires an xml configuration file for each output executable.
+You can create and edit it conveniently using the graphic user
+interface or your favorite editor. Alternatively it's possible to pass
+all of the configuration parameters through the Ant task. All files
+may be absolute paths or relative to the configuration file path.
+
+
+ Type of the header used to wrap the application.
+
+
+
+
Header type
+
Launcher
+
Splash screen
+
Wait for the application to close
+
+
+
+
+
gui
+
javaw
+
yes
+
wrapper waits only if stayAlive is set to true,
+ otherwise it terminates immediately or after closing
+ the splash screen.
+
+
+
+
console
+
java
+
no
+
always waits and returns application's exit code.
+
+
+
+
+
+
+
<outfile>
+
Output executable file.
+
+
+
<jar>
+
+ Optional, by default specifies the jar to wrap. To launch a jar without
+ wrapping it enter the runtime path of the jar relative to
+ the executable and set <dontWrapJar> to true.
+ For example, if the executable launcher and the application jar named
+ calc.exe and calc.jar are in the same directory
+ then you would use <jar>calc.jar</jar>
+ and <dontWrapJar>true</dontWrapJar>.
+
+
+
+
<dontWrapJar>
+
+ Optional, defaults to false. Launch4j by default wraps jars in native
+ executables, you can prevent this by setting <dontWrapJar> to true.
+ The exe acts then as a launcher and starts the application specified in
+ <jar> or <classPath><mainClass>
+
+
+
+
<errTitle>
+
+ Optional, sets the title of the error message box that's displayed if Java cannot
+ be found for instance. This usually should contain the name of your
+ application. The console header prefixes error messages with this
+ property (myapp: error...)
+
+
+
+
<cmdLine>
+
Optional, constant command line arguments.
+
+
+
<chdir>
+
Optional. Change current directory to an arbitrary path relative to the executable.
+ If you omit this property or leave it blank it will have no effect.
+ Setting it to . will change the current dir to the same directory
+ as the executable. .. will change it to the parent directory, and so on.
+
+
+
<chdir>.</chdir>
+
+
+
<chdir>../somedir</chdir>
+
+
+
+
<customProcName>
+
Optional, defaults to false.
+ Set the process name as the executable filename and use Xp style manifests
+ (if any).
+ Creates a temporary file in launch4j-tmp directory inside the used JRE.
+ These files are deleted by any launch4j wrapped application, which sets
+ the process name and uses the same JRE. The removal takes place
+ when the application starts,
+ so at least one copy of this file will always be present.
+
+
+
+
<stayAlive>
+
Optional, defaults to false in GUI header, always true in console header.
+ When enabled the launcher waits for the Java application
+ to finish and returns it's exit code.
+
+
+
+
<icon>
+
Application icon in ICO format. May contain multiple color depths/resolutions.
+
+
+
<obj>
+
Optional, custom headers only. Ordered list of header object files.
+
+
+
<lib>
+
Optional, custom headers only. Ordered list of libraries used by header.
+
+
+
<singleInstance>
+
Optional, allow to run only a single instance of the application.
+
+
+
+
<mutexName>
+
Unique mutex name that will identify the application.
+
<windowTitle>
+
Optional, recognized by GUI header only. Title or title part of a window
+ to bring up instead of running a new instance.
+
+
+
+
+
<jre>
+
Required element that groups JRE settings.
+
+
+
+
<path>, <minVersion>, <maxVersion>
+
The <path> property is used
+ to specify the absolute or relative path (to the executable) of a bundled JRE, it
+ does not rely on the current directory or <chdir>.
+ Note that this path is not checked until the actual application execution.
+ If you'd like the wrapper to search for a JRE (public or SDK private)
+ use the <minVersion> property, you may also specify
+ the <maxVersion> to prevent it from using higher Java versions.
+ Launch4j will always use the highest version available (in the min/max range of course).
+ If a Sun's JRE is not available or does not satisfy the search criteria,
+ the search will be repeated on IBM runtimes.
+ You can also combine these properties to change the startup process...
+
+
+
+
+
<path>
+
Run if bundled JRE and javaw.exe are present, otherwise stop with error.
+
<path> + <minVersion> [+ <maxVersion>]
+
Use bundled JRE first, if it cannot be located search for Java,
+ if that fails display error message and open the Java download page.
+
+
<minVersion> [+ <maxVersion>]
+
Search for Java, if an appropriate version cannot be found display
+ error message and open the Java download page.
+
+
+
+
+
+
+
<jdkPreference>
+
Optional, defaults to preferJre; Allows you to specify a preference
+ for a public JRE or a private JDK runtime. Valid values are:
+
+
+
+
+
jreOnly
+
Always use a public JRE (equivalent to the
+ old option dontUsePrivateJres=true)
+
preferJre
+
Prefer a public JRE, but use a JDK private
+ runtime if it is newer than the public
+ JRE (equivalent to the old option
+ dontUsePrivateJres=false)
+
preferJdk
+
Prefer a JDK private runtime, but use a
+ public JRE if it is newer than the
+ JDK
+
jdkOnly
+
Always use a private JDK runtime (fails
+ if there is no JDK installed)
+
+
+
+
HeapSize, HeapPercent
+
If size and percent are specified, then the setting which yields
+ more memory will be chosen at runtime. In other words, setting both values
+ means: percent of free memory no less than size in MB.
+
+
+
+
+
<initialHeapSize>
+
Optional, initial heap size in MB.
+
+
+
<initialHeapPercent>
+
Optional, initial heap size in % of free memory.
+
+
+
<maxHeapSize>
+
Optional, max heap size in MB.
+
+
+
<maxHeapPercent>
+
Optional, max heap size in % of free memory.
+
+
+
+
<opt>
+
Optional, accepts everything you would normally pass to
+ java/javaw launcher: assertion options, system properties and X options.
+ Here you can map environment and special variables EXEDIR
+ (exe's runtime directory), EXEFILE (exe's runtime full file path)
+ to system properties. All variable references must be surrounded with
+ percentage signs and quoted.
+
Optional, groups the splash screen settings. Allowed only in GUI header.
+
+
+
+
<file>
+
Splash screen image in BMP format.
+
+
+
<waitForWindow>
+
Optional, defaults to true. Close the splash screen when an application
+ window or Java error message box appears. If set to false,
+ the splash screen will be closed on timeout.
+
+
+
+
<timeout>
+
Optional, defaults to 60. Number of seconds after which the splash screen
+ must be closed. Splash timeout may cause an error depending on
+ <timeoutErr>.
+
+
+
+
<timeoutErr>
+
Optional, defaults to true. True signals an error on splash timeout,
+ false closes the splash screen quietly.
+
+
+
+
+
+
<versionInfo>
+
Optional, version information to be displayed by the Windows Explorer.
+
+
+
+
<fileVersion>
+
Version number 'x.x.x.x'
+
+
+
<txtFileVersion>
+
Free form file version, for example '1.20.RC1'.
+
+
+
<fileDescription>
+
File description presented to the user.
+
+
+
<copyright>
+
Legal copyright.
+
+
+
<productVersion>
+
Version number 'x.x.x.x'
+
+
+
<txtProductVersion>
+
Free form file version, for example '1.20.RC1'.
+
+
+
<productName>
+
Text.
+
+
+
<companyName>
+
Optional text.
+
+
+
<internalName>
+
Internal name without extension, original filename or module name for example.
+
+
+
<originalFilename>
+
Original name of the file without the path. Allows to determine
+ whether a file has been renamed by a user.
+
+
+
+
+
Importing 1.x configuration
+It's possible to import a 1.x configuration file using the GUI
+interface. Open the file, correct the paths and save it as a new xml
+configuration.
+
+
Ant task
+You may set a launch4j directory property or change the task definition.
+
+
+
+You can also define the entire configuration in the task, but it will
+not be possible to edit such a file in the GUI mode. All paths except
+for <chdir>, <jre><path> and jarPath
+are calculated using the basedir project attribute.
+
+
+When you create a wrapper or launcher all configuration details are compiled into the
+executable and cannot be changed without recreating it or hacking with a resource editor.
+Launch4j 2.1.2 introduces a new feature that allows to pass additional JVM options
+at runtime from an .l4j.ini file. Now you can specify the options in the configuration file,
+ini file or in both, but you cannot override them. The ini file's name must correspond
+to the executable's (myapp.exe : myapp.l4j.ini).
+The arguments should be separated with spaces or new lines, environment variable
+expansion is supported, for example:
+
+ To make sure the output executable is configured correctly you can use the
+ debug launching mode to log various information to the launch4j.log file.
+
+
+
--l4j-default-proc
+
+ Use default process name.
+
+
+
--l4j-dont-wait
+
+ Disable the "stay alive" function.
+
+
+
--l4j-no-splash
+
+ Disable the splash screen.
+
+
+
--l4j-no-splash-err
+
+ Disable splash screen error on timeout, might be useful on very slow computers.
+
+
+
+
Settings
+
+
Alternate bin directory: launch4j.bindir
+
+ It's possible to override the default bin directory location which contains windres and ld
+ tools using the launch4j.bindir system property. The property can have two forms:
+ a path relative to Launch4j's directory (altbin for example) or an absolute path.
+
+
+
Working directory: launch4j.tmpdir
+
Change the working directory if the default path contains spaces which windres cannot handle.
+ Launch4j is a cross-platform tool for wrapping
+ Java applications distributed as jars in lightweight Windows
+ native executables. The executable can be
+ configured to search for a certain JRE version or
+ use a bundled one, and it's possible to set
+ runtime options, like the initial/max heap size.
+ The wrapper also provides better user experience
+ through an application icon, a native pre-JRE
+ splash screen, a custom process name, and a Java
+ download page in case the appropriate JRE cannot
+ be found.
+
+
+
Features
+
+
Launch4j wraps jars in Windows native executables and allows to run them
+ like a regular Windows program. It's possible to wrap applications
+ on Windows, Linux, Mac OS X and Solaris!
+
+
Also creates launchers for jars and class files without wrapping.
+
+ Supports executable jars and dynamic classpath resolution using
+ environment variables and wildcards.
+
+
Doesn't extract the jar from the executable.
+
Custom application icon with multiple resolutions and color depths.
+
Native pre-JRE splash screen in BMP format shown until
+ the Java application starts.
+
+
Process name as the executable filename to easily
+ identify your application, initial priority and
+ single aplication instance features.
+
+
Works with a bundled JRE or searches for newest Sun or IBM JRE / JDK in given
+ version range.
+
Opens Java download page if an appropriate Java version cannot be
+ found or a support website in case of an error.
+
+
Supports GUI and console apps.
+
Supports Vista manifests and XP visual style manifests.
+
Passes command line arguments, also supports constant arguments.
+
Allows to set the initial/max heap size also dynamically in percent of free memory.
+
JVM options: set system properties, tweak the garbage collection...
+
Runtime JVM options from an .l4j.ini file.
+
Runtime command line switches to change the compiled options.
+
Access to environment variables, the registry and executable file path through system properties.
+
Set environment variables.
+
Option to change current directory to the executable location.
+
The JRE's bin directory is appended to the Path environment variable.
+
Custom version information shown by Windows Explorer.
+
GUI and command line interface.
+
Build integration through an Ant task and a Maven Plugin.
+
Lightweight: 26 KB!
+
It's free and may be used for commercial purposes.
+
Includes a sample application and Ant script
+ that automates the build process from Java sources to native executable.
+
+
The wrapped program works on all Windows platforms (98/Me/NT/2K/XP/Vista),
+ Launch4j works on NT/2K/XP/Vista, Linux, Mac OS X (build on 10.4) and Sparc Solaris 8-10.
+
+
+
License
+
+ This program is free software licensed under the
+ BSD license, the head subproject
+ (the code which is attached to the wrapped jars) is licensed under the
+ MIT license.
+ Launch4j may be used for wrapping closed source, commercial applications.
+
+
Info
+
+ Running Launch4j on other Java enabled platforms is a matter of getting a binary version
+ of MinGW binutils 2.15.90 (windres and ld only)
+ for your system or compiling them. If you'll provide these, I'll be able to create a binary package
+ available for download.
+
+
+
+
+
+
+
diff --git a/build/windows/launcher/launch4j/web/launch4j-use.gif b/build/windows/launcher/launch4j/web/launch4j-use.gif
new file mode 100755
index 000000000..ccb888247
Binary files /dev/null and b/build/windows/launcher/launch4j/web/launch4j-use.gif differ
diff --git a/build/windows/launcher/launch4j/web/launch4j.gif b/build/windows/launcher/launch4j/web/launch4j.gif
new file mode 100755
index 000000000..27552074a
Binary files /dev/null and b/build/windows/launcher/launch4j/web/launch4j.gif differ
diff --git a/build/windows/launcher/launch4j/web/links.html b/build/windows/launcher/launch4j/web/links.html
new file mode 100755
index 000000000..4213b86f9
--- /dev/null
+++ b/build/windows/launcher/launch4j/web/links.html
@@ -0,0 +1,73 @@
+
+
+
+ Launch4j - Cross-platform Java executable wrapper
+
+
+
+
+
+
+
+
+
+
diff --git a/build/windows/launcher/launch4j/web/style.css b/build/windows/launcher/launch4j/web/style.css
new file mode 100755
index 000000000..f57c086d6
--- /dev/null
+++ b/build/windows/launcher/launch4j/web/style.css
@@ -0,0 +1,159 @@
+body, table {
+ font: 12px/20px Verdana, Arial, Helvetica, sans-serif;
+}
+
+
+pre {
+ padding: 8px;
+ border: 1px dashed #999999;
+ background-color: #f1f1f1;
+ font: 13px/20px "Courier New", Courier, monospace;
+}
+
+
+.version {
+ color: #307fe1;
+ font-weight: bold;
+}
+
+
+.codeword {
+ color: #3333ff;
+}
+.attrib {
+ color: #404040;
+}
+.option {
+ font-family: "Courier New", Courier, monospace;
+ font-weight: bold;
+}
+
+
+dt {
+ margin-top: 1.5em;
+ color: #404040;
+ font-size: 115%;
+ border-bottom: 1px solid #cccccc;
+}
+dd {
+ margin-left: 1em;
+}
+
+
+.warn, ul.changes em {
+ color: #ff0000;
+}
+
+
+table {
+ margin-top: 1em;
+ padding: 0;
+ border: 1px solid #999999;
+ border-collapse: collapse;
+ text-align: center;
+}
+table th {
+ padding: 2px 4px;
+ border: 1px solid #999999;
+ background-color: #f1f1f1;
+}
+table td {
+ padding: 2px 4px;
+ border: 1px solid #999999;
+}
+.description {
+ text-align: left;
+}
+
+
+#container {
+ width: 90%;
+ margin: 10px auto;
+ border-width: 0;
+ background-color: #ffffff;
+}
+
+
+#top {
+ padding: 0.5em;
+ background-color: #ffffff;
+}
+#top h1 {
+ margin: 0;
+ padding: 0;
+}
+
+
+#leftnav {
+ float: left;
+ width: 170px;
+ margin: 0;
+ padding: 0.5em;
+ background-color: #ffffff;
+}
+#leftnav ul {
+ margin: 0;
+ padding: 0;
+ border: none;
+ list-style-type: none;
+ font-size: 115%;
+}
+#leftnav a {
+ width: 170px;
+ height: 1.6em;
+ line-height: 1.6em;
+ display: block;
+ padding-left: 0.2em;
+}
+#leftnav a:link, #leftnav a:visited {
+ text-decoration: none;
+ color: #666666;
+}
+#leftnav a:hover {
+ background-color: #307fe1;
+ color: #ffffff;
+}
+
+
+#content {
+ max-width: 52em;
+ margin-left: 190px;
+ padding: 1em;
+ border-left: 1px solid #cccccc;
+ background-color: #ffffff;
+}
+
+#content ul {
+ list-style-image: url('bullet.gif');
+}
+
+#content a:link {
+ text-decoration: none;
+ color: #307fe1;
+}
+#content a:visited {
+ text-decoration: none;
+ color: #307fe1;
+}
+#content a:hover {
+ color: #307fe1;
+ text-decoration: underline;
+}
+
+#content h2 {
+ font-size: 150%;
+}
+#content h2:first-child {
+ margin: 0 0 0.5em;
+}
+
+
+.footer {
+ clear: both;
+ margin: 0;
+ padding: 0.5em;
+ background-color: #ffffff;
+ color: #333333;
+ text-align: center;
+ font-size: 90%;
+}
diff --git a/build/windows/launcher/launcher.cpp b/build/windows/launcher/launcher.cpp
deleted file mode 100644
index 2e683ab96..000000000
--- a/build/windows/launcher/launcher.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-
-// launcher.cpp : Defines the class behaviors for the application.
-//
-
-// The size of all of the strings was made sort of ambiguously large, since
-// 1) nothing is hurt by allocating an extra few bytes temporarily and
-// 2) if the user has a long path, and it gets copied five times over for the
-// classpath, the program runs the risk of crashing. Bad bad.
-
-#define JAVA_ARGS "-Xms128m -Xmx128m "
-#define JAVA_MAIN_CLASS "processing.app.Base"
-
-#include
-#include
-#include
-
-int STDCALL
-WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
-{
- // all these malloc statements... things may need to be larger.
-
- // what was passed to this application
- char *incoming_cmdline = (char *)malloc(strlen(lpCmd) * sizeof(char));
- strcpy (incoming_cmdline, lpCmd);
-
- // what gets put together to pass to jre
- char *outgoing_cmdline = (char *)malloc(16384 * sizeof(char));
-
- // prepend the args for -mx and -ms
- strcpy(outgoing_cmdline, JAVA_ARGS);
-
- // append the classpath and launcher.Application
- char *loaddir = (char *)malloc(MAX_PATH * sizeof(char));
- *loaddir = 0;
-
- GetModuleFileName(NULL, loaddir, MAX_PATH);
- // remove the application name
- *(strrchr(loaddir, '\\')) = '\0';
-
- char *cp = (char *)malloc(8 * strlen(loaddir) + 4096);
-
-
- // if this code looks shitty, that's because it is. people are
- // likely to have the durndest things in their CLASSPATH and QTJAVA
- // environment variables. mostly because installers often mangle
- // them without the user knowing. so who knows where and when the
- // quotes will show up. this is a guess at dealing with the things,
- // without spending a whole day to make it overly robust. [fry]
-
-
-
-
- // test to see if running with a java runtime nearby or not
- char *testpath = (char *)malloc(MAX_PATH * sizeof(char));
- *testpath = 0;
- strcpy(testpath, loaddir);
- strcat(testpath, "\\java\\bin\\java.exe");
- FILE *fp = fopen(testpath, "rb");
- int local_jre_installed = (fp != NULL);
- //char *rt_jar = (fp == NULL) ? "" : "java\\lib\\rt.jar;";
- if (fp != NULL) fclose(fp); // argh! this was probably causing trouble
-
-
- //MessageBox(NULL, local_jre_installed ?
- // "local jre installed" : "couldn't find jre", "p5", MB_OK);
-
-
- //const char *envClasspath = getenv("CLASSPATH");
- char *env_classpath = (char *)malloc(16384 * sizeof(char));
-
- // ignoring CLASSPATH for now, because it's not needed
- // and causes more trouble than it's worth [0060]
- env_classpath[0] = 0;
-
- /*
- // keep this code around since may be re-enabled later
- if (getenv("CLASSPATH") != NULL) {
- strcpy(env_classpath, getenv("CLASSPATH"));
- if (env_classpath[0] == '\"') {
- // starting quote in classpath.. yech
- env_classpath++; // shitty.. i know..
-
- int len = strlen(env_classpath);
- if (env_classpath[len-1] == '\"') {
- env_classpath[len-1] = 0;
- } else {
- // a starting quote but no ending quote.. ugh
- // maybe throw an error
- }
- }
- int last = strlen(env_classpath);
- env_classpath[last++] = ';';
- env_classpath[last] = 0;
- } else {
- env_classpath[0] = 0;
- }
- */
-/* WE DUNNO NEED QUICKTIME JAVA FOR ARDUINO
- char *qtjava_path = (char *)malloc(16384 * sizeof(char));
- qtjava_path[0] = 0;
-
- if (getenv("WINDIR") == NULL) {
- // uh-oh.. serious problem.. gonna have to report this
- // but hopefully WINDIR is set on win98 too
-
- } else {
- strcpy(qtjava_path, getenv("WINDIR"));
- strcat(qtjava_path, "\\SYSTEM32\\QTJava.zip");
-
- FILE *fp = fopen(qtjava_path, "rb");
- if (fp != NULL) {
- fclose(fp); // found it, all set
- strcat(qtjava_path, ";"); // add path separator
-
- } else {
- strcpy(qtjava_path, getenv("WINDIR"));
- strcat(qtjava_path, "\\SYSTEM\\QTJava.zip");
-
- fp = fopen(qtjava_path, "rb");
- if (fp != NULL) {
- fclose(fp); // found it, all set
- strcat(qtjava_path, ";"); // add path separator
-
- } else {
- // doesn't seem to be installed, which is a problem.
- // but the error will be reported by the pde
- qtjava_path[0] = 0;
- }
- }
- }
-END WE DUNNO NEED QUICKTIME JAVA FOR ARDUINO*/
- // NO! put quotes around contents of cp, because %s might have spaces in it.
- // don't put quotes in it, because it's setting the environment variable
- // for CLASSPATH, not being included on the command line. so setting the
- // env var it's ok to have spaces, and the quotes prevent
- // javax.comm.properties from being found.
- sprintf(cp,
- //"\"" // begin quote
- //"'"
-
- "%s" // local jre or blank
- //"%s" // qtjava path
- ""
-
- "%s\\lib;"
- "%s\\lib\\build;"
- "%s\\lib\\pde.jar;"
- //"%s\\lib\\core.jar;"
- "%s\\lib\\mrj.jar;"
- "%s\\lib\\RXTXcomm.jar;"
- "%s\\lib\\oro.jar;"
- "%s\\lib\\registry.jar;"
- "%s\\lib\\antlr.jar;"
-
- "%s", // original CLASSPATH
-
-
- //"C:\\WINNT\\system32\\QTJava.zip;" // worthless
- //"C:\\WINDOWS\\system32\\QTJava.zip;"
-
- //"\"", // end quote
- //"'",
- //,
-
- // the first three %s args
- //local_jre_installed ? "java\\lib\\rt.jar;java\\lib\\jaws.jar;" : "",
- local_jre_installed ? "java\\lib\\rt.jar;" : "",
- //qtjava_path,
- loaddir, loaddir, loaddir, loaddir,
- loaddir, loaddir, loaddir, loaddir,
- env_classpath);
-
- //MessageBox(NULL, cp, "it's twoo! it's twoo!", MB_OK);
-
- if (!SetEnvironmentVariable("CLASSPATH", cp)) {
- MessageBox(NULL, "Could not set CLASSPATH environment variable",
- "Arduino Error", MB_OK);
- return 0;
- }
-
-
-
- // need to add the local jre to the path for 'java mode' in the env
- if (local_jre_installed) {
-
- char *env_path = (char *)malloc(strlen(getenv("PATH")) * sizeof(char));
- strcpy(env_path, getenv("PATH"));
- char *paf = (char *)malloc((strlen(env_path) + strlen(loaddir) + 32) * sizeof(char));
- sprintf(paf, "%s\\java\\bin;lib;%s", loaddir, env_path);
-
- if (!SetEnvironmentVariable("PATH", paf)) {
- MessageBox(NULL, "Could not set PATH environment variable",
- "Arduino Error", MB_OK);
- return 0;
- }
-
-
- }
-
- //MessageBox(NULL, cp, "whaadddup", MB_OK);
-
- // add the name of the class to execute and a space before the next arg
- strcat(outgoing_cmdline, JAVA_MAIN_CLASS " ");
-
- // append additional incoming stuff (document names), if any
- strcat(outgoing_cmdline, incoming_cmdline);
-
- char *executable = (char *)malloc((strlen(loaddir) + 256) * sizeof(char));
- // loaddir is the name path to the current application
-
- //if (localJreInstalled) {
- if (local_jre_installed) {
- strcpy(executable, loaddir);
- // copy in the path for javaw, relative to launcher.exe
- strcat(executable, "\\java\\bin\\javaw.exe");
- } else {
- strcpy(executable, "javaw.exe");
- }
-
- SHELLEXECUTEINFO ShExecInfo;
-
- // set up the execution info
- ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
- ShExecInfo.fMask = 0;
- ShExecInfo.hwnd = 0;
- ShExecInfo.lpVerb = "open";
- ShExecInfo.lpFile = executable;
- ShExecInfo.lpParameters = outgoing_cmdline;
- ShExecInfo.lpDirectory = loaddir;
- ShExecInfo.nShow = SW_SHOWNORMAL;
- ShExecInfo.hInstApp = NULL;
-
- if (!ShellExecuteEx(&ShExecInfo)) {
- MessageBox(NULL, "Error calling ShellExecuteEx()",
- "Arduino Error", MB_OK);
- return 0;
- }
-
- if (reinterpret_cast(ShExecInfo.hInstApp) <= 32) {
-
- // some type of error occurred
- switch (reinterpret_cast(ShExecInfo.hInstApp)) {
- case ERROR_FILE_NOT_FOUND:
- case ERROR_PATH_NOT_FOUND:
- MessageBox(NULL, "A required file could not be found. \n"
- "You may need to install a Java runtime\n"
- "or re-install Arduino.",
- "Arduino Error", MB_OK);
- break;
- case 0:
- case SE_ERR_OOM:
- MessageBox(NULL, "Not enough memory or resources to run at"
- " this time.", "Arduino Error", MB_OK);
-
- break;
- default:
- MessageBox(NULL, "There is a problem with your installation.\n"
- "If the problem persists, re-install the program.",
- "Arduino Error", MB_OK);
- break;
- }
- }
-
- return 0;
-}
diff --git a/build/windows/launcher/launcher.dev b/build/windows/launcher/launcher.dev
deleted file mode 100644
index 84d2f7d77..000000000
--- a/build/windows/launcher/launcher.dev
+++ /dev/null
@@ -1,68 +0,0 @@
-[Project]
-FileName=launcher.dev
-Name=launcher
-UnitCount=2
-Type=1
-Ver=1
-ObjFiles=
-Includes=
-Libs=
-PrivateResource=launcher_private.rc
-ResourceIncludes=
-MakeIncludes=
-Compiler=
-CppCompiler=
-Linker=
-IsCpp=1
-Icon=
-ExeOutput=
-ObjectOutput=
-OverrideOutput=0
-OverrideOutputName=
-HostApplication=
-Folders=
-CommandLine=
-UseCustomMakefile=0
-CustomMakefile=
-IncludeVersionInfo=0
-SupportXPThemes=0
-CompilerSet=0
-CompilerSettings=
-
-[Unit1]
-FileName=launcher.rc
-Folder=launcher
-Compile=1
-Link=0
-Priority=1000
-OverrideBuildCmd=0
-BuildCmd=
-
-[Unit2]
-FileName=launcher.cpp
-CompileCpp=1
-Folder=launcher
-Compile=1
-Link=1
-Priority=1000
-OverrideBuildCmd=0
-BuildCmd=
-
-[VersionInfo]
-Major=0
-Minor=1
-Release=1
-Build=1
-LanguageID=1033
-CharsetID=1252
-CompanyName=
-FileVersion=
-FileDescription=Developed using the Dev-C++ IDE
-InternalName=
-LegalCopyright=
-LegalTrademarks=
-OriginalFilename=
-ProductName=
-ProductVersion=
-AutoIncBuildNr=0
-
diff --git a/build/windows/launcher/launcher.rc b/build/windows/launcher/launcher.rc
deleted file mode 100644
index df972b015..000000000
--- a/build/windows/launcher/launcher.rc
+++ /dev/null
@@ -1,60 +0,0 @@
-//Originally a Microsoft Developer Studio generated resource script.
-//
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-#define IDR_MAINFRAME 128
-#define IDR_DOCUMENT 129
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDR_MAINFRAME ICON DISCARDABLE "application.ico"
-IDR_DOCUMENT ICON DISCARDABLE "document.ico"
-
-// not sure what triggers _MAC to be defined
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-IDR_MAINFRAME VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904B0"
- BEGIN
- VALUE "CompanyName", "\0"
- VALUE "FileDescription", "Launcher MFC Application\0"
- VALUE "FileVersion", "1, 0, 0, 1\0"
- VALUE "InternalName", "Launcher\0"
- VALUE "LegalCopyright", "Copyright (C) 1998\0"
- VALUE "LegalTrademarks", "\0"
- VALUE "OriginalFilename", "Launcher.EXE\0"
- VALUE "ProductName", "Launcher Application\0"
- VALUE "ProductVersion", "1, 0, 0, 1\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // !_MAC
-
-
-
diff --git a/build/windows/make.sh b/build/windows/make.sh
index 66dee9bbf..87aeb2d43 100755
--- a/build/windows/make.sh
+++ b/build/windows/make.sh
@@ -7,70 +7,51 @@ if test -d work
then
BUILD_PREPROC=false
else
- echo Setting up directories to build arduino...
+ echo Setting up directories to build P5...
BUILD_PREPROC=true
- cp -r ../shared work
- rm -f work/.DS_Store
- #cp ../../lib/*.dll work
- cp dist/*.dll work
- cp dist/run.bat work
- chmod 755 work/run.bat
- cp ../../readme.txt work
- unix2dos work/readme.txt
-
- # needs to make the dir because of packaging goofiness
- mkdir -p work/classes/arduino/app/syntax
- mkdir -p work/classes/arduino/app/tools
- echo Extracting reference...
- cd work
- unzip reference.zip
- # necessary for launching reference from shell/command prompt
- # which is done internally to view reference
- #chmod +x reference/*.html
- # needed by 'help' menu
- #chmod +x reference/environment/*.html
- # chmod -R +x *.html doesn't seem to work
- rm reference.zip
- cd ..
+ mkdir work
+ cp -r ../shared/lib work/
+ cp -r ../shared/tools work/
- echo Extracting enormous JRE...
- unzip -q -d work jre.zip
- # cygwin requires this because of unknown weirdness
- # it was not formerly this anal retentive
- cd work/java/bin/
- #chmod +x *.exe *.dll
- #chmod +x client/*.dll
- cd ../../..
-
- mkdir work/lib/build
- #mkdir work/classes
-
- echo Compiling arduino.exe
- cd launcher
- make && cp arduino.exe ../work/
- cd ..
-
- # get jikes and depedencies
- cp dist/jikes.exe work/
- #chmod +x work/jikes.exe
-
- cp dist/ICE_JNIRegistry.dll work/
+ cp dist/*.dll work/
+ cp -r dist/drivers work/
cp -r ../../hardware work/
- cp dist/bootloader/*.* work/hardware/bootloaders/atmega8
- mkdir work/drivers
- cp -r dist/drivers/* work/drivers/
- cp dist/avr_tools.zip .
- echo Extracting avr tools ...
- unzip -q -d work/hardware avr_tools.zip
- rm -f avr_tools.zip
+ cp ../../app/lib/antlr.jar work/lib/
+ cp ../../app/lib/ecj.jar work/lib/
+ cp ../../app/lib/jna.jar work/lib/
+ cp ../../app/lib/oro.jar work/lib/
+ cp ../../app/lib/RXTXcomm.jar work/lib/
- # take care of the examples
- cp -r ../shared/dist/examples work/
+ echo Copying examples...
+ cp -r ../shared/examples work/
+
+ echo Extracting reference...
+ unzip -q -d work/ ../shared/reference.zip
+
+ echo Extracting avr tools...
+ unzip -q -d work/hardware/ avr_tools.zip
+
+ echo Extracting enormous JRE...
+ unzip -q -d work/ jre.zip
+
+ # build the processing.exe bundle
+ # there are a few hacks in the source to launch4j-3.0.1
+ # to build them, use the following:
+ # cd head_src/gui_head && make -f Makefile.win
+ cd launcher
+ ./launch4j/launch4jc.exe config.xml
+ cp arduino.exe ../work/
+ cd ..
# chmod +x the crew
+ # cygwin requires this because of unknown weirdness
+ # it was not formerly this anal retentive
+ # with the html, it's necessary on windows for launching reference
+ # from shell/command prompt, which is done internally to view reference
+ find work -name "*.html" -exec chmod +x {} ';'
find work -name "*.dll" -exec chmod +x {} ';'
find work -name "*.exe" -exec chmod +x {} ';'
find work -name "*.html" -exec chmod +x {} ';'
@@ -78,28 +59,66 @@ fi
cd ../..
+
+### -- BUILD CORE ----------------------------------------------
+
+echo Building processing.core...
+
+cd core
+
+#CLASSPATH="..\\build\\windows\\work\\java\\lib\\rt.jar;..\\build\\windows\\work\\java\\lib\\tools.jar"
+#CLASSPATH="..\\build\\windows\\work\\java\\lib\\tools.jar"
+#export CLASSPATH
+
+perl preproc.pl
+
+mkdir -p bin
+../build/windows/work/java/bin/java \
+ -classpath "..\\build\\windows\\work\\java\\lib\\tools.jar" \
+ com.sun.tools.javac.Main \
+ -source 1.5 -target 1.5 -d bin \
+ src/processing/core/*.java src/processing/xml/*.java
+
+rm -f ../build/windows/work/lib/core.jar
+
+# package this folder into core.jar
+cd bin && zip -rq ../../build/windows/work/lib/core.jar \
+ processing/core/*.class processing/xml/*.class && cd ..
+
+# back to base processing dir
+cd ..
+
+
+
### -- BUILD PDE ------------------------------------------------
+echo Building the PDE...
+
cd app
-CLASSPATH="..\\build\\windows\\work\\lib\\RXTXcomm.jar;..\\build\\windows\\work\\lib\\mrj.jar;..\\build\\windows\\work\\lib\antlr.jar;..\\build\\windows\\work\\lib\\oro.jar;..\\build\\windows\\work\\lib\\registry.jar;..\\build\\windows\\work\\java\\lib\\rt.jar"
+# has to be present, otherwise javac will complain of file writing errors
+rm -rf ../build/windows/work/classes
+mkdir ../build/windows/work/classes
-# compile the code as java 1.3, so that the application will run and
-# show the user an error, rather than crapping out with some strange
-# "class not found" crap
-# need to do this twice because otherwise dependencies aren't resolved right.
-../build/windows/work/jikes -target 1.3 +D -classpath "$CLASSPATH;..\\build\\windows\\work\\classes" -d ..\\build\\windows\\work\\classes ../core/*.java preproc/*.java syntax/*.java tools/*.java *.java
-../build/windows/work/jikes -target 1.3 +D -classpath "$CLASSPATH;..\\build\\windows\\work\\classes" -d ..\\build\\windows\\work\\classes ../core/*.java preproc/*.java syntax/*.java tools/*.java *.java
+../build/windows/work/java/bin/java \
+ -classpath "..\\build\\windows\\work\\java\\lib\\tools.jar" \
+ com.sun.tools.javac.Main \
+ -source 1.5 -target 1.5 \
+ -classpath "..\\build\\windows\\work\\lib\\core.jar;..\\build\\windows\\work\\lib\antlr.jar;..\\build\\windows\\work\\lib\\ecj.jar;..\\build\\windows\\work\\lib\\jna.jar;..\\build\\windows\\work\\lib\\oro.jar;..\\build\\windows\\work\\lib\\RXTXcomm.jar;..\\build\\windows\\work\\java\\lib\\tools.jar" \
+ -d ..\\build\\windows\\work\\classes \
+ src/processing/app/*.java \
+ src/processing/app/debug/*.java \
+ src/processing/app/syntax/*.java \
+ src/processing/app/preproc/*.java \
+ src/processing/app/tools/*.java \
+ src/processing/app/windows/*.java
cd ../build/windows/work/classes
rm -f ../lib/pde.jar
-zip -0rq ../lib/pde.jar .
-
-# back to build/windows
+zip -rq ../lib/pde.jar .
cd ../..
-
echo
echo Done.
diff --git a/build/windows/run.sh b/build/windows/run.sh
index 641586ea9..a86f10442 100644
--- a/build/windows/run.sh
+++ b/build/windows/run.sh
@@ -1,10 +1,6 @@
#!/bin/sh
-PATH=lib:$PATH
-CLASSPATH=\"java\\lib\\rt.jar\;lib\\RXTXcomm.jar\;lib\;lib\\build\;lib\\pde.jar\;lib\\mrj.jar\;lib\\antlr.jar\;lib\\oro.jar\;lib\\registry.jar\"
-export PATH
+CLASSPATH=lib\\pde.jar\;lib\\core.jar\;lib\\jna.jar\;lib\\ecj.jar\;lib\\antlr.jar\;lib\\oro.jar\;lib\\RXTXcomm.jar\;java\\lib\\tools.jar
export CLASSPATH
-#cd work && ./java/bin/java -Xint PdeBase
cd work && ./java/bin/java processing.app.Base
-#cd work && /cygdrive/c/jdk-1.3.1_11/bin/java PdeBase
diff --git a/build/windows/srun.sh b/build/windows/srun.sh
index 73c0b3a4f..d81943ba9 100755
--- a/build/windows/srun.sh
+++ b/build/windows/srun.sh
@@ -1,25 +1,25 @@
-#!/bin/sh
-
-QT_JAVA_PATH="$WINDIR\\system32\\QTJava.zip"
-if test -f "${QT_JAVA_PATH}"
-then
- #echo "Found Quicktime at $QT_JAVA_PATH"
-else
- QT_JAVA_PATH="$WINDIR\\system\\QTJava.zip"
- if test -f "${QT_JAVA_PATH}"
- echo "could not find qtjava.zip in either"
- echo "${WINDIR}\\system32\\qtjava.zip or"
- echo "${WINDIR}\\system\\qtjava.zip"
- echo "quicktime for java must be installed before building."
- exit 1;
- then
- #echo "Found Quicktime at $QT_JAVA_PATH"
- else
- fi
-fi
-
-CLASSPATH=\"java\\lib\\rt.jar\;lib\;lib\\build\;lib\\pde.jar\;lib\\kjc.jar\;lib\\antlr.jar\;lib\\oro.jar\;lib\\comm.jar\;lib\\RXTXcomm.jar\;${QT_JAVA_PATH}\"
-
-export CLASSPATH
-
-cd work && ./java/bin/java -Djava.compiler=NONE PdeBase
+#!/bin/sh
+
+QT_JAVA_PATH="$WINDIR\\system32\\QTJava.zip"
+if test -f "${QT_JAVA_PATH}"
+then
+ #echo "Found Quicktime at $QT_JAVA_PATH"
+else
+ QT_JAVA_PATH="$WINDIR\\system\\QTJava.zip"
+ if test -f "${QT_JAVA_PATH}"
+ echo "could not find qtjava.zip in either"
+ echo "${WINDIR}\\system32\\qtjava.zip or"
+ echo "${WINDIR}\\system\\qtjava.zip"
+ echo "quicktime for java must be installed before building."
+ exit 1;
+ then
+ #echo "Found Quicktime at $QT_JAVA_PATH"
+ else
+ fi
+fi
+
+CLASSPATH=\"java\\lib\\rt.jar\;lib\;lib\\build\;lib\\pde.jar\;lib\\kjc.jar\;lib\\antlr.jar\;lib\\oro.jar\;lib\\comm.jar\;lib\\RXTXcomm.jar\;${QT_JAVA_PATH}\"
+
+export CLASSPATH
+
+cd work && ./java/bin/java -Djava.compiler=NONE PdeBase
diff --git a/core/.classpath b/core/.classpath
new file mode 100644
index 000000000..fb5011632
--- /dev/null
+++ b/core/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/core/.project b/core/.project
new file mode 100644
index 000000000..9884df8b9
--- /dev/null
+++ b/core/.project
@@ -0,0 +1,17 @@
+
+
+ core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/core/.settings/org.eclipse.jdt.core.prefs b/core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..f80f9b559
--- /dev/null
+++ b/core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,261 @@
+#Thu Aug 28 17:36:28 EDT 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+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
diff --git a/core/.settings/org.eclipse.jdt.ui.prefs b/core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..cfbda4c3e
--- /dev/null
+++ b/core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,5 @@
+#Thu Jan 10 10:50:38 PST 2008
+eclipse.preferences.version=1
+formatter_profile=_two spaces no tabs
+formatter_settings_version=11
+org.eclipse.jdt.ui.text.custom_code_templates=
diff --git a/core/PGraphics.java b/core/PGraphics.java
deleted file mode 100644
index c1318177d..000000000
--- a/core/PGraphics.java
+++ /dev/null
@@ -1,4308 +0,0 @@
-/* -*- mode: jde; 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 library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-*/
-
-package processing.core;
-
-import java.awt.*;
-import java.awt.image.*;
-
-
-/**
- * Main graphics and rendering context, as well as
- * the base API implementation for processing "core".
- *
- * As of beta, this class is semi-disabled.
- */
-public abstract class PGraphics extends PImage implements PConstants {
-
- // transformed values
- // (to be used in rendering)
-
- static public final int X = 0; // transformed xyzw
- static public final int Y = 1; // formerly SX SY SZ
- static public final int Z = 2;
-
- static public final int R = 3; // actual rgb, after lighting
- static public final int G = 4; // fill stored here, transform in place
- static public final int B = 5;
- static public final int A = 6;
-
- // values that need no transformation
- // but will be used in rendering
-
- static public final int U = 7; // texture
- static public final int V = 8;
-
- // incoming values, raw and untransformed
- // (won't be used in rendering)
-
- static public final int MX = 9; // model coords xyz
- static public final int MY = 10;
- static public final int MZ = 11;
-
- /** stroke argb values */
- static public final int SR = 12;
- static public final int SG = 13;
- static public final int SB = 14;
- static public final int SA = 15;
-
- /** stroke weight */
- static public final int SW = 16;
-
- // not used in rendering
- // only used for calculating colors
-
- static public final int NX = 17; // normal
- static public final int NY = 18;
- static public final int NZ = 19;
-
- static public final int VX = 20; // view space coords
- static public final int VY = 21;
- static public final int VZ = 22;
- static public final int VW = 23;
-
- // Ambient color (usually to be kept the same as diffuse)
- // fill(_) sets both ambient and diffuse.
- static public final int AR = 24;
- static public final int AG = 25;
- static public final int AB = 26;
-
- // Diffuse is shared with fill.
- static public final int DR = 3;
- static public final int DG = 4;
- static public final int DB = 5;
- static public final int DA = 6;
-
- //specular (by default kept white)
- static public final int SPR = 27;
- static public final int SPG = 28;
- static public final int SPB = 29;
- //GL doesn't use a separate specular alpha, but we do (we're better)
- static public final int SPA = 30;
-
- static public final int SHINE = 31;
-
- //emissive (by default kept black)
- static public final int ER = 32;
- static public final int EG = 33;
- static public final int EB = 34;
-
- //has this vertex been lit yet
- static public final int BEEN_LIT = 35;
-
- static final int VERTEX_FIELD_COUNT = 36;
-
- // line & triangle fields (note how these overlap)
-
- static public final int INDEX = 0; // shape index
- static public final int VERTEX1 = 1;
- static public final int VERTEX2 = 2;
- static public final int VERTEX3 = 3; // (triangles only)
- static public final int TEXTURE_INDEX = 4; // (triangles only)
- static public final int STROKE_MODE = 3; // (lines only)
- static public final int STROKE_WEIGHT = 4; // (lines only)
-
- static public final int LINE_FIELD_COUNT = 5;
- static public final int TRIANGLE_FIELD_COUNT = 5;
-
- static public final int TRI_DIFFUSE_R = 0;
- static public final int TRI_DIFFUSE_G = 1;
- static public final int TRI_DIFFUSE_B = 2;
- static public final int TRI_DIFFUSE_A = 3;
- static public final int TRI_SPECULAR_R = 4;
- static public final int TRI_SPECULAR_G = 5;
- static public final int TRI_SPECULAR_B = 6;
- static public final int TRI_SPECULAR_A = 7;
-
- static public final int TRIANGLE_COLOR_COUNT = 8;
-
-
- // normal modes for lighting, these have the uglier naming
- // because the constants are never seen by users
-
- /// normal calculated per triangle
- static public final int AUTO_NORMAL = 0;
- /// one normal manually specified per shape
- static public final int MANUAL_SHAPE_NORMAL = 1;
- /// normals specified for each shape vertex
- static public final int MANUAL_VERTEX_NORMAL = 2;
-
-
- /// width minus one (useful for many calculations)
- public int width1;
-
- /// height minus one (useful for many calculations)
- public int height1;
-
- /// width * height (useful for many calculations)
- public int pixelCount;
-
- /// true if defaults() has been called a first time
- protected boolean defaultsInited;
-
- /// true if in-between beginDraw() and endDraw()
- protected boolean insideDraw;
-
- /// true if in the midst of resize (no drawing can take place)
- boolean insideResize;
-
- // ........................................................
-
- /**
- * true if this is the main drawing surface for a particular sketch.
- * This would be set to false for an offscreen buffer or if it were
- * created any other way than size(). When this is set, the listeners
- * are also added to the sketch.
- */
- protected boolean mainDrawingSurface;
-
- // ........................................................
-
- // specifics for java memoryimagesource
- DirectColorModel cm;
- MemoryImageSource mis;
- public Image image;
-
- // ........................................................
-
- // used by recordRaw()
- public PGraphics raw;
-
- // ........................................................
-
- // needs to happen before background() is called
- // and resize.. so it's gotta be outside
- protected boolean hints[] = new boolean[HINT_COUNT];
-
- // ........................................................
-
- // underscored_names are used for private functions or variables
-
- /** The current colorMode */
- public int colorMode; // = RGB;
-
- /** Max value for red (or hue) set by colorMode */
- public float colorModeX; // = 255;
-
- /** Max value for green (or saturation) set by colorMode */
- public float colorModeY; // = 255;
-
- /** Max value for blue (or value) set by colorMode */
- public float colorModeZ; // = 255;
-
- /** Max value for alpha set by colorMode */
- public float colorModeA; // = 255;
-
- /** True if colors are not in the range 0..1 */
- boolean colorScale; // = true;
-
- /** True if colorMode(RGB, 255) */
- boolean colorRgb255; // = true;
-
- // ........................................................
-
- /**
- * true if tint() is enabled (read-only).
- * Using tint/tintColor seems a better option for naming than
- * tintEnabled/tint because the latter seems ugly, even though
- * g.tint as the actual color seems a little more intuitive,
- * it's just that g.tintEnabled is even more unintuitive.
- * Same goes for fill and stroke et al.
- */
- public boolean tint;
-
- /** tint that was last set (read-only) */
- public int tintColor;
-
- protected boolean tintAlpha;
- protected float tintR, tintG, tintB, tintA;
- protected int tintRi, tintGi, tintBi, tintAi;
-
- // ........................................................
-
- /** true if fill() is enabled, (read-only) */
- public boolean fill;
-
- /** fill that was last set (read-only) */
- public int fillColor = 0xffFFFFFF;
-
- protected boolean fillAlpha;
- protected float fillR, fillG, fillB, fillA;
- protected int fillRi, fillGi, fillBi, fillAi;
-
- // ........................................................
-
- /** true if stroke() is enabled, (read-only) */
- public boolean stroke;
-
- /** stroke that was last set (read-only) */
- public int strokeColor = 0xff000000;
-
- protected boolean strokeAlpha;
- protected float strokeR, strokeG, strokeB, strokeA;
- protected int strokeRi, strokeGi, strokeBi, strokeAi;
-
- // ........................................................
-
- /** Last background color that was set, zero if an image */
- public int backgroundColor = 0xffCCCCCC;
-
- protected boolean backgroundAlpha;
- protected float backgroundR, backgroundG, backgroundB, backgroundA;
- protected int backgroundRi, backgroundGi, backgroundBi, backgroundAi;
-
- // ........................................................
-
- // internal color for setting/calculating
- protected float calcR, calcG, calcB, calcA;
- int calcRi, calcGi, calcBi, calcAi;
- int calcColor;
- boolean calcAlpha;
-
- /** The last rgb value converted to HSB */
- int cacheHsbKey;
- /** Result of the last conversion to HSB */
- float cacheHsbValue[] = new float[3]; // inits to zero
-
- // ........................................................
-
- /**
- * Last value set by strokeWeight() (read-only). This has a default
- * setting, rather than fighting with renderers about whether that
- * renderer supports thick lines.
- */
- public float strokeWeight = 1;
-
- /**
- * Set by strokeJoin() (read-only). This has a default setting
- * so that strokeJoin() need not be called by defaults,
- * because subclasses may not implement it (i.e. PGraphicsGL)
- */
- public int strokeJoin = MITER;
-
- /**
- * Set by strokeCap() (read-only). This has a default setting
- * so that strokeCap() need not be called by defaults,
- * because subclasses may not implement it (i.e. PGraphicsGL)
- */
- public int strokeCap = ROUND;
-
- // ........................................................
-
- /**
- * Model transformation of the form m[row][column],
- * which is a "column vector" (as opposed to "row vector") matrix.
- */
- public float m00, m01, m02, m03;
- public float m10, m11, m12, m13;
- public float m20, m21, m22, m23;
- public float m30, m31, m32, m33;
-
- static final int MATRIX_STACK_DEPTH = 32;
- float matrixStack[][] = new float[MATRIX_STACK_DEPTH][16];
- int matrixStackDepth;
-
- // ........................................................
-
- //Path path;
-
- // ........................................................
-
- /**
- * Type of shape passed to beginShape(),
- * zero if no shape is currently being drawn.
- */
- protected int shape;
-
- // vertices
- static final int DEFAULT_VERTICES = 512;
- protected float vertices[][] =
- new float[DEFAULT_VERTICES][VERTEX_FIELD_COUNT];
- protected int vertexCount; // total number of vertices
-
-
- // ........................................................
-
- protected boolean bezierInited = false;
- public int bezierDetail = 20;
- // msjvm complained when bezier_basis was final
- protected float bezier_basis[][] = {
- { -1, 3, -3, 1},
- { 3, -6, 3, 0},
- { -3, 3, 0, 0},
- { 1, 0, 0, 0}
- };
-
- protected PMatrix bezierBasis =
- new PMatrix(-1, 3, -3, 1,
- 3, -6, 3, 0,
- -3, 3, 0, 0,
- 1, 0, 0, 0);
-
- protected float bezierForwardMatrix[][]; // = new float[4][4];
- protected float bezierDrawMatrix[][]; // = new float[4][4];
-
- // ........................................................
-
- protected boolean curve_inited = false;
- protected int curveDetail = 20;
- // catmull-rom basis matrix, perhaps with optional s parameter
- public float curveTightness = 0;
- protected float curve_basis[][]; // = new float[4][4];
- protected float curve_forward[][]; // = new float[4][4];
- protected float curve_draw[][];
-
- protected PMatrix bezierBasisInverse;
- protected PMatrix curveToBezierMatrix;
-
- // ........................................................
-
- // spline vertices
-
- static final int DEFAULT_SPLINE_VERTICES = 128;
- protected float splineVertices[][];
- protected int splineVertexCount;
-
- // ........................................................
-
- // precalculate sin/cos lookup tables [toxi]
- // circle resolution is determined from the actual used radii
- // passed to ellipse() method. this will automatically take any
- // scale transformations into account too
-
- // [toxi 031031]
- // changed table's precision to 0.5 degree steps
- // introduced new vars for more flexible code
- static final protected float sinLUT[];
- static final protected float cosLUT[];
- static final protected float SINCOS_PRECISION = 0.5f;
- static final protected int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION);
- static {
- sinLUT = new float[SINCOS_LENGTH];
- cosLUT = new float[SINCOS_LENGTH];
- for (int i = 0; i < SINCOS_LENGTH; i++) {
- sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
- cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
- }
- }
-
- // ........................................................
-
- /** The current rect mode (read-only) */
- public int rectMode;
-
- /** The current ellipse mode (read-only) */
- public int ellipseMode;
-
- /** The current text font (read-only) */
- public PFont textFont;
-
- /** The current font if a Java version of it is installed */
- public Font textFontNative;
-
- /** Metrics for the current native Java font */
- public FontMetrics textFontNativeMetrics;
-
- /** The current text align (read-only) */
- public int textAlign;
-
- /** The current vertical text alignment (read-only) */
- public int textAlignY;
-
- /** The current text mode (read-only) */
- public int textMode;
-
- /** The current text size (read-only) */
- public float textSize;
-
- /** The current text leading (read-only) */
- public float textLeading;
-
- /** Last text position, because text often mixed on lines together */
- public float textX, textY, textZ;
-
- /**
- * Internal buffer used by the text() functions
- * because the String object is slow
- */
- protected char textBuffer[] = new char[8 * 1024];
- protected char textWidthBuffer[] = new char[8 * 1024];
-
-
- //////////////////////////////////////////////////////////////
-
- // VARIABLES FOR 3D (used to prevent the need for a subclass)
-
-
- /** The modelview matrix. */
- public PMatrix modelview;
-
- /** Inverse modelview matrix, used for lighting. */
- public PMatrix modelviewInv;
-
- /**
- * The camera matrix, the modelview will be set to this on beginDraw.
- */
- public PMatrix camera;
-
- /** Inverse camera matrix */
- public PMatrix cameraInv;
-
- // ........................................................
-
- // Material properties
-
- public float ambientR, ambientG, ambientB;
- public float specularR, specularG, specularB, specularA;
- public float emissiveR, emissiveG, emissiveB;
- public float shininess;
-
- // ........................................................
-
- /** Camera field of view (in radians, as of rev 86) */
- public float cameraFOV;
-
- /** Position of the camera */
- public float cameraX, cameraY, cameraZ;
-
- public float cameraNear, cameraFar;
- public float cameraAspect;
-
- // projection matrix
- public PMatrix projection; // = new PMatrix();
-
- // ........................................................
-
- /// the stencil buffer
- public int stencil[];
-
- /// depth buffer
- public float zbuffer[];
-
- // ........................................................
-
- /** Maximum lights by default is 8, which is arbitrary,
- but is the minimum defined by OpenGL */
- public static final int MAX_LIGHTS = 8;
-
- public int lightCount = 0;
-
- /** Light types */
- public int lightType[];
-
- /** Light positions */
- public float lightPosition[][];
- //public float lightsX[], lightsY[], lightsZ[];
-
- /** Light direction (normalized vector) */
- public float lightNormal[][];
- //public float lightsNX[], lightsNY[], lightsNZ[];
-
- /** Light falloff */
- public float lightFalloffConstant[];
- public float lightFalloffLinear[];
- public float lightFalloffQuadratic[];
-
- /** Light spot angle */
- public float lightSpotAngle[];
-
- /** Cosine of light spot angle */
- public float lightSpotAngleCos[];
-
- /** Light spot concentration */
- public float lightSpotConcentration[];
-
- /** Diffuse colors for lights.
- * For an ambient light, this will hold the ambient color.
- * Internally these are stored as numbers between 0 and 1. */
- public float lightDiffuse[][];
-
- /** Specular colors for lights.
- Internally these are stored as numbers between 0 and 1. */
- public float lightSpecular[][];
-
- /** Current specular color for lighting */
- public float currentLightSpecular[];
-
- /** Current light falloff */
- public float currentLightFalloffConstant;
- public float currentLightFalloffLinear;
- public float currentLightFalloffQuadratic;
-
- // ........................................................
-
- /**
- * Sets whether texture coordinates passed to
- * vertex() calls will be based on coordinates that are
- * based on the IMAGE or NORMALIZED.
- */
- public int textureMode;
-
- /**
- * Current horizontal coordinate for texture, will always
- * be between 0 and 1, even if using textureMode(IMAGE).
- */
- public float textureU;
-
- /** Current vertical coordinate for texture, see above. */
- public float textureV;
-
- /** Current image being used as a texture */
- public PImage textureImage;
-
- // ........................................................
-
- /**
- * Normals
- */
- public float normalX, normalY, normalZ;
- public int normalMode;
- public int normalCount;
-
- // ........................................................
-
- // [toxi031031] new & faster sphere code w/ support flexibile resolutions
- // will be set by sphereDetail() or 1st call to sphere()
- public int sphereDetail = 0;
-
-
-
- //////////////////////////////////////////////////////////////
-
- // INTERNAL
-
-
- /**
- * Constructor for the PGraphics object. This prototype only exists
- * because of annoying java compilers, and cannot be used.
- */
- /*
- protected PGraphics() { }
- */
-
-
- /**
- * Constructor for the PGraphics object. Use this to ensure that
- * the defaults get set properly. In a subclass, use this(w, h)
- * as the first line of a subclass' constructor to properly set
- * the internal fields and defaults.
- *
- * @param iwidth viewport width
- * @param iheight viewport height
- * @param parent null unless this is the main drawing surface
- */
- public PGraphics(int iwidth, int iheight, PApplet parent) {
- this.parent = parent;
- if (parent != null) setMainDrawingSurface();
-/*
- // if this is being created by createGraphics(), the parent applet
- // will be set later via another method.
- if (parent != null) {
- mainDrawingSurface = true;
- // base images must be opaque (for performance and general
- // headache reasons.. argh, a semi-transparent opengl surface?)
- // use createGraphics() if you want a transparent surface.
- format = RGB;
- parent.addListeners();
- }
-*/
- resize(iwidth, iheight);
- }
-
-
- /**
- * Set this as the main drawing surface. Meaning that it can safely be
- * set to opaque (given a default gray background) and listeners for
- * the mouse and keyboard added.
- *
- * This should only be used by subclasses of PGraphics.
- */
- public void setMainDrawingSurface() { // ignore
- mainDrawingSurface = true;
- // base images must be opaque (for performance and general
- // headache reasons.. argh, a semi-transparent opengl surface?)
- // use createGraphics() if you want a transparent surface.
- format = RGB;
- parent.addListeners();
- }
-
-
- /**
- * Called in repsonse to a resize event, handles setting the
- * new width and height internally, as well as re-allocating
- * the pixel buffer for the new size.
- *
- * Note that this will nuke any camera settings.
- */
- public void resize(int iwidth, int iheight) { // ignore
- //System.out.println("resize " + iwidth + " " + iheight);
- insideDrawWait();
- insideResize = true;
-
- width = iwidth;
- height = iheight;
- width1 = width - 1;
- height1 = height - 1;
-
- allocate();
-
- insideResize = false; // ok to draw again
- }
-
-
- /**
- * Parent thread has requested that visual action be taken.
- * This is broken out like this because the OpenGL library
- * handles updates in a very different way.
- */
- public void requestDisplay(PApplet pa) { // ignore
- pa.handleDisplay();
- }
-
-
- // broken out because of subclassing
- abstract protected void allocate();
-
-
-
- //////////////////////////////////////////////////////////////
-
- // FRAME
-
-
- protected void insideResizeWait() {
- /*
- while (insideResize) {
- //System.out.println("waiting");
- try {
- Thread.sleep(5);
- } catch (InterruptedException e) { }
- }
- */
- }
-
-
- protected void insideDrawWait() {
- /*
- while (insideDraw) {
- //System.out.println("waiting");
- try {
- Thread.sleep(5);
- } catch (InterruptedException e) { }
- }
- */
- }
-
-
- /**
- * Prepares the PGraphics for drawing.
- *
- * When creating your own PGraphics, you should call this before
- * drawing anything.
- */
- abstract public void beginDraw(); // ignore
-
-
- /**
- * This will finalize rendering so that it can be shown on-screen.
- *
- * When creating your own PGraphics, you should call this when
- * you're finished drawing.
- */
- abstract public void endDraw(); // ignore
-
-
- /**
- * Set engine's default values. This has to be called by PApplet,
- * somewhere inside setup() or draw() because it talks to the
- * graphics buffer, meaning that for subclasses like OpenGL, there
- * needs to be a valid graphics context to mess with otherwise
- * you'll get some good crashing action.
- */
- public void defaults() { // ignore
- //System.out.println("PGraphics.defaults() " + width + " " + height);
-
- colorMode(RGB, 255);
- fill(255);
- stroke(0);
- // other stroke attributes are set in the initializers
- // inside the class (see above, strokeWeight = 1 et al)
-
- // init shape stuff
- shape = 0;
-
- // init matrices (must do before lights)
- matrixStackDepth = 0;
-
- rectMode(CORNER);
- ellipseMode(CENTER);
- //arcMode(CENTER);
- //angleMode(RADIANS);
-
- // no current font
- textFont = null;
- textSize = 12;
- textLeading = 14;
- textAlign = LEFT;
- textMode = MODEL;
-
- // if this fella is associated with an applet, then clear its background.
- // if it's been created by someone else through createGraphics,
- // they have to call background() themselves, otherwise everything gets
- // a gray background (when just a transparent surface or an empty pdf
- // is what's desired)
- if (mainDrawingSurface) {
- //System.out.println("main drawing surface");
- background(backgroundColor);
- }
-
- defaultsInited = true;
- }
-
-
- protected void flush() {
- // no-op, mostly for P3D to write sorted stuff
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // HINTS
-
- /**
- * Enable a hint option.
- *
- * For the most part, hints are temporary api quirks,
- * for which a proper api hasn't been properly worked out.
- * for instance SMOOTH_IMAGES existed because smooth()
- * wasn't yet implemented, but it will soon go away.
- *
- * They also exist for obscure features in the graphics
- * engine, like enabling/disabling single pixel lines
- * that ignore the zbuffer, the way they do in alphabot.
- *
- * Current hint options:
- *
- *
DISABLE_DEPTH_TEST -
- * turns off the z-buffer in the P3D or OPENGL renderers.
- *
- */
- public void hint(int which) {
- hints[which] = true;
- }
-
-
- /**
- * Disable a hint.
- */
- public void noHint(int which) {
- hints[which] = false;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // SHAPES
-
- /**
- * Start a new shape of type POLYGON
- */
- public void beginShape() {
- beginShape(POLYGON);
- }
-
-
- /**
- * Start a new shape.
- *
- * Differences between beginShape() and line() and point() methods.
- *
- * beginShape() is intended to be more flexible at the expense of being
- * a little more complicated to use. it handles more complicated shapes
- * that can consist of many connected lines (so you get joins) or lines
- * mixed with curves.
- *
- * The line() and point() command are for the far more common cases
- * (particularly for our audience) that simply need to draw a line
- * or a point on the screen.
- *
- * From the code side of things, line() may or may not call beginShape()
- * to do the drawing. In the beta code, they do, but in the alpha code,
- * they did not. they might be implemented one way or the other depending
- * on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
- * meaning the speed that things run at vs. the speed it takes me to write
- * the code and maintain it. for beta, the latter is most important so
- * that's how things are implemented.
- */
- abstract public void beginShape(int kind);
- /*
- shape = kind;
-
- // reset vertex, line and triangle information
- // every shape is rendered at endShape();
- vertexCount = 0;
-
- splineVertexCount = 0;
- //spline_vertices_flat = true;
-
- //strokeChanged = false;
- //fillChanged = false;
- //normalChanged = false;
- */
-
-
- public void normal(float nx, float ny, float nz) {
- //depthError("normal");
- }
-
-
- /**
- * Set texture mode to either to use coordinates based on the IMAGE
- * (more intuitive for new users) or NORMALIZED (better for advanced chaps)
- */
- public void textureMode(int mode) {
- this.textureMode = mode;
- }
-
-
- /**
- * Set texture image for current shape.
- * Needs to be called between @see beginShape and @see endShape
- *
- * @param image reference to a PImage object
- */
- public void texture(PImage image) {
- textureImage = image;
- }
-
-
- /**
- * Set (U, V) coords for the next vertex in the current shape.
- * This is ugly as its own function, and will (almost?) always be
- * coincident with a call to vertex. As of beta, this was moved to
- * the protected method you see here, and called from an optional
- * param of and overloaded vertex().
- *
- * The parameters depend on the current textureMode. When using
- * textureMode(IMAGE), the coordinates will be relative to the size
- * of the image texture, when used with textureMode(NORMAL),
- * they'll be in the range 0..1.
- *
- * Used by both PGraphics2D (for images) and PGraphics3D.
- */
- protected void textureVertex(float u, float v) {
- if (textureImage == null) {
- throw new RuntimeException("need to set an image with texture() " +
- "before using u and v coordinates");
- }
- if (textureMode == IMAGE) {
- u /= (float) textureImage.width;
- v /= (float) textureImage.height;
- }
-
- textureU = u;
- textureV = v;
-
- if (textureU < 0) textureU = 0;
- else if (textureU > 1) textureU = 1;
-
- if (textureV < 0) textureV = 0;
- else if (textureV > 1) textureV = 1;
- }
-
-
- // eventually need to push a "default" setup down to this class
- abstract public void vertex(float x, float y);
- /*
- splineVertexCount = 0;
- //float vertex[];
-
- if (vertexCount == vertices.length) {
- float temp[][] = new float[vertexCount<<1][VERTEX_FIELD_COUNT];
- System.arraycopy(vertices, 0, temp, 0, vertexCount);
- vertices = temp;
- //message(CHATTER, "allocating more vertices " + vertices.length);
- }
- // not everyone needs this, but just easier to store rather
- // than adding another moving part to the code...
- vertices[vertexCount][MX] = x;
- vertices[vertexCount][MY] = y;
- vertexCount++;
-
- switch (shape) {
-
- case POINTS:
- point(x, y);
- break;
-
- case LINES:
- if ((vertexCount % 2) == 0) {
- line(vertices[vertexCount-2][MX],
- vertices[vertexCount-2][MY], x, y);
- }
- break;
-
- case LINE_STRIP:
- case LINE_LOOP:
- if (vertexCount == 1) {
- path = new Path();
- path.moveTo(x, y);
- } else {
- path.lineTo(x, y);
- }
- break;
-
- case TRIANGLES:
- if ((vertexCount % 3) == 0) {
- triangle(vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY],
- vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY],
- x, y);
- }
- break;
-
- case TRIANGLE_STRIP:
- if (vertexCount == 3) {
- triangle(vertices[0][MX], vertices[0][MY],
- vertices[1][MX], vertices[1][MY],
- x, y);
- } else if (vertexCount > 3) {
- path = new Path();
- // when vertexCount == 4, draw an un-closed triangle
- // for indices 2, 3, 1
- path.moveTo(vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY]);
- path.lineTo(vertices[vertexCount - 1][MX],
- vertices[vertexCount - 1][MY]);
- path.lineTo(vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY]);
- draw_shape(path);
- }
- break;
-
- case TRIANGLE_FAN:
- if (vertexCount == 3) {
- triangle(vertices[0][MX], vertices[0][MY],
- vertices[1][MX], vertices[1][MY],
- x, y);
- } else if (vertexCount > 3) {
- path = new Path();
- // when vertexCount > 3, draw an un-closed triangle
- // for indices 0 (center), previous, current
- path.moveTo(vertices[0][MX],
- vertices[0][MY]);
- path.lineTo(vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY]);
- path.lineTo(x, y);
- draw_shape(path);
- }
- break;
-
- case QUADS:
- if ((vertexCount % 4) == 0) {
- quad(vertices[vertexCount - 4][MX],
- vertices[vertexCount - 4][MY],
- vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY],
- vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY],
- x, y);
- }
- break;
-
- case QUAD_STRIP:
- // 0---2---4
- // | | |
- // 1---3---5
- if (vertexCount == 4) {
- // note difference in winding order:
- quad(vertices[0][MX], vertices[0][MY],
- vertices[2][MX], vertices[2][MY],
- x, y,
- vertices[1][MX], vertices[1][MY]);
-
- } else if (vertexCount > 4) {
- path = new Path();
- // when vertexCount == 5, draw an un-closed triangle
- // for indices 2, 4, 5, 3
- path.moveTo(vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY]);
- path.lineTo(vertices[vertexCount - 1][MX],
- vertices[vertexCount - 1][MY]);
- path.lineTo(x, y);
- path.lineTo(vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY]);
- draw_shape(path);
- }
- break;
-
- case POLYGON:
- //case CONCAVE_POLYGON:
- //case CONVEX_POLYGON:
- if (vertexCount == 1) {
- path = new Path();
- path.moveTo(x, y);
- } else {
- path.lineTo(x, y);
- }
- break;
- }
- */
-
-
- abstract public void vertex(float x, float y, float z);
-
-
- abstract public void vertex(float x, float y, float u, float v);
-
-
- abstract public void vertex(float x, float y, float z, float u, float v);
-
-
- public void bezierVertex(float x2, float y2,
- float x3, float y3,
- float x4, float y4) {
- bezierVertex(x2, y2, Float.MAX_VALUE,
- x3, y3, Float.MAX_VALUE,
- x4, y4, Float.MAX_VALUE);
- }
-
-
- /**
- * See notes with the bezier() function.
- */
- public void bezierVertex(float x2, float y2, float z2,
- float x3, float y3, float z3,
- float x4, float y4, float z4) {
- if (shape != POLYGON) {
- throw new RuntimeException("beginShape() and vertex() " +
- "must be used before bezierVertex()");
- }
- if (splineVertexCount > 0) {
- float vertex[] = splineVertices[splineVertexCount-1];
- splineVertex(vertex[MX], vertex[MY], vertex[MZ], true);
-
- } else if (vertexCount > 0) {
- // make sure there's at least a call to vertex()
- float vertex[] = vertices[vertexCount-1];
- splineVertex(vertex[MX], vertex[MY], vertex[MZ], true);
-
- } else {
- throw new RuntimeException("A call to vertex() must be used " +
- "before bezierVertex()");
- }
- splineVertex(x2, y2, z2, true);
- splineVertex(x3, y3, z3, true);
- splineVertex(x4, y4, z4, true);
- }
-
-
- /**
- * See notes with the curve() function.
- */
- public void curveVertex(float x, float y) {
- splineVertex(x, y, Float.MAX_VALUE, false);
- }
-
-
- /**
- * See notes with the curve() function.
- */
- public void curveVertex(float x, float y, float z) {
- splineVertex(x, y, z, false);
- }
-
-
- /**
- * Implementation of generic spline vertex, will add coords to
- * the splineVertices[] array and emit calls to draw segments
- * as needed (every fourth point for bezier or every point starting
- * with the fourth for catmull-rom).
- * @param z z-coordinate, set to MAX_VALUE if it's 2D
- * @param bezier true if it's a bezier instead of catmull-rom
- */
- protected void splineVertex(float x, float y, float z, boolean bezier) {
- // to improve processing applet load times, don't allocate
- // space for the vertex data until actual use
- if (splineVertices == null) {
- splineVertices = new float[DEFAULT_SPLINE_VERTICES][VERTEX_FIELD_COUNT];
- }
-
- // if more than 128 points, shift everything back to the beginning
- if (splineVertexCount == DEFAULT_SPLINE_VERTICES) {
- System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-3], 0,
- splineVertices[0], 0, VERTEX_FIELD_COUNT);
- System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-2], 0,
- splineVertices[1], 0, VERTEX_FIELD_COUNT);
- System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES-1], 0,
- splineVertices[2], 0, VERTEX_FIELD_COUNT);
- splineVertexCount = 3;
- }
-
- float vertex[] = splineVertices[splineVertexCount];
-
- vertex[MX] = x;
- vertex[MY] = y;
-
- if (fill) {
- vertex[R] = fillR;
- vertex[G] = fillG;
- vertex[B] = fillB;
- vertex[A] = fillA;
- }
-
- if (stroke) {
- vertex[SR] = strokeR;
- vertex[SG] = strokeG;
- vertex[SB] = strokeB;
- vertex[SA] = strokeA;
- vertex[SW] = strokeWeight;
- }
-
- if (textureImage != null) {
- vertex[U] = textureU;
- vertex[V] = textureV;
- }
-
- // when the coords are Float.MAX_VALUE, then treat as a 2D curve
- int dimensions = (z == Float.MAX_VALUE) ? 2 : 3;
-
- if (dimensions == 3) {
- vertex[MZ] = z;
-
- vertex[NX] = normalX;
- vertex[NY] = normalY;
- vertex[NZ] = normalZ;
- }
-
- splineVertexCount++;
-
- // draw a segment if there are enough points
- if (splineVertexCount > 3) {
- if (bezier) {
- if ((splineVertexCount % 4) == 0) {
- if (!bezierInited) bezierInit();
- splineSegment(splineVertexCount-4,
- splineVertexCount-4,
- bezierDrawMatrix, dimensions,
- bezierDetail);
- }
- } else { // catmull-rom curve (!bezier)
- if (!curve_inited) curve_init();
- splineSegment(splineVertexCount-4,
- splineVertexCount-3,
- curve_draw, dimensions,
- curveDetail);
- }
- }
- }
-
-
- /** This feature is in testing, do not use or rely upon its implementation */
- public void breakShape() {
- }
-
-
- public final void endShape() {
- endShape(OPEN);
- }
-
-
- abstract public void endShape(int mode);
-
-
-
- //////////////////////////////////////////////////////////////
-
- // COMPOUND PATHS
-
-
- /**
- * Begin a new path. This can be used after beginShape() to draw
- * a compound path (i.e. to draw shape with a hole on the interior)
- * For instance, to draw a shape that has a hole in its interior,
- * the format would be:
- *
- * beginShape();
- * beginPath();
- * // multiple calls to vertex() that draw the exterior shape
- * endPath();
- * beginPath();
- * // several calls to vertex() to draw the interior hole
- * endPath();
- * // more beginPath/endPath pairs can be used for additional holes
- * endShape();
- *
- *
- * This will probably be available only with the OpenGL renderer,
- * because it has a built-in tesselator from GLU.
- */
- //public void beginPath() {
- //throw new RuntimeException("beginPath() is not available");
- //}
-
-
- /**
- * End a path. Use this with beginPath() to close out a compound path.
- *
- * This will probably be available only with the OpenGL renderer,
- * because it has a built-in tesselator from GLU.
- */
- //public void endPath() {
- //throw new RuntimeException("endPath() is not available");
- //}
-
-
-
- //////////////////////////////////////////////////////////////
-
- // SIMPLE SHAPES WITH ANALOGUES IN beginShape()
-
-
- public void point(float x, float y) {
- beginShape(POINTS);
- vertex(x, y);
- endShape();
- }
-
-
- public void point(float x, float y, float z) {
- beginShape(POINTS);
- vertex(x, y, z);
- endShape();
- }
-
-
- public void line(float x1, float y1, float x2, float y2) {
- beginShape(LINES);
- vertex(x1, y1);
- vertex(x2, y2);
- endShape();
- }
-
-
- public void line(float x1, float y1, float z1,
- float x2, float y2, float z2) {
- beginShape(LINES);
- vertex(x1, y1, z1);
- vertex(x2, y2, z2);
- endShape();
- }
-
-
- public void triangle(float x1, float y1, float x2, float y2,
- float x3, float y3) {
- beginShape(TRIANGLES);
- vertex(x1, y1);
- vertex(x2, y2);
- vertex(x3, y3);
- endShape();
- }
-
-
- public void quad(float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4) {
- beginShape(QUADS);
- vertex(x1, y1);
- vertex(x2, y2);
- vertex(x3, y3);
- vertex(x4, y4);
- endShape();
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // RECT
-
-
- public void rectMode(int mode) {
- rectMode = mode;
- }
-
-
- public void rect(float x1, float y1, float x2, float y2) {
- float hradius, vradius;
- switch (rectMode) {
- case CORNERS:
- break;
- case CORNER:
- x2 += x1; y2 += y1;
- break;
- case RADIUS:
- hradius = x2;
- vradius = y2;
- x2 = x1 + hradius;
- y2 = y1 + vradius;
- x1 -= hradius;
- y1 -= vradius;
- break;
- case CENTER:
- hradius = x2 / 2.0f;
- vradius = y2 / 2.0f;
- x2 = x1 + hradius;
- y2 = y1 + vradius;
- x1 -= hradius;
- y1 -= vradius;
- }
-
- if (x1 > x2) {
- float temp = x1; x1 = x2; x2 = temp;
- }
-
- if (y1 > y2) {
- float temp = y1; y1 = y2; y2 = temp;
- }
-
- rectImpl(x1, y1, x2, y2);
- }
-
-
- protected void rectImpl(float x1, float y1, float x2, float y2) {
- quad(x1, y1, x2, y1, x2, y2, x1, y2);
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // ELLIPSE AND ARC
-
-
- public void ellipseMode(int mode) {
- ellipseMode = mode;
- }
-
-
- public void ellipse(float a, float b, float c, float d) {
- float x = a;
- float y = b;
- float w = c;
- float h = d;
-
- if (ellipseMode == CORNERS) {
- w = c - a;
- h = d - b;
-
- } else if (ellipseMode == RADIUS) {
- x = a - c;
- y = b - d;
- w = c * 2;
- h = d * 2;
-
- } else if (ellipseMode == CENTER) {
- x = a - c/2f;
- y = b - d/2f;
- }
-
- if (w < 0) { // undo negative width
- x += w;
- w = -w;
- }
-
- if (h < 0) { // undo negative height
- y += h;
- h = -h;
- }
-
- ellipseImpl(x, y, w, h);
- }
-
-
- protected void ellipseImpl(float x1, float y1, float w, float h) {
- float hradius = w / 2f;
- float vradius = h / 2f;
-
- float centerX = x1 + hradius;
- float centerY = y1 + vradius;
-
- // adapt accuracy to radii used w/ a minimum of 4 segments [toxi]
- // now uses current scale factors to determine "real" transformed radius
-
- //int cAccuracy = (int)(4+Math.sqrt(hradius*abs(m00)+vradius*abs(m11))*2);
- //int cAccuracy = (int)(4+Math.sqrt(hradius+vradius)*2);
-
- // notched this up to *3 instead of *2 because things were
- // looking a little rough, i.e. the calculate->arctangent example [fry]
-
- // also removed the m00 and m11 because those were causing weirdness
- // need an actual measure of magnitude in there [fry]
-
- int accuracy = (int)(4+Math.sqrt(hradius+vradius)*3);
- //System.out.println("accuracy is " + accuracy);
-
- // [toxi031031] adapted to use new lookup tables
- float inc = (float)SINCOS_LENGTH / accuracy;
-
- float val = 0;
- /*
- beginShape(POLYGON);
- for (int i = 0; i < cAccuracy; i++) {
- vertex(centerX + cosLUT[(int) val] * hradius,
- centerY + sinLUT[(int) val] * vradius);
- val += inc;
- }
- endShape();
- */
-
- if (fill) {
- boolean savedStroke = stroke;
- stroke = false;
-
- beginShape(TRIANGLE_FAN);
- normal(0, 0, 1);
- vertex(centerX, centerY);
- for (int i = 0; i < accuracy; i++) {
- vertex(centerX + cosLUT[(int) val] * hradius,
- centerY + sinLUT[(int) val] * vradius);
- val += inc;
- }
- // back to the beginning
- vertex(centerX + cosLUT[0] * hradius,
- centerY + sinLUT[0] * vradius);
- endShape();
-
- stroke = savedStroke;
- }
-
- if (stroke) {
- boolean savedFill = fill;
- fill = false;
-
- val = 0;
- beginShape(); //LINE_LOOP);
- for (int i = 0; i < accuracy; i++) {
- vertex(centerX + cosLUT[(int) val] * hradius,
- centerY + sinLUT[(int) val] * vradius);
- val += inc;
- }
- endShape(CLOSE);
-
- fill = savedFill;
- }
- }
-
-
- /**
- * Identical parameters and placement to ellipse,
- * but draws only an arc of that ellipse.
- *
- * start and stop are always radians because angleMode() was goofy.
- * ellipseMode() sets the placement.
- *
- * also tries to be smart about start < stop.
- */
- public void arc(float a, float b, float c, float d,
- float start, float stop) {
- float x = a;
- float y = b;
- float w = c;
- float h = d;
-
- if (ellipseMode == CORNERS) {
- w = c - a;
- h = d - b;
-
- } else if (ellipseMode == RADIUS) {
- x = a - c;
- y = b - d;
- w = c * 2;
- h = d * 2;
-
- } else if (ellipseMode == CENTER) {
- x = a - c/2f;
- y = b - d/2f;
- }
-
- //if (angleMode == DEGREES) {
- //start = start * DEG_TO_RAD;
- //stop = stop * DEG_TO_RAD;
- //}
- // before running a while loop like this,
- // make sure it will exit at some point.
- if (Float.isInfinite(start) || Float.isInfinite(stop)) return;
- while (stop < start) stop += TWO_PI;
-
- arcImpl(x, y, w, h, start, stop);
- }
-
-
- /**
- * Start and stop are in radians, converted by the parent function.
- * Note that the radians can be greater (or less) than TWO_PI.
- * This is so that an arc can be drawn that crosses zero mark,
- * and the user will still collect $200.
- */
- protected void arcImpl(float x1, float y1, float w, float h,
- float start, float stop) {
- float hr = w / 2f;
- float vr = h / 2f;
-
- float centerX = x1 + hr;
- float centerY = y1 + vr;
-
- if (fill) {
- // shut off stroke for a minute
- boolean savedStroke = stroke;
- stroke = false;
-
- int startLUT = (int) (0.5f + (start / TWO_PI) * SINCOS_LENGTH);
- int stopLUT = (int) (0.5f + (stop / TWO_PI) * SINCOS_LENGTH);
-
- beginShape(TRIANGLE_FAN);
- vertex(centerX, centerY);
- int increment = 1; // what's a good algorithm? stopLUT - startLUT;
- for (int i = startLUT; i < stopLUT; i += increment) {
- int ii = i % SINCOS_LENGTH;
- vertex(centerX + cosLUT[ii] * hr,
- centerY + sinLUT[ii] * vr);
- }
- // draw last point explicitly for accuracy
- vertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr,
- centerY + sinLUT[stopLUT % SINCOS_LENGTH] * vr);
- endShape();
-
- stroke = savedStroke;
- }
-
- if (stroke) {
- // Almost identical to above, but this uses a LINE_STRIP
- // and doesn't include the first (center) vertex.
-
- boolean savedFill = fill;
- fill = false;
-
- int startLUT = (int) (0.5f + (start / TWO_PI) * SINCOS_LENGTH);
- int stopLUT = (int) (0.5f + (stop / TWO_PI) * SINCOS_LENGTH);
-
- beginShape(); //LINE_STRIP);
- int increment = 1; // what's a good algorithm? stopLUT - startLUT;
- for (int i = startLUT; i < stopLUT; i += increment) {
- int ii = i % SINCOS_LENGTH;
- vertex(centerX + cosLUT[ii] * hr,
- centerY + sinLUT[ii] * vr);
- }
- // draw last point explicitly for accuracy
- vertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr,
- centerY + sinLUT[stopLUT % SINCOS_LENGTH] * vr);
- endShape();
-
- fill = savedFill;
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // BOX & SPHERE
-
-
- public void box(float size) {
- depthError("box");
- }
-
- public void box(float w, float h, float d) {
- depthError("box");
- }
-
- public void sphereDetail(int res) {
- depthError("sphereDetail");
- }
-
- public void sphere(float r) {
- depthError("sphere");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // BEZIER
-
-
- /**
- * Evalutes quadratic bezier at point t for points a, b, c, d.
- * t varies between 0 and 1, and a and d are the on curve points,
- * b and c are the control points. this can be done once with the
- * x coordinates and a second time with the y coordinates to get
- * the location of a bezier curve at t.
- *
- * For instance, to convert the following example:
- * stroke(255, 102, 0);
- * line(85, 20, 10, 10);
- * line(90, 90, 15, 80);
- * stroke(0, 0, 0);
- * bezier(85, 20, 10, 10, 90, 90, 15, 80);
- *
- * // draw it in gray, using 10 steps instead of the default 20
- * // this is a slower way to do it, but useful if you need
- * // to do things with the coordinates at each step
- * stroke(128);
- * beginShape(LINE_STRIP);
- * for (int i = 0; i <= 10; i++) {
- * float t = i / 10.0f;
- * float x = bezierPoint(85, 10, 90, 15, t);
- * float y = bezierPoint(20, 10, 90, 80, t);
- * vertex(x, y);
- * }
- * endShape();
- */
- public float bezierPoint(float a, float b, float c, float d, float t) {
- float t1 = 1.0f - t;
- return a*t1*t1*t1 + 3*b*t*t1*t1 + 3*c*t*t*t1 + d*t*t*t;
- }
-
-
- /**
- * Provide the tangent at the given point on the bezier curve.
- * Based on code from v3ga's wordstree sketch.
- */
- public float bezierTangent(float a, float b, float c, float d, float t) {
- float t1 = 1.0f - t;
-
- return (a * 3 * t*t +
- b * 3 * t * (2 - 3*t) +
- c * 3 * (3*t*t - 4*t + 1) +
- d * -3 * t1*t1);
- }
-
-
- protected void bezierInit() {
- bezierDetail(bezierDetail);
- }
-
-
- public void bezierDetail(int detail) {
- if (bezierForwardMatrix == null) {
- bezierForwardMatrix = new float[4][4];
- bezierDrawMatrix = new float[4][4];
- }
- bezierDetail = detail;
- bezierInited = true;
-
- // setup matrix for forward differencing to speed up drawing
- setup_spline_forward(detail, bezierForwardMatrix);
-
- // multiply the basis and forward diff matrices together
- // saves much time since this needn't be done for each curve
- mult_spline_matrix(bezierForwardMatrix, bezier_basis, bezierDrawMatrix, 4);
- }
-
-
- /**
- * Draw a cubic bezier curve. The first and last points are
- * the on-curve points. The middle two are the 'control' points,
- * or 'handles' in an application like Illustrator.
- *
- * If you were to try and continue that curve like so:
- *
curveto(x5, y5, x6, y6, x7, y7);
- * This would be done in processing by adding these statements:
- *
bezierVertex(x5, y5, x6, y6, x7, y7)
- *
- * To draw a quadratic (instead of cubic) curve,
- * use the control point twice by doubling it:
- *
bezier(x1, y1, cx, cy, cx, cy, x2, y2);
- */
- public void bezier(float x1, float y1,
- float x2, float y2,
- float x3, float y3,
- float x4, float y4) {
- beginShape(); //LINE_STRIP);
- vertex(x1, y1);
- bezierVertex(x2, y2, x3, y3, x4, y4);
- endShape();
- }
-
-
- public void bezier(float x1, float y1, float z1,
- float x2, float y2, float z2,
- float x3, float y3, float z3,
- float x4, float y4, float z4) {
- beginShape(); //LINE_STRIP);
- vertex(x1, y1, z1);
- bezierVertex(x2, y2, z2,
- x3, y3, z3,
- x4, y4, z4);
- endShape();
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // CATMULL-ROM CURVE
-
-
- /**
- * Get a location along a catmull-rom curve segment.
- *
- * @param t Value between zero and one for how far along the segment
- */
- public float curvePoint(float a, float b, float c, float d, float t) {
- if (!curve_inited) curve_init();
-
- float tt = t * t;
- float ttt = t * tt;
- float m[][] = curve_basis;
-
- // not optimized (and probably need not be)
- return (a * (ttt*m[0][0] + tt*m[1][0] + t*m[2][0] + m[3][0]) +
- b * (ttt*m[0][1] + tt*m[1][1] + t*m[2][1] + m[3][1]) +
- c * (ttt*m[0][2] + tt*m[1][2] + t*m[2][2] + m[3][2]) +
- d * (ttt*m[0][3] + tt*m[1][3] + t*m[2][3] + m[3][3]));
- }
-
-
- public float curveTangent(float a, float b, float c, float d,
- float t) {
- System.err.println("curveTangent not yet implemented");
- return 0;
- }
-
-
- public void curveDetail(int detail) {
- curve_mode(detail, curveTightness);
- }
-
-
- public void curveTightness(float tightness) {
- curve_mode(curveDetail, tightness);
- }
-
-
- protected void curve_init() {
- curve_mode(curveDetail, curveTightness);
- }
-
-
- /**
- * Set the number of segments to use when drawing a Catmull-Rom
- * curve, and setting the s parameter, which defines how tightly
- * the curve fits to each vertex. Catmull-Rom curves are actually
- * a subset of this curve type where the s is set to zero.
- *
- * (This function is not optimized, since it's not expected to
- * be called all that often. there are many juicy and obvious
- * opimizations in here, but it's probably better to keep the
- * code more readable)
- */
- protected void curve_mode(int segments, float s) {
- curveDetail = segments;
-
- if (curve_basis == null) {
- // allocate these when used, to save startup time
- curve_basis = new float[4][4];
- curve_forward = new float[4][4];
- curve_draw = new float[4][4];
- curve_inited = true;
- }
-
- float c[][] = curve_basis;
-
- c[0][0] = s-1; c[0][1] = s+3; c[0][2] = -3-s; c[0][3] = 1-s;
- c[1][0] = 2*(1-s); c[1][1] = -5-s; c[1][2] = 2*(s+2); c[1][3] = s-1;
- c[2][0] = s-1; c[2][1] = 0; c[2][2] = 1-s; c[2][3] = 0;
- c[3][0] = 0; c[3][1] = 2; c[3][2] = 0; c[3][3] = 0;
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- c[i][j] /= 2f;
- }
- }
- setup_spline_forward(segments, curve_forward);
-
- if (bezierBasisInverse == null) {
- bezierBasisInverse = new PMatrix(bezierBasis).invert();
- }
-
- // hack here to get PGraphics2 working
- curveToBezierMatrix = new PMatrix(c[0][0], c[0][1], c[0][2], c[0][3],
- c[1][0], c[1][1], c[1][2], c[1][3],
- c[2][0], c[2][1], c[2][2], c[2][3],
- c[3][0], c[3][1], c[3][2], c[3][3]);
- curveToBezierMatrix.preApply(bezierBasisInverse);
-
- // multiply the basis and forward diff matrices together
- // saves much time since this needn't be done for each curve
- mult_spline_matrix(curve_forward, curve_basis, curve_draw, 4);
- }
-
-
- /**
- * Draws a segment of Catmull-Rom curve.
- *
- * As of 0070, this function no longer doubles the first and
- * last points. The curves are a bit more boring, but it's more
- * mathematically correct, and properly mirrored in curvePoint().
- *
- * The default implementation draws an image as a textured quad.
- * The (u, v) coordinates are in image space (they're ints, after all..)
- */
- protected void imageImpl(PImage image,
- float x1, float y1, float x2, float y2,
- int u1, int v1, int u2, int v2) {
- boolean savedStroke = stroke;
- boolean savedFill = fill;
- int savedTextureMode = textureMode;
-
- stroke = false;
- fill = true;
- textureMode = IMAGE;
-
- float savedFillR = fillR;
- float savedFillG = fillG;
- float savedFillB = fillB;
- float savedFillA = fillA;
-
- if (tint) {
- fillR = tintR;
- fillG = tintG;
- fillB = tintB;
- fillA = tintA;
-
- } else {
- fillR = 1;
- fillG = 1;
- fillB = 1;
- fillA = 1;
- }
-
- //System.out.println(fill + " " + fillR + " " + fillG + " " + fillB);
-
- beginShape(QUADS);
- texture(image);
- vertex(x1, y1, u1, v1);
- vertex(x1, y2, u1, v2);
- vertex(x2, y2, u2, v2);
- vertex(x2, y1, u2, v1);
- endShape();
-
- stroke = savedStroke;
- fill = savedFill;
- textureMode = savedTextureMode;
-
- fillR = savedFillR;
- fillG = savedFillG;
- fillB = savedFillB;
- fillA = savedFillA;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // TEXT/FONTS
-
-
- /**
- * Sets the alignment of the text to one of LEFT, CENTER, or RIGHT.
- * This will also reset the vertical text alignment to BASELINE.
- */
- public void textAlign(int align) {
- textAlign(align, BASELINE);
- }
-
-
- /**
- * Sets the horizontal and vertical alignment of the text. The horizontal
- * alignment can be one of LEFT, CENTER, or RIGHT. The vertical alignment
- * can be TOP, BOTTOM, CENTER, or the BASELINE (the default).
- */
- public void textAlign(int alignX, int alignY) {
- textAlign = alignX;
- textAlignY = alignY;
- }
-
-
- /**
- * Returns the ascent of the current font at the current size.
- * This is a method, rather than a variable inside the PGraphics object
- * because it requires calculation.
- */
- public float textAscent() {
- if (textFont == null) {
- throw new RuntimeException("use textFont() before textAscent()");
- }
-
- return textFont.ascent() *
- ((textMode == SCREEN) ? textFont.size : textSize);
- }
-
-
- /**
- * Returns the descent of the current font at the current size.
- * This is a method, rather than a variable inside the PGraphics object
- * because it requires calculation.
- */
- public float textDescent() {
- if (textFont != null) {
- return textFont.descent() *
- ((textMode == SCREEN) ? textFont.size : textSize);
-
- } else {
- throw new RuntimeException("use textFont() before textDescent()");
- }
- }
-
-
- /**
- * Sets the current font. The font's size will be the "natural"
- * size of this font (the size that was set when using "Create Font").
- * The leading will also be reset.
- */
- public void textFont(PFont which) {
- if (which != null) {
- textFont = which;
- if (hints[ENABLE_NATIVE_FONTS]) {
- if (which.font == null) {
- which.findFont();
- }
- }
- textFontNative = which.font;
-
- //textFontNativeMetrics = null;
- // changed for rev 0104 for textMode(SHAPE) in opengl
- if (textFontNative != null) {
- // TODO need a better way to handle this. could use reflection to get
- // rid of the warning, but that'd be a little silly. supporting this is
- // an artifact of supporting java 1.1, otherwise we'd use getLineMetrics,
- // as recommended by the @deprecated flag.
- textFontNativeMetrics =
- Toolkit.getDefaultToolkit().getFontMetrics(textFontNative);
- }
- textSize(which.size);
-
- } else {
- throw new RuntimeException("a null PFont was passed to textFont()");
- }
- }
-
-
- /**
- * Useful function to set the font and size at the same time.
- */
- public void textFont(PFont which, float size) {
- textFont(which);
- textSize(size);
- }
-
-
- /**
- * Set the text leading to a specific value. If using a custom
- * value for the text leading, you'll have to call textLeading()
- * again after any calls to textSize().
- */
- public void textLeading(float leading) {
- textLeading = leading;
- }
-
-
- /**
- * Sets the text rendering/placement to be either SCREEN (direct
- * to the screen, exact coordinates, only use the font's original size)
- * or MODEL (the default, where text is manipulated by translate() and
- * can have a textSize). The text size cannot be set when using
- * textMode(SCREEN), because it uses the pixels directly from the font.
- */
- public void textMode(int mode) {
- // CENTER and MODEL overlap (they're both 3)
- if ((mode == LEFT) || (mode == RIGHT)) {
- throw new RuntimeException("textMode() is now textAlign() " +
- "in Processing beta");
- }
- if ((mode != SCREEN) && (mode != MODEL)) {
- throw new RuntimeException("Only textMode(SCREEN) and textMode(MODEL) " +
- "are available with this renderer.");
- }
-
- //if (textFont != null) {
- textMode = mode;
-
- // reset the font to its natural size
- // (helps with width calculations and all that)
- //if (textMode == SCREEN) {
- //textSize(textFont.size);
- //}
-
- //} else {
- //throw new RuntimeException("use textFont() before textMode()");
- //}
- }
-
-
- /**
- * Sets the text size, also resets the value for the leading.
- */
- public void textSize(float size) {
- if (textFont != null) {
- if ((textMode == SCREEN) && (size != textFont.size)) {
- throw new RuntimeException("textSize() cannot be used with " +
- "textMode(SCREEN)");
- }
- textSize = size;
- //textLeading = textSize *
- // ((textFont.ascent() + textFont.descent()) * 1.275f);
- textLeading = (textAscent() + textDescent()) * 1.275f;
-
- } else {
- throw new RuntimeException("Use textFont() before textSize()");
- }
- }
-
-
- // ........................................................
-
-
- public float textWidth(char c) {
- textBuffer[0] = c;
- return textWidthImpl(textBuffer, 0, 1);
- }
-
-
- /**
- * Return the width of a line of text. If the text has multiple
- * lines, this returns the length of the longest line.
- */
- public float textWidth(String str) {
- if (textFont == null) {
- throw new RuntimeException("use textFont() before textWidth()");
- }
-
- int length = str.length();
- if (length > textWidthBuffer.length) {
- textWidthBuffer = new char[length + 10];
- }
- str.getChars(0, length, textWidthBuffer, 0);
-
- float wide = 0;
- int index = 0;
- int start = 0;
-
- while (index < length) {
- if (textWidthBuffer[index] == '\n') {
- wide = Math.max(wide, textWidthImpl(textWidthBuffer, start, index));
- start = index+1;
- }
- index++;
- }
- if (start < length) {
- wide = Math.max(wide, textWidthImpl(textWidthBuffer, start, index));
- }
- return wide;
- }
-
-
- /**
- * Implementation of returning the text width of
- * the chars [start, stop) in the buffer.
- * Unlike the previous version that was inside PFont, this will
- * return the size not of a 1 pixel font, but the actual current size.
- */
- protected float textWidthImpl(char buffer[], int start, int stop) {
- float wide = 0;
- for (int i = start; i < stop; i++) {
- // could add kerning here, but it just ain't implemented
- wide += textFont.width(buffer[i]) * textSize;
- }
- return wide;
- }
-
-
- // ........................................................
-
-
- /**
- * Write text where we just left off.
- */
- public void text(char c) {
- text(c, textX, textY, textZ);
- }
-
-
- /**
- * Draw a single character on screen.
- * Extremely slow when used with textMode(SCREEN) and Java 2D,
- * because loadPixels has to be called first and updatePixels last.
- */
- public void text(char c, float x, float y) {
- if (textFont == null) {
- throw new RuntimeException("use textFont() before text()");
- }
-
- if (textMode == SCREEN) loadPixels();
-
- textBuffer[0] = c;
- textLineImpl(textBuffer, 0, 1, x, y);
-
- if (textMode == SCREEN) updatePixels();
- }
-
-
- /**
- * Draw a single character on screen (with a z coordinate)
- */
- public void text(char c, float x, float y, float z) {
- if ((z != 0) && (textMode == SCREEN)) {
- String msg = "textMode(SCREEN) cannot have a z coordinate";
- throw new RuntimeException(msg);
- }
-
- if (z != 0) translate(0, 0, z); // slowness, badness
-
- text(c, x, y);
- textZ = z;
-
- if (z != 0) translate(0, 0, -z);
- }
-
-
- /**
- * Write text where we just left off.
- */
- public void text(String str) {
- text(str, textX, textY, textZ);
- }
-
-
- /**
- * Draw a chunk of text.
- * Newlines that are \n (Unix newline or linefeed char, ascii 10)
- * are honored, but \r (carriage return, Windows and Mac OS) are
- * ignored.
- */
- public void text(String str, float x, float y) {
- if (textFont == null) {
- throw new RuntimeException("use textFont() before text()");
- }
-
- if (textMode == SCREEN) loadPixels();
-
- int length = str.length();
- if (length > textBuffer.length) {
- textBuffer = new char[length + 10];
- }
- str.getChars(0, length, textBuffer, 0);
-
- // If multiple lines, sum the height of the additional lines
- float high = 0; //-textAscent();
- for (int i = 0; i < length; i++) {
- if (textBuffer[i] == '\n') {
- high += textLeading;
- }
- }
- if (textAlignY == CENTER) {
- // for a single line, this adds half the textAscent to y
- // for multiple lines, subtract half the additional height
- //y += (textAscent() - textDescent() - high)/2;
- y += (textAscent() - high)/2;
- } else if (textAlignY == TOP) {
- // for a single line, need to add textAscent to y
- // for multiple lines, no different
- y += textAscent();
- } else if (textAlignY == BOTTOM) {
- // for a single line, this is just baseline (unchanged)
- // for multiple lines, subtract leading for each line
- y -= high;
- //} else if (textAlignY == BASELINE) {
- // do nothing
- }
-
- int start = 0;
- int index = 0;
- while (index < length) {
- if (textBuffer[index] == '\n') {
- textLineImpl(textBuffer, start, index, x, y);
- start = index + 1;
- y += textLeading;
- }
- index++;
- }
- if (start < length) {
- textLineImpl(textBuffer, start, index, x, y);
- }
- if (textMode == SCREEN) updatePixels();
- }
-
-
- /**
- * Same as above but with a z coordinate.
- */
- public void text(String str, float x, float y, float z) {
- if ((z != 0) && (textMode == SCREEN)) {
- String msg = "textMode(SCREEN) cannot have a z coordinate";
- throw new RuntimeException(msg);
- }
-
- if (z != 0) translate(0, 0, z); // slow!
-
- text(str, x, y);
- textZ = z;
-
- if (z != 0) translate(0, 0, -z);
- }
-
-
- /**
- * Handles placement of a text line, then calls textLinePlaced
- * to actually render at the specific point.
- */
- protected void textLineImpl(char buffer[], int start, int stop,
- float x, float y) {
- if (textAlign == CENTER) {
- x -= textWidthImpl(buffer, start, stop) / 2f;
-
- } else if (textAlign == RIGHT) {
- x -= textWidthImpl(buffer, start, stop);
- }
-
- textLinePlacedImpl(buffer, start, stop, x, y);
- }
-
-
- protected void textLinePlacedImpl(char buffer[], int start, int stop,
- float x, float y) {
- for (int index = start; index < stop; index++) {
- textCharImpl(buffer[index], x, y); //, 0); //z);
-
- // this doesn't account for kerning
- x += textWidth(buffer[index]);
- }
- textX = x;
- textY = y;
- textZ = 0; // this will get set by the caller if non-zero
- }
-
-
- /**
- * Draw text in a box that is constrained to a particular size.
- * The current rectMode() determines what the coordinates mean
- * (whether x1/y1/x2/y2 or x/y/w/h).
- *
- * Note that the x,y coords of the start of the box
- * will align with the *ascent* of the text, not the baseline,
- * as is the case for the other text() functions.
- *
- * Newlines that are \n (Unix newline or linefeed char, ascii 10)
- * are honored, and \r (carriage return, Windows and Mac OS) are
- * ignored.
- */
- public void text(String str, float x1, float y1, float x2, float y2) {
- if (textFont == null) {
- throw new RuntimeException("use textFont() before text()");
- }
-
- if (textMode == SCREEN) loadPixels();
-
- float hradius, vradius;
- switch (rectMode) {
- case CORNER:
- x2 += x1; y2 += y1;
- break;
- case RADIUS:
- hradius = x2;
- vradius = y2;
- x2 = x1 + hradius;
- y2 = y1 + vradius;
- x1 -= hradius;
- y1 -= vradius;
- break;
- case CENTER:
- hradius = x2 / 2.0f;
- vradius = y2 / 2.0f;
- x2 = x1 + hradius;
- y2 = y1 + vradius;
- x1 -= hradius;
- y1 -= vradius;
- }
- if (x2 < x1) {
- float temp = x1; x1 = x2; x2 = temp;
- }
- if (y2 < y1) {
- float temp = y1; y1 = y2; y2 = temp;
- }
-
- float spaceWidth = textWidth(' ');
- float runningX = x1; //boxX1;
- float currentY = y1; //boxY1;
- float boxWidth = x2 - x1; //boxX2 - boxX1;
-
- // lineX is the position where the text starts, which is adjusted
- // to left/center/right based on the current textAlign
- float lineX = x1; //boxX1;
- if (textAlign == CENTER) {
- lineX = lineX + boxWidth/2f;
- } else if (textAlign == RIGHT) {
- lineX = x2; //boxX2;
- }
-
- // ala illustrator, the text itself must fit inside the box
- currentY += textAscent(); //ascent() * textSize;
- // if the box is already too small, tell em to f off
- if (currentY > y2) return; //boxY2) return;
-
- int length = str.length();
- if (length > textBuffer.length) {
- textBuffer = new char[length + 10];
- }
- str.getChars(0, length, textBuffer, 0);
-
- int wordStart = 0;
- int wordStop = 0;
- int lineStart = 0;
- int index = 0;
- while (index < length) {
- if ((textBuffer[index] == ' ') || (index == length-1)) {
- // boundary of a word
- float wordWidth = textWidthImpl(textBuffer, wordStart, index);
-
- if (runningX + wordWidth > x2) { //boxX2) {
- if (runningX == x1) { //boxX1) {
- // if this is the first word, and its width is
- // greater than the width of the text box,
- // then break the word where at the max width,
- // and send the rest of the word to the next line.
- do {
- index--;
- if (index == wordStart) {
- // not a single char will fit on this line. screw 'em.
- //System.out.println("screw you");
- return;
- }
- wordWidth = textWidthImpl(textBuffer, wordStart, index);
- } while (wordWidth > boxWidth);
- textLineImpl(textBuffer, lineStart, index, lineX, currentY);
-
- } else {
- // next word is too big, output current line
- // and advance to the next line
- textLineImpl(textBuffer, lineStart, wordStop, lineX, currentY);
- // only increment index if a word wasn't broken inside the
- // do/while loop above.. also, this is a while() loop too,
- // because multiple spaces don't count for shit when they're
- // at the end of a line like this.
-
- index = wordStop; // back that ass up
- while ((index < length) &&
- (textBuffer[index] == ' ')) {
- index++;
- }
- }
- lineStart = index;
- wordStart = index;
- wordStop = index;
- runningX = x1; //boxX1;
- currentY += textLeading;
- //if (currentY > boxY2) return; // box is now full
- if (currentY > y2) return; // box is now full
-
- } else {
- runningX += wordWidth + spaceWidth;
- // on to the next word
- wordStop = index;
- wordStart = index + 1;
- }
-
- } else if (textBuffer[index] == '\n') {
- if (lineStart != index) { // if line is not empty
- textLineImpl(textBuffer, lineStart, index, lineX, currentY);
- }
- lineStart = index + 1;
- wordStart = lineStart;
- runningX = x1; // fix for bug 188
- currentY += textLeading;
- //if (currentY > boxY2) return; // box is now full
- if (currentY > y2) return; // box is now full
- }
- index++;
- }
- if ((lineStart < length) && (lineStart != index)) {
- textLineImpl(textBuffer, lineStart, index, lineX, currentY);
- }
-
- if (textMode == SCREEN) updatePixels();
- }
-
-
- public void text(String s, float x1, float y1, float x2, float y2, float z) {
- if ((z != 0) && (textMode == SCREEN)) {
- String msg = "textMode(SCREEN) cannot have a z coordinate";
- throw new RuntimeException(msg);
- }
-
- if (z != 0) translate(0, 0, z); // slowness, badness
-
- text(s, x1, y1, x2, y2);
- textZ = z;
-
- if (z != 0) translate(0, 0, -z); // TEMPORARY HACK! SLOW!
- }
-
-
- public void text(int num, float x, float y) {
- text(String.valueOf(num), x, y);
- }
-
-
- public void text(int num, float x, float y, float z) {
- text(String.valueOf(num), x, y, z);
- }
-
-
- /**
- * This does a basic number formatting, to avoid the
- * generally ugly appearance of printing floats.
- * Users who want more control should use their own nf() cmmand,
- * or if they want the long, ugly version of float,
- * use String.valueOf() to convert the float to a String first.
- */
- public void text(float num, float x, float y) {
- text(PApplet.nfs(num, 0, 3), x, y);
- }
-
-
- public void text(float num, float x, float y, float z) {
- text(PApplet.nfs(num, 0, 3), x, y, z);
- }
-
-
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
-
- // what was this for?
- //font.getStringBounds(text, g2.getFontRenderContext()).getWidth();
-
-
- protected void textCharImpl(char ch, float x, float y) { //, float z) {
- int index = textFont.index(ch);
- if (index == -1) return;
-
- PImage glyph = textFont.images[index];
-
- if (textMode == MODEL) {
- float high = (float) textFont.height[index] / textFont.fheight;
- float bwidth = (float) textFont.width[index] / textFont.fwidth;
- float lextent = (float) textFont.leftExtent[index] / textFont.fwidth;
- float textent = (float) textFont.topExtent[index] / textFont.fheight;
-
- float x1 = x + lextent * textSize;
- float y1 = y - textent * textSize;
- float x2 = x1 + bwidth * textSize;
- float y2 = y1 + high * textSize;
-
- textCharModelImpl(glyph,
- x1, y1, x2, y2,
- //x1, y1, z, x2, y2, z,
- textFont.width[index], textFont.height[index]);
-
- } else if (textMode == SCREEN) {
- int xx = (int) x + textFont.leftExtent[index];;
- int yy = (int) y - textFont.topExtent[index];
-
- int w0 = textFont.width[index];
- int h0 = textFont.height[index];
-
- textCharScreenImpl(glyph, xx, yy, w0, h0);
- }
- }
-
-
- protected void textCharModelImpl(PImage glyph,
- float x1, float y1, //float z1,
- float x2, float y2, //float z2,
- int u2, int v2) {
- boolean savedTint = tint;
- int savedTintColor = tintColor;
- float savedTintR = tintR;
- float savedTintG = tintG;
- float savedTintB = tintB;
- float savedTintA = tintA;
- boolean savedTintAlpha = tintAlpha;
-
- tint = true;
- tintColor = fillColor;
- tintR = fillR;
- tintG = fillG;
- tintB = fillB;
- tintA = fillA;
- tintAlpha = fillAlpha;
-
- imageImpl(glyph, x1, y1, x2, y2, 0, 0, u2, v2);
-
- tint = savedTint;
- tintColor = savedTintColor;
- tintR = savedTintR;
- tintG = savedTintG;
- tintB = savedTintB;
- tintA = savedTintA;
- tintAlpha = savedTintAlpha;
- }
-
-
- // should take image, int x1, int y1, and x2, y2
-
- protected void textCharScreenImpl(PImage glyph,
- int xx, int yy, //int x2, int y2,
- int w0, int h0) {
- /*
- System.out.println("textimplscreen");
- rectMode(CORNER);
- stroke(255);
- rect(xx, yy, w0, h0);
- */
-
- int x0 = 0;
- int y0 = 0;
-
- if ((xx >= width) || (yy >= height) ||
- (xx + w0 < 0) || (yy + h0 < 0)) return;
-
- if (xx < 0) {
- x0 -= xx;
- w0 += xx;
- xx = 0;
- }
- if (yy < 0) {
- y0 -= yy;
- h0 += yy;
- yy = 0;
- }
- if (xx + w0 > width) {
- w0 -= ((xx + w0) - width);
- }
- if (yy + h0 > height) {
- h0 -= ((yy + h0) - height);
- }
-
- int fr = fillRi;
- int fg = fillGi;
- int fb = fillBi;
- int fa = fillAi;
-
- int pixels1[] = glyph.pixels; //images[glyph].pixels;
-
- // TODO this can be optimized a bit
- for (int row = y0; row < y0 + h0; row++) {
- for (int col = x0; col < x0 + w0; col++) {
- int a1 = (fa * pixels1[row * textFont.twidth + col]) >> 8;
- int a2 = a1 ^ 0xff;
- //int p1 = pixels1[row * glyph.width + col];
- int p2 = pixels[(yy + row-y0)*width + (xx+col-x0)];
-
- pixels[(yy + row-y0)*width + xx+col-x0] =
- (0xff000000 |
- (((a1 * fr + a2 * ((p2 >> 16) & 0xff)) & 0xff00) << 8) |
- (( a1 * fg + a2 * ((p2 >> 8) & 0xff)) & 0xff00) |
- (( a1 * fb + a2 * ( p2 & 0xff)) >> 8));
- }
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // MATRIX TRANSFORMATIONS
-
-
- public void translate(float tx, float ty) {
- m02 += tx*m00 + ty*m01 + m02;
- m12 += tx*m10 + ty*m11 + m12;
- }
-
-
- public void translate(float tx, float ty, float tz) {
- depthErrorXYZ("translate");
- }
-
-
- /**
- * Two dimensional rotation.
- *
- * Same as rotateZ (this is identical to a 3D rotation along the z-axis)
- * but included for clarity. It'd be weird for people drawing 2D graphics
- * to be using rotateZ. And they might kick our a-- for the confusion.
- */
- public void rotate(float angle) {
- float c = (float) Math.cos(angle);
- float s = (float) Math.sin(angle);
-
- applyMatrix(c, -s, 0, s, c, 0);
- }
-
-
- public void rotateX(float angle) {
- depthError("rotateX");
- }
-
- public void rotateY(float angle) {
- depthError("rotateY");
- }
-
-
- /**
- * Rotate around the z axis. The functions rotate() and rotateZ() are
- * the same, it's just that it make sense to have rotate() and then rotateX()
- * and rotateY() when running in 3D; nor does it make sense to use
- * a function called rotateZ() if you're only doing things in 2D.
- * so we just decided to have them both be the same.
- */
- public void rotateZ(float angle) {
- depthError("rotateZ");
- }
-
-
- /**
- * Rotate about a vector in space. Same as the glRotatef() function.
- */
- public void rotate(float angle, float vx, float vy, float vz) {
- throw new RuntimeException("rotate(angle, x, y, z) " +
- "can only be used with P3D or OPENGL");
- }
-
-
- public void scale(float s) {
- applyMatrix(s, 0, 0,
- 0, s, 0);
- }
-
-
- public void scale(float sx, float sy) {
- applyMatrix(sx, 0, 0,
- 0, sy, 0);
- }
-
-
- public void scale(float x, float y, float z) {
- depthErrorXYZ("scale");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // TRANSFORMATION MATRIX
-
-
- public void pushMatrix() {
- if (matrixStackDepth+1 == MATRIX_STACK_DEPTH) {
- throw new RuntimeException("too many calls to pushMatrix()");
- }
- float mat[] = matrixStack[matrixStackDepth];
- mat[0] = m00; mat[1] = m01; mat[2] = m02;
- mat[3] = m10; mat[4] = m11; mat[5] = m12;
- matrixStackDepth++;
- }
-
-
- public void popMatrix() {
- if (matrixStackDepth == 0) {
- throw new RuntimeException("too many calls to popMatrix() " +
- "(and not enough to pushMatrix)");
- }
- matrixStackDepth--;
- float mat[] = matrixStack[matrixStackDepth];
- m00 = mat[0]; m01 = mat[1]; m02 = mat[2];
- m10 = mat[3]; m11 = mat[4]; m12 = mat[5];
- }
-
-
- /**
- * Load identity as the transform/model matrix.
- * Same as glLoadIdentity().
- */
- public void resetMatrix() {
- m00 = 1; m01 = 0; m02 = 0;
- m10 = 0; m11 = 1; m12 = 0;
- }
-
-
- /**
- * Apply a 3x2 affine transformation matrix.
- */
- public void applyMatrix(float n00, float n01, float n02,
- float n10, float n11, float n12) {
-
- float r00 = m00*n00 + m01*n10;
- float r01 = m00*n01 + m01*n11;
- float r02 = m00*n02 + m01*n12 + m02;
-
- float r10 = m10*n00 + m11*n10;
- float r11 = m10*n01 + m11*n11;
- float r12 = m10*n02 + m11*n12 + m12;
-
- m00 = r00; m01 = r01; m02 = r02;
- m10 = r10; m11 = r11; m12 = r12;
- }
-
-
- public void applyMatrix(float n00, float n01, float n02, float n03,
- float n10, float n11, float n12, float n13,
- float n20, float n21, float n22, float n23,
- float n30, float n31, float n32, float n33) {
- throw new RuntimeException("applyMatrix() with a 4x4 matrix " +
- "can only be used with OPENGL or P3D");
- }
-
-
- /**
- * Loads the current matrix into m00, m01 etc (or modelview and
- * projection when using 3D) so that the values can be read.
- *
- * Note that there is no "updateMatrix" because that gets too
- * complicated (unnecessary) when considering the 3D matrices.
- */
- public void loadMatrix() {
- // no-op on base PGraphics because they're used directly
- }
-
-
- /**
- * Print the current model (or "transformation") matrix.
- */
- public void printMatrix() {
- loadMatrix(); // just to make sure
-
- float big = Math.abs(m00);
- if (Math.abs(m01) > big) big = Math.abs(m01);
- if (Math.abs(m02) > big) big = Math.abs(m02);
- if (Math.abs(m10) > big) big = Math.abs(m10);
- if (Math.abs(m11) > big) big = Math.abs(m11);
- if (Math.abs(m12) > big) big = Math.abs(m12);
-
- // avoid infinite loop
- if (Float.isNaN(big) || Float.isInfinite(big)) {
- big = 1000000; // set to something arbitrary
- }
-
- int d = 1;
- int bigi = (int) big;
- while ((bigi /= 10) != 0) d++; // cheap log()
-
- System.out.println(PApplet.nfs(m00, d, 4) + " " +
- PApplet.nfs(m01, d, 4) + " " +
- PApplet.nfs(m02, d, 4));
-
- System.out.println(PApplet.nfs(m10, d, 4) + " " +
- PApplet.nfs(m11, d, 4) + " " +
- PApplet.nfs(m12, d, 4));
-
- System.out.println();
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // CAMERA (none are supported in 2D)
-
-
- public void beginCamera() {
- depthError("beginCamera");
- }
-
- public void endCamera() {
- depthError("endCamera");
- }
-
- public void camera() {
- depthError("camera");
- }
-
- public void camera(float eyeX, float eyeY, float eyeZ,
- float centerX, float centerY, float centerZ,
- float upX, float upY, float upZ) {
- depthError("camera");
- }
-
- public void printCamera() {
- depthError("printCamera");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // PROJECTION (none are supported in 2D)
-
-
- public void ortho() {
- depthError("ortho");
- }
-
- public void ortho(float left, float right,
- float bottom, float top,
- float near, float far) {
- depthError("ortho");
- }
-
- public void perspective() {
- depthError("perspective");
- }
-
- public void perspective(float fovy, float aspect, float zNear, float zFar) {
- depthError("perspective");
- }
-
- public void frustum(float left, float right, float bottom,
- float top, float znear, float zfar) {
- depthError("frustum");
- }
-
- public void printProjection() {
- depthError("printCamera");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // SCREEN TRANSFORMS
-
-
- /**
- * Given an x and y coordinate, returns the x position of where
- * that point would be placed on screen, once affected by translate(),
- * scale(), or any other transformations.
- */
- public float screenX(float x, float y) {
- return m00*x + m01*y + m02;
- }
-
-
- /**
- * Given an x and y coordinate, returns the y position of where
- * that point would be placed on screen, once affected by translate(),
- * scale(), or any other transformations.
- */
- public float screenY(float x, float y) {
- return m10*x + m11*y + m12;
- }
-
-
- /**
- * Maps a three dimensional point to its placement on-screen.
- *
- * Given an (x, y, z) coordinate, returns the x position of where
- * that point would be placed on screen, once affected by translate(),
- * scale(), or any other transformations.
- */
- public float screenX(float x, float y, float z) {
- depthErrorXYZ("screenX");
- return 0;
- }
-
-
- /**
- * Maps a three dimensional point to its placement on-screen.
- *
- * Given an (x, y, z) coordinate, returns the y position of where
- * that point would be placed on screen, once affected by translate(),
- * scale(), or any other transformations.
- */
- public float screenY(float x, float y, float z) {
- depthErrorXYZ("screenY");
- return 0;
- }
-
-
- /**
- * Maps a three dimensional point to its placement on-screen.
- *
- * Given an (x, y, z) coordinate, returns its z value.
- * This value can be used to determine if an (x, y, z) coordinate
- * is in front or in back of another (x, y, z) coordinate.
- * The units are based on how the zbuffer is set up, and don't
- * relate to anything "real". They're only useful for in
- * comparison to another value obtained from screenZ(),
- * or directly out of the zbuffer[].
- */
- public float screenZ(float x, float y, float z) {
- depthErrorXYZ("screenZ");
- return 0;
- }
-
-
- /**
- * Returns the model space x value for an x, y, z coordinate.
- *
- * This will give you a coordinate after it has been transformed
- * by translate(), rotate(), and camera(), but not yet transformed
- * by the projection matrix. For instance, his can be useful for
- * figuring out how points in 3D space relate to the edge
- * coordinates of a shape.
- */
- public float modelX(float x, float y, float z) {
- depthError("modelX");
- return 0;
- }
-
-
- /**
- * Returns the model space y value for an x, y, z coordinate.
- */
- public float modelY(float x, float y, float z) {
- depthError("modelY");
- return 0;
- }
-
-
- /**
- * Returns the model space z value for an x, y, z coordinate.
- */
- public float modelZ(float x, float y, float z) {
- depthError("modelZ");
- return 0;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // COLOR
-
-
- public void colorMode(int mode) {
- colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA);
- }
-
-
- public void colorMode(int mode, float max) {
- colorMode(mode, max, max, max, max);
- }
-
-
- /**
- * Set the colorMode and the maximum values for (r, g, b)
- * or (h, s, b).
- *
- * Note that this doesn't set the maximum for the alpha value,
- * which might be confusing if for instance you switched to
- *
colorMode(HSB, 360, 100, 100);
- * because the alpha values were still between 0 and 255.
- */
- public void colorMode(int mode,
- float maxX, float maxY, float maxZ) {
- colorMode(mode, maxX, maxY, maxZ, colorModeA);
- }
-
-
- public void colorMode(int mode,
- float maxX, float maxY, float maxZ, float maxA) {
- colorMode = mode;
-
- colorModeX = maxX; // still needs to be set for hsb
- colorModeY = maxY;
- colorModeZ = maxZ;
- colorModeA = maxA;
-
- // if color max values are all 1, then no need to scale
- colorScale = ((maxA != 1) || (maxX != maxY) ||
- (maxY != maxZ) || (maxZ != maxA));
-
- // if color is rgb/0..255 this will make it easier for the
- // red() green() etc functions
- colorRgb255 = (colorMode == RGB) &&
- (colorModeA == 255) && (colorModeX == 255) &&
- (colorModeY == 255) && (colorModeZ == 255);
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- protected void colorCalc(float gray) {
- colorCalc(gray, colorModeA);
- }
-
-
- protected void colorCalc(float gray, float alpha) {
- if (gray > colorModeX) gray = colorModeX;
- if (alpha > colorModeA) alpha = colorModeA;
-
- if (gray < 0) gray = 0;
- if (alpha < 0) alpha = 0;
-
- calcR = colorScale ? (gray / colorModeX) : gray;
- calcG = calcR;
- calcB = calcR;
- calcA = colorScale ? (alpha / colorModeA) : alpha;
-
- calcRi = (int)(calcR*255); calcGi = (int)(calcG*255);
- calcBi = (int)(calcB*255); calcAi = (int)(calcA*255);
- calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi;
- calcAlpha = (calcAi != 255);
- }
-
-
- protected void colorCalc(float x, float y, float z) {
- colorCalc(x, y, z, colorModeA);
- }
-
-
- protected void colorCalc(float x, float y, float z, float a) {
- if (x > colorModeX) x = colorModeX;
- if (y > colorModeY) y = colorModeY;
- if (z > colorModeZ) z = colorModeZ;
- if (a > colorModeA) a = colorModeA;
-
- if (x < 0) x = 0;
- if (y < 0) y = 0;
- if (z < 0) z = 0;
- if (a < 0) a = 0;
-
- switch (colorMode) {
- case RGB:
- if (colorScale) {
- calcR = x / colorModeX;
- calcG = y / colorModeY;
- calcB = z / colorModeZ;
- calcA = a / colorModeA;
- } else {
- calcR = x; calcG = y; calcB = z; calcA = a;
- }
- break;
-
- case HSB:
- x /= colorModeX; // h
- y /= colorModeY; // s
- z /= colorModeZ; // b
-
- calcA = colorScale ? (a/colorModeA) : a;
-
- if (y == 0) { // saturation == 0
- calcR = calcG = calcB = z;
-
- } else {
- float which = (x - (int)x) * 6.0f;
- float f = which - (int)which;
- float p = z * (1.0f - y);
- float q = z * (1.0f - y * f);
- float t = z * (1.0f - (y * (1.0f - f)));
-
- switch ((int)which) {
- case 0: calcR = z; calcG = t; calcB = p; break;
- case 1: calcR = q; calcG = z; calcB = p; break;
- case 2: calcR = p; calcG = z; calcB = t; break;
- case 3: calcR = p; calcG = q; calcB = z; break;
- case 4: calcR = t; calcG = p; calcB = z; break;
- case 5: calcR = z; calcG = p; calcB = q; break;
- }
- }
- break;
- }
- calcRi = (int)(255*calcR); calcGi = (int)(255*calcG);
- calcBi = (int)(255*calcB); calcAi = (int)(255*calcA);
- calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi;
- calcAlpha = (calcAi != 255);
- }
-
-
- /**
- * Unpacks AARRGGBB color for direct use with colorCalc.
- *
- * Handled here with its own function since this is indepenent
- * of the color mode.
- *
- * Strangely the old version of this code ignored the alpha
- * value. not sure if that was a bug or what.
- *
- * The problem with this code is that it has to detect between
- * these two situations automatically. This is done by checking
- * to see if the high bits (the alpha for 0xAA000000) is set,
- * and if not, whether the color value that follows is less than
- * colorModeX (the first param passed to colorMode).
- *
- * This auto-detect would break in the following situation:
- *
size(256, 256);
- * for (int i = 0; i < 256; i++) {
- * color c = color(0, 0, 0, i);
- * stroke(c);
- * line(i, 0, i, 256);
- * }
- * ...on the first time through the loop, where (i == 0),
- * since the color itself is zero (black) then it would appear
- * indistinguishable from someone having written fill(0).
- */
- public void fill(int rgb) {
- if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above
- fill((float) rgb);
-
- } else {
- colorCalcARGB(rgb, colorModeA);
- fillFromCalc();
- }
- }
-
-
- public void fill(int rgb, float alpha) {
- if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above
- fill((float) rgb, alpha);
-
- } else {
- colorCalcARGB(rgb, alpha);
- fillFromCalc();
- }
- }
-
-
- public void fill(float gray) {
- colorCalc(gray);
- fillFromCalc();
- }
-
-
- public void fill(float gray, float alpha) {
- colorCalc(gray, alpha);
- fillFromCalc();
- }
-
-
- public void fill(float x, float y, float z) {
- colorCalc(x, y, z);
- fillFromCalc();
- }
-
-
- public void fill(float x, float y, float z, float a) {
- colorCalc(x, y, z, a);
- fillFromCalc();
- }
-
-
- protected void fillFromCalc() {
- fill = true;
- fillR = calcR;
- fillG = calcG;
- fillB = calcB;
- fillA = calcA;
- fillRi = calcRi;
- fillGi = calcGi;
- fillBi = calcBi;
- fillAi = calcAi;
- fillColor = calcColor;
- fillAlpha = calcAlpha;
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void ambient(int rgb) {
- depthError("ambient");
- }
-
- public void ambient(float gray) {
- depthError("ambient");
- }
-
- public void ambient(float x, float y, float z) {
- depthError("ambient");
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void specular(int rgb) {
- depthError("specular");
- }
-
- public void specular(float gray) {
- depthError("specular");
- }
-
- public void specular(float gray, float alpha) {
- depthError("specular");
- }
-
- public void specular(float x, float y, float z) {
- depthError("specular");
- }
-
- public void specular(float x, float y, float z, float a) {
- depthError("specular");
- }
-
- public void shininess(float shine) {
- depthError("shininess");
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void emissive(int rgb) {
- depthError("emissive");
- }
-
- public void emissive(float gray) {
- depthError("emissive");
- }
-
- public void emissive(float x, float y, float z ) {
- depthError("emissive");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // LIGHTS
-
-
- public void lights() {
- depthError("lights");
- }
-
- public void ambientLight(float red, float green, float blue) {
- depthError("ambientLight");
- }
-
- public void ambientLight(float red, float green, float blue,
- float x, float y, float z) {
- depthError("ambientLight");
- }
-
- public void directionalLight(float red, float green, float blue,
- float nx, float ny, float nz) {
- depthError("directionalLight");
- }
-
- public void pointLight(float red, float green, float blue,
- float x, float y, float z) {
- depthError("pointLight");
- }
-
- public void spotLight(float red, float green, float blue,
- float x, float y, float z,
- float nx, float ny, float nz,
- float angle, float concentration) {
- depthError("spotLight");
- }
-
- public void lightFalloff(float constant, float linear, float quadratic) {
- depthError("lightFalloff");
- }
-
- public void lightSpecular(float x, float y, float z) {
- depthError("lightSpecular");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
-
- /**
- * Set the background to a gray or ARGB color.
- *
- * Note that background() should be called before any
- * transformations occur, because some implementations may
- * require the current transformation matrix to be identity
- * before drawing.
- */
- public void background(int rgb) {
- if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) {
- background((float) rgb);
-
- } else {
- colorCalcARGB(rgb, colorModeA);
- backgroundFromCalc();
- }
- clear();
- }
-
-
- /**
- * See notes about alpha in background(x, y, z, a).
- */
- public void background(int rgb, float alpha) {
- if (mainDrawingSurface) {
- background(rgb); // don't allow people to set alpha
-
- } else {
- if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above
- background((float) rgb, alpha);
-
- } else {
- colorCalcARGB(rgb, alpha);
- backgroundFromCalc();
- clear();
- }
- }
- }
-
-
- /**
- * Set the background to a grayscale value, based on the
- * current colorMode.
- */
- public void background(float gray) {
- colorCalc(gray);
- backgroundFromCalc();
- clear();
- }
-
-
- /**
- * See notes about alpha in background(x, y, z, a).
- */
- public void background(float gray, float alpha) {
- if (mainDrawingSurface) {
- background(gray); // don't allow people to set alpha
-
- } else {
- colorCalc(gray, alpha);
- backgroundFromCalc();
- clear();
- }
- }
-
-
- /**
- * Set the background to an r, g, b or h, s, b value,
- * based on the current colorMode.
- */
- public void background(float x, float y, float z) {
- colorCalc(x, y, z);
- backgroundFromCalc();
- clear();
- }
-
-
- /**
- * Clear the background with a color that includes an alpha value.
- * This should only be used with objects created by createGraphics(),
- * setting the main drawing surface transparent may cause problems.
- * It might be tempting to use this function to partially clear the
- * screen on each frame, however that's not how this function works.
- * When calling background(), the pixels will be replaced with pixels
- * that have that level of transparency. To do a semi-transparent
- * overlay, use fill() with alpha and draw a rectangle.
- */
- public void background(float x, float y, float z, float a) {
- if (mainDrawingSurface) {
- background(x, y, z); // don't allow people to set alpha
-
- } else {
- colorCalc(x, y, z, a);
- backgroundFromCalc();
- clear();
- }
- }
-
-
- protected void backgroundFromCalc() {
- backgroundR = calcR;
- backgroundG = calcG;
- backgroundB = calcB;
- backgroundA = calcA;
- backgroundRi = calcRi;
- backgroundGi = calcGi;
- backgroundBi = calcBi;
- backgroundAi = calcAi;
- backgroundAlpha = calcAlpha;
- backgroundColor = calcColor;
- }
-
-
- /**
- * Takes an RGB or ARGB image and sets it as the background.
- *
- * Note that even if the image is set as RGB, the high 8 bits of
- * each pixel should be set opaque (0xFF000000), because the image data
- * will be copied directly to the screen, and non-opaque background
- * images may have strange behavior. Using image.filter(OPAQUE)
- * will handle this easily.
- *
- * When using 3D, this will also clear out the zbuffer and
- * stencil buffer if they exist.
- */
- public void background(PImage image) {
- if ((image.width != width) || (image.height != height)) {
- throw new RuntimeException("background image must be " +
- "the same size as your application");
- }
- if ((image.format != RGB) && (image.format != ARGB)) {
- throw new RuntimeException("background images should be RGB or ARGB");
- }
-
- // zero this out since it's an image
- backgroundColor = 0;
-
- // blit image to the screen
- System.arraycopy(image.pixels, 0, pixels, 0, pixels.length);
- }
-
-
- /**
- * Clear the pixel buffer.
- */
- abstract protected void clear();
-
-
-
- //////////////////////////////////////////////////////////////
-
- // MESSAGES / ERRORS / LOGGING
-
-
- protected void depthError(String method) {
- throw new RuntimeException(method + "() can only be used " +
- "with P3D or OPENGL.");
- }
-
-
- protected void depthErrorXYZ(String method) {
- throw new RuntimeException(method + "(x, y, z) can only be used with " +
- "OPENGL or P3D, use " +
- method + "(x, y) instead.");
- }
-
-
- protected void unavailableError(String methodStr) {
- throw new RuntimeException(methodStr +
- " is not available with this renderer");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // COLOR MANIPULATION
-
- // these functions are really slow, but easy to use
- // if folks are advanced enough to want something faster,
- // they can write it themselves (not difficult)
-
-
- public final int color(int gray) { // ignore
- if (((gray & 0xff000000) == 0) && (gray <= colorModeX)) {
- if (colorRgb255) {
- // bounds checking to make sure the numbers aren't to high or low
- if (gray > 255) gray = 255; else if (gray < 0) gray = 0;
- return 0xff000000 | (gray << 16) | (gray << 8) | gray;
- } else {
- colorCalc(gray);
- }
- } else {
- colorCalcARGB(gray, colorModeA);
- }
- return calcColor;
- }
-
- public final int color(float gray) { // ignore
- colorCalc(gray);
- return calcColor;
- }
-
-
- /**
- * @param gray can be packed ARGB or a gray in this case
- */
- public final int color(int gray, int alpha) { // ignore
- if (colorRgb255) {
- // bounds checking to make sure the numbers aren't to high or low
- if (gray > 255) gray = 255; else if (gray < 0) gray = 0;
- if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0;
-
- return ((alpha & 0xff) << 24) | (gray << 16) | (gray << 8) | gray;
- }
- colorCalc(gray, alpha);
- return calcColor;
- }
-
- /**
- * @param rgb can be packed ARGB or a gray in this case
- */
- public final int color(int rgb, float alpha) { // ignore
- if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) {
- colorCalc(rgb, alpha);
- } else {
- colorCalcARGB(rgb, alpha);
- }
- return calcColor;
- }
-
- public final int color(float gray, float alpha) { // ignore
- colorCalc(gray, alpha);
- return calcColor;
- }
-
-
- public final int color(int x, int y, int z) { // ignore
- if (colorRgb255) {
- // bounds checking to make sure the numbers aren't to high or low
- if (x > 255) x = 255; else if (x < 0) x = 0;
- if (y > 255) y = 255; else if (y < 0) y = 0;
- if (z > 255) z = 255; else if (z < 0) z = 0;
-
- return 0xff000000 | (x << 16) | (y << 8) | z;
- }
- colorCalc(x, y, z);
- return calcColor;
- }
-
- public final int color(float x, float y, float z) { // ignore
- colorCalc(x, y, z);
- return calcColor;
- }
-
-
- public final int color(int x, int y, int z, int a) { // ignore
- if (colorRgb255) {
- // bounds checking to make sure the numbers aren't to high or low
- if (a > 255) a = 255; else if (a < 0) a = 0;
- if (x > 255) x = 255; else if (x < 0) x = 0;
- if (y > 255) y = 255; else if (y < 0) y = 0;
- if (z > 255) z = 255; else if (z < 0) z = 0;
-
- return (a << 24) | (x << 16) | (y << 8) | z;
- }
- colorCalc(x, y, z, a);
- return calcColor;
- }
-
- public final int color(float x, float y, float z, float a) { // ignore
- colorCalc(x, y, z, a);
- return calcColor;
- }
-
-
- public final float alpha(int what) {
- float c = (what >> 24) & 0xff;
- if (colorModeA == 255) return c;
- return (c / 255.0f) * colorModeA;
- }
-
- public final float red(int what) {
- float c = (what >> 16) & 0xff;
- if (colorRgb255) return c;
- return (c / 255.0f) * colorModeX;
- }
-
- public final float green(int what) {
- float c = (what >> 8) & 0xff;
- if (colorRgb255) return c;
- return (c / 255.0f) * colorModeY;
- }
-
- public final float blue(int what) {
- float c = (what) & 0xff;
- if (colorRgb255) return c;
- return (c / 255.0f) * colorModeZ;
- }
-
-
- public final float hue(int what) {
- if (what != cacheHsbKey) {
- Color.RGBtoHSB((what >> 16) & 0xff, (what >> 8) & 0xff,
- what & 0xff, cacheHsbValue);
- cacheHsbKey = what;
- }
- return cacheHsbValue[0] * colorModeX;
- }
-
- public final float saturation(int what) {
- if (what != cacheHsbKey) {
- Color.RGBtoHSB((what >> 16) & 0xff, (what >> 8) & 0xff,
- what & 0xff, cacheHsbValue);
- cacheHsbKey = what;
- }
- return cacheHsbValue[1] * colorModeY;
- }
-
- public final float brightness(int what) {
- if (what != cacheHsbKey) {
- Color.RGBtoHSB((what >> 16) & 0xff, (what >> 8) & 0xff,
- what & 0xff, cacheHsbValue);
- cacheHsbKey = what;
- }
- return cacheHsbValue[2] * colorModeZ;
- }
-
-
- public int lerpColor(int c1, int c2, float amt) {
- return lerpColor(c1, c2, amt, colorMode);
- }
-
- static float[] lerpColorHSB1;
- static float[] lerpColorHSB2;
-
- static public int lerpColor(int c1, int c2, float amt, int mode) {
- if (mode == RGB) {
- float a1 = ((c1 >> 24) & 0xff);
- float r1 = (c1 >> 16) & 0xff;
- float g1 = (c1 >> 8) & 0xff;
- float b1 = c1 & 0xff;
- float a2 = (c2 >> 24) & 0xff;
- float r2 = (c2 >> 16) & 0xff;
- float g2 = (c2 >> 8) & 0xff;
- float b2 = c2 & 0xff;
-
- return (((int) (a1 + (a2-a1)*amt) << 24) |
- ((int) (r1 + (r2-r1)*amt) << 16) |
- ((int) (g1 + (g2-g1)*amt) << 8) |
- ((int) (b1 + (b2-b1)*amt)));
-
- } else if (mode == HSB) {
- if (lerpColorHSB1 == null) {
- lerpColorHSB1 = new float[3];
- lerpColorHSB2 = new float[3];
- }
-
- float a1 = (c1 >> 24) & 0xff;
- float a2 = (c2 >> 24) & 0xff;
- int alfa = ((int) (a1 + (a2-a1)*amt)) << 24;
-
- Color.RGBtoHSB((c1 >> 16) & 0xff, (c1 >> 8) & 0xff, c1 & 0xff,
- lerpColorHSB1);
- Color.RGBtoHSB((c2 >> 16) & 0xff, (c2 >> 8) & 0xff, c2 & 0xff,
- lerpColorHSB2);
-
- // roll around when 0.9 to 0.1
- // more than 0.5 away means that it should roll in the other direction
- float h1 = lerpColorHSB1[0];
- float h2 = lerpColorHSB2[0];
- if (Math.abs(h1 - h2) > 0.5f) {
- if (h1 > h2) {
- // i.e. h1 is 0.7, h2 is 0.1
- h2 += 1;
- } else {
- // i.e. h1 is 0.1, h2 is 0.7
- h1 += 1;
- }
- }
- float ho = (PApplet.lerp(lerpColorHSB1[0], lerpColorHSB2[0], amt)) % 1.0f;
- float so = PApplet.lerp(lerpColorHSB1[1], lerpColorHSB2[1], amt);
- float bo = PApplet.lerp(lerpColorHSB1[2], lerpColorHSB2[2], amt);
-
- return alfa | (Color.HSBtoRGB(ho, so, bo) & 0xFFFFFF);
- }
- return 0;
- }
-
-
- //////////////////////////////////////////////////////////////
-
- // MATH
-
-
- static final float sqrt(float a) {
- return (float)Math.sqrt(a);
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // PATH
-
- /*
- class Path {
-
- public void moveTo(float x, float y) { // ignore
- }
-
- public void lineTo(float x, float y) { // ignore
- }
-
- public void curveTo(float x1, float y1, // ignore
- float x2, float y2,
- float x3, float y3) {
- }
-
- public void closePath() { // ignore
- }
- }
- */
-
-
- //////////////////////////////////////////////////////////////
-
-
- /**
- * Use with caution on PGraphics. This should not be used with
- * the base PGraphics that's tied to a PApplet, but it can be used
- * with user-created PGraphics objects that are drawn to the screen.
- */
- public void mask(int alpha[]) { // ignore
- super.mask(alpha);
- }
-
-
- /**
- * Use with caution on PGraphics. This should not be used with
- * the base PGraphics that's tied to a PApplet, but it can be used
- * with user-created PGraphics objects that are drawn to the screen.
- */
- public void mask(PImage alpha) { // ignore
- super.mask(alpha);
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void beginRaw(PGraphics rawGraphics) {
- this.raw = rawGraphics;
- rawGraphics.beginDraw();
- }
-
-
- public void endRaw() {
- if (raw != null) {
- // for 3D, need to flush any geometry that's been stored for sorting
- raw.flush(); // this should be called by endDraw() instead
-
- // just like beginDraw, this will have to be called because
- // endDraw() will be happening outside of draw()
- raw.endDraw();
- raw.dispose();
- raw = null;
- }
- }
-
-
- /**
- * Handle any takedown for this graphics context.
- *
- * This is called when a sketch is shut down and this renderer was
- * specified using the size() command, or inside endRecord() and
- * endRaw(), in order to shut things off.
- */
- public void dispose() { // ignore
- }
-
-
- /**
- * Return true if this renderer should be drawn to the screen.
- * Overridden for subclasses like PDF so that an enormous window
- * doesn't open up.
- * showFrame, displayable, isVisible, visible, shouldDisplay,
- * what to call this?
- */
- public boolean displayable() {
- return true;
- }
-}
diff --git a/core/PGraphics2D.java b/core/PGraphics2D.java
deleted file mode 100644
index 3899b52e9..000000000
--- a/core/PGraphics2D.java
+++ /dev/null
@@ -1,1672 +0,0 @@
-/* -*- mode: jde; 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 library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-*/
-
-package processing.core;
-
-import java.awt.Toolkit;
-import java.awt.image.DirectColorModel;
-import java.awt.image.MemoryImageSource;
-
-
-/**
- * Subclass of PGraphics that handles fast 2D rendering,
- * more commonly referred to as P2D. This class uses no Java2D
- * and will run with Java 1.1.
- */
-public class PGraphics2D extends PGraphics {
-
- PPolygon polygon; // general polygon to use for shape
- PPolygon fpolygon; // used to fill polys for tri or quad strips
- PPolygon spolygon; // stroke/line polygon
- float svertices[][]; // temp vertices used for stroking end of poly
-
- // polygon that handles tesselation
- private PPolygon tpolygon;
- private int TPOLYGON_MAX_VERTICES = 512;
- private int tpolygon_vertex_order[]; // = new int[MAX_VERTICES];
-
- PLine line;
-
- //boolean untransformed;
- boolean strokeChanged = true;
- boolean fillChanged = true;
-
- static final int CVERTEX_ALLOC = 128;
- float cvertex[][] = new float[CVERTEX_ALLOC][VERTEX_FIELD_COUNT];
- int cvertexIndex;
-
-
- //////////////////////////////////////////////////////////////
-
-
- //protected PGraphics2D() { }
-
-
- /*
- public PGraphics2D(int iwidth, int iheight) {
- this(iwidth, iheight, null);
- }
- */
-
-
- public PGraphics2D(int iwidth, int iheight, PApplet applet) {
- super(iwidth, iheight, applet);
- /*
- if (applet != null) {
- this.parent = applet;
- applet.addListeners();
- }
- resize(iwidth, iheight);
- */
- }
-
-
- //resize handled by superclass
-
-
- //requestDisplay handled by superclass
-
-
- protected void allocate() {
- pixelCount = width * height;
- pixels = new int[pixelCount];
-
- // because of a java 1.1 bug, pixels must be registered as
- // opaque before their first run, the memimgsrc will flicker
- // and run very slowly.
- backgroundColor |= 0xff000000; // just for good measure
- for (int i = 0; i < pixelCount; i++) pixels[i] = backgroundColor;
- //for (int i = 0; i < pixelCount; i++) pixels[i] = 0xffffffff;
-
- //if (parent != null) {
- if (mainDrawingSurface) {
- cm = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);;
- mis = new MemoryImageSource(width, height, pixels, 0, width);
- mis.setFullBufferUpdates(true);
- mis.setAnimated(true);
- image = Toolkit.getDefaultToolkit().createImage(mis);
- }
-
- // can't un-set this because this may be only a resize (Bug #463)
- //defaultsInited = false;
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void beginDraw() {
- insideResizeWait();
- insideDraw = true;
-
- // need to call defaults(), but can only be done when it's ok
- // to draw (i.e. for opengl, no drawing can be done outside
- // beginDraw/endDraw).
- if (!defaultsInited) {
- defaults();
-
- polygon = new PPolygon(this);
- fpolygon = new PPolygon(this);
- spolygon = new PPolygon(this);
- spolygon.vertexCount = 4;
- svertices = new float[2][];
- }
-
- resetMatrix(); // reset model matrix
-
- // reset vertices
- vertexCount = 0;
- }
-
-
- public void endDraw() {
- // moving this back here (post-68) because of macosx thread problem
- if (mis != null) {
- mis.newPixels(pixels, cm, 0, width);
- }
- // mark pixels as having been updated, so that they'll work properly
- // when this PGraphics is drawn using image().
- updatePixels();
-
- insideDraw = false;
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void beginShape(int kind) {
- shape = kind;
- vertexCount = 0;
- splineVertexCount = 0;
-
- polygon.reset(0);
- fpolygon.reset(4);
- spolygon.reset(4);
-
- polygon.interpUV = false;
- }
-
-
- // PGraphics will throw a depthError
- //public void normal(float nx, float ny, float nz)
-
- // PGraphics will handle setting these
- //public void textureMode(int mode)
- //public void texture(PImage image)
- //protected void textureVertex(float u, float v)
-
-
- public void vertex(float x, float y) {
- float vertex[] = polygon.nextVertex();
- cvertexIndex = 0; // reset curves to start
-
- vertex[MX] = x;
- vertex[MY] = y;
-
- if (fill) {
- vertex[R] = fillR;
- vertex[G] = fillG;
- vertex[B] = fillB;
- vertex[A] = fillA;
- }
-
- if (stroke) {
- vertex[SR] = strokeR;
- vertex[SG] = strokeG;
- vertex[SB] = strokeB;
- vertex[SA] = strokeA;
- vertex[SW] = strokeWeight;
- }
-
- // this complicated if construct may defeat the purpose
- if (textureImage != null) {
- vertex[U] = textureU;
- vertex[V] = textureV;
- }
- }
-
-
- public void vertex(float x, float y, float u, float v) {
- textureVertex(u, v);
- vertex(x, y);
- }
-
-
- public void vertex(float x, float y, float z) {
- depthErrorXYZ("vertex");
- }
-
-
- public void vertex(float x, float y, float z, float u, float v) {
- depthErrorXYZ("vertex");
- }
-
-
- public void endShape(int mode) {
- // clear the 'shape drawing' flag in case of early exit
- //shape = 0;
- // hm can't do anymore..
-
- int polyVertexCount = polygon.vertexCount;
- float polyVertices[][] = polygon.vertices;
-
- if (untransformed()) {
- for (int i = 0; i < polyVertexCount; i++) {
- polyVertices[i][X] = polyVertices[i][MX];
- polyVertices[i][Y] = polyVertices[i][MY];
- }
- } else {
- for (int i = 0; i < polyVertexCount; i++) {
- polyVertices[i][X] = m00*polyVertices[i][MX] + m01*polyVertices[i][MY] + m03;
- polyVertices[i][Y] = m10*polyVertices[i][MX] + m11*polyVertices[i][MY] + m13;
- }
- }
-
- // ------------------------------------------------------------------
- // TEXTURES
-
- if (polygon.interpUV) {
- fpolygon.texture(textureImage); //polygon.timage);
- }
-
-
- // ------------------------------------------------------------------
- // COLORS
- // calculate RGB for each vertex
-
- spolygon.interpARGB = strokeChanged; //false;
- fpolygon.interpARGB = fillChanged; //false;
-
- // all the values for r, g, b have been set with calls to vertex()
- // (no need to re-calculate anything here)
-
-
- // ------------------------------------------------------------------
- // RENDER SHAPES
-
- int increment;
-
- switch (shape) {
- case POINTS:
- if (untransformed() && (strokeWeight == 1)) {
- if (!strokeChanged) {
- for (int i = 0; i < polyVertexCount; i++) {
- thin_point((int) polyVertices[i][X], (int) polyVertices[i][Y],
- 0, strokeColor);
- }
- } else {
- for (int i = 0; i < polyVertexCount; i++) {
- thin_point((int) polyVertices[i][X], (int) polyVertices[i][Y],
- 0, float_color(polyVertices[i][SR],
- polyVertices[i][SG],
- polyVertices[i][SB]));
- }
- //strokei = strokeiSaved;
- }
- } else {
- float f[] = polyVertices[0];
-
- for (int i = 0; i < polyVertexCount; i++) {
- float v[] = polyVertices[i];
-
- // if this is the first time (i == 0)
- // or if lighting is enabled
- // or the stroke color has changed inside beginShape/endShape
- // then re-calculate the color at this vertex
- if ((i == 0) || strokeChanged) {
- // push calculated color into 'f' (this way, f is always valid)
- calc_lighting(v[SR], v[SG], v[SB],
- v[X], v[Y], v[Z],
- v[NX], v[NY], v[NZ], f, R);
- }
- // uses [SA], since stroke alpha isn't moved into [A] the
- // way that [SR] goes to [R] etc on the calc_lighting call
- // (there's no sense in copying it to [A], except consistency
- // in the code.. but why the extra slowness?)
- thick_point(v[X], v[Y], v[Z], f[R], f[G], f[B], f[SA]);
- }
- }
- break;
-
- case LINES:
- //case LINE_STRIP:
- //case LINE_LOOP:
- if (!stroke) return;
-
- // if it's a line loop, copy the vertex data to the last element
- //if (shape == LINE_LOOP) {
- if (mode == CLOSE) {
- float v0[] = polygon.vertices[0];
- float v1[] = polygon.nextVertex();
- polyVertexCount++; // since it had already been read above
-
- v1[X] = v0[X]; v1[Y] = v0[Y]; v1[Z] = v0[Z];
- v1[SR] = v0[SR]; v1[SG] = v0[SG]; v1[SB] = v0[SB];
- }
-
- // increment by two for individual lines
- increment = (shape == LINES) ? 2 : 1;
- draw_lines(polyVertices, polyVertexCount-1, 1, increment, 0);
- break;
-
- case TRIANGLES:
- case TRIANGLE_STRIP:
- increment = (shape == TRIANGLES) ? 3 : 1;
- // do fill and stroke separately because otherwise
- // the lines will be stroked more than necessary
- if (fill) {
- fpolygon.vertexCount = 3;
- for (int i = 0; i < polyVertexCount-2; i += increment) {
- for (int j = 0; j < 3; j++) {
- fpolygon.vertices[j][R] = polyVertices[i+j][R];
- fpolygon.vertices[j][G] = polyVertices[i+j][G];
- fpolygon.vertices[j][B] = polyVertices[i+j][B];
- fpolygon.vertices[j][A] = polyVertices[i+j][A];
-
- fpolygon.vertices[j][X] = polyVertices[i+j][X];
- fpolygon.vertices[j][Y] = polyVertices[i+j][Y];
- fpolygon.vertices[j][Z] = polyVertices[i+j][Z];
-
- if (polygon.interpUV) {
- fpolygon.vertices[j][U] = polyVertices[i+j][U];
- fpolygon.vertices[j][V] = polyVertices[i+j][V];
- }
- }
- fpolygon.render();
- }
- }
- if (stroke) {
- // first draw all vertices as a line strip
- if (shape == TRIANGLE_STRIP) {
- draw_lines(polyVertices, polyVertexCount-1, 1, 1, 0);
- } else {
- draw_lines(polyVertices, polyVertexCount-1, 1, 1, 3);
- }
- // then draw from vertex (n) to (n+2)
- // incrementing n using the same as above
- draw_lines(polyVertices, polyVertexCount-2, 2, increment, 0);
- // changed this to vertexCount-2, because it seemed
- // to be adding an extra (nonexistant) line
- }
- break;
-
- case QUADS:
- case QUAD_STRIP:
- //System.out.println("pooping out a quad");
- increment = (shape == QUADS) ? 4 : 2;
- if (fill) {
- fpolygon.vertexCount = 4;
- for (int i = 0; i < polyVertexCount-3; i += increment) {
- for (int j = 0; j < 4; j++) {
- fpolygon.vertices[j][R] = polyVertices[i+j][R];
- fpolygon.vertices[j][G] = polyVertices[i+j][G];
- fpolygon.vertices[j][B] = polyVertices[i+j][B];
- fpolygon.vertices[j][A] = polyVertices[i+j][A];
-
- fpolygon.vertices[j][X] = polyVertices[i+j][X];
- fpolygon.vertices[j][Y] = polyVertices[i+j][Y];
- fpolygon.vertices[j][Z] = polyVertices[i+j][Z];
-
- if (polygon.interpUV) {
- fpolygon.vertices[j][U] = polyVertices[i+j][U];
- fpolygon.vertices[j][V] = polyVertices[i+j][V];
- }
- }
- fpolygon.render();
- }
- }
- if (stroke) {
- // first draw all vertices as a line strip
- if (shape == QUAD_STRIP) {
- draw_lines(polyVertices, polyVertexCount-1, 1, 1, 0);
- } else { // skip every few for quads
- draw_lines(polyVertices, polyVertexCount, 1, 1, 4);
- }
- // then draw from vertex (n) to (n+3)
- // incrementing n by the same increment as above
- draw_lines(polyVertices, polyVertexCount-2, 3, increment, 0);
- }
- break;
-
- case POLYGON:
- if (isConvex()) {
- if (fill) {
- polygon.render();
- if (stroke) polygon.unexpand();
- }
-
- if (stroke) {
- draw_lines(polyVertices, polyVertexCount-1, 1, 1, 0);
- // draw the last line connecting back to the first point in poly
- svertices[0] = polyVertices[polyVertexCount-1];
- svertices[1] = polyVertices[0];
- draw_lines(svertices, 1, 1, 1, 0);
- }
- } else {
- if (fill) {
- // the triangulator produces polygons that don't align
- // when smoothing is enabled. but if there is a stroke around
- // the polygon, then smoothing can be temporarily disabled.
- boolean smoov = smooth;
- //if (stroke && !hints[DISABLE_SMOOTH_HACK]) smooth = false;
- if (stroke) smooth = false;
- concaveRender();
- //if (stroke && !hints[DISABLE_SMOOTH_HACK]) smooth = smoov;
- if (stroke) smooth = smoov;
- }
-
- if (stroke) {
- draw_lines(polyVertices, polyVertexCount-1, 1, 1, 0);
- // draw the last line connecting back
- // to the first point in poly
- svertices[0] = polyVertices[polyVertexCount-1];
- svertices[1] = polyVertices[0];
- draw_lines(svertices, 1, 1, 1, 0);
- }
- }
- break;
- }
-
- // to signify no shape being drawn
- shape = 0;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // CONCAVE/CONVEX POLYGONS
-
-
- private boolean isConvex() {
- float v[][] = polygon.vertices;
- int n = polygon.vertexCount;
- int j,k;
- int flag = 0;
- float z;
- //float tol = 0.001f;
-
- if (n < 3)
- // ERROR: this is a line or a point, render with CONVEX
- return true;
-
- // iterate along border doing dot product.
- // if the sign of the result changes, then is concave
- for (int i=0;i 0)
- flag |= 2;
- if (flag == 3)
- return false; // CONCAVE
- }
- if (flag != 0)
- return true; // CONVEX
- else
- // ERROR: colinear points, self intersection
- // treat as CONVEX
- return true;
- }
-
-
- // triangulate the current polygon
- private void concaveRender() {
- // WARNING: code is not in optimum form
- // local initiations of some variables are made to
- // keep the code modular and easy to integrate
- // restet triangle
- float polyVertices[][] = polygon.vertices;
-
- if (tpolygon == null) {
- // allocate on first use, rather than slowing
- // the startup of the class.
- tpolygon = new PPolygon(this);
- tpolygon_vertex_order = new int[TPOLYGON_MAX_VERTICES];
- }
- tpolygon.reset(3);
-
- // copy render parameters
-
- if (textureImage != null) {
- tpolygon.texture(textureImage); //polygon.timage);
- }
-
- tpolygon.interpX = polygon.interpX;
- tpolygon.interpZ = polygon.interpZ;
- tpolygon.interpUV = polygon.interpUV;
- tpolygon.interpARGB = polygon.interpARGB;
-
- // simple ear clipping polygon triangulation
- // addapted from code by john w. ratcliff (jratcliff@verant.com)
-
- // 1 - first we check if the polygon goes CW or CCW
- // CW-CCW ordering adapted from code by
- // Joseph O'Rourke orourke@cs.smith.edu
- // 1A - we start by finding the lowest-right most vertex
-
- boolean ccw = false; // clockwise
-
- int n = polygon.vertexCount;
- int mm; // postion for LR vertex
- float min[] = new float[2];
-
- min[X] = polyVertices[0][X];
- min[Y] = polyVertices[0][Y];
- mm = 0;
-
- for(int i = 0; i < n; i++ ) {
- if( (polyVertices[i][Y] < min[Y]) ||
- ( (polyVertices[i][Y] == min[Y]) && (polyVertices[i][X] > min[X]) )
- ) {
- mm = i;
- min[X] = polyVertices[mm][X];
- min[Y] = polyVertices[mm][Y];
- }
- }
-
- // 1B - now we compute the cross product of the edges of this vertex
- float cp;
- int mm1;
-
- // just for renaming
- float a[] = new float[2];
- float b[] = new float[2];
- float c[] = new float[2];
-
- mm1 = (mm + (n-1)) % n;
-
- // assign a[0] to point to poly[m1][0] etc.
- for(int i = 0; i < 2; i++ ) {
- a[i] = polyVertices[mm1][i];
- b[i] = polyVertices[mm][i];
- c[i] = polyVertices[(mm+1)%n][i];
- }
-
- cp = a[0] * b[1] - a[1] * b[0] +
- a[1] * c[0] - a[0] * c[1] +
- b[0] * c[1] - c[0] * b[1];
-
- if ( cp > 0 )
- ccw = true; // CCW
- else
- ccw = false; // CW
-
- // 1C - then we sort the vertices so they
- // are always in a counterclockwise order
- //int j = 0;
- if (!ccw) {
- // keep the same order
- for (int i = 0; i < n; i++) {
- tpolygon_vertex_order[i] = i;
- }
-
- } else {
- // invert the order
- for (int i = 0; i < n; i++) {
- tpolygon_vertex_order[i] = (n - 1) - i;
- }
- }
-
- // 2 - begin triangulation
- // resulting triangles are stored in the triangle array
- // remove vc-2 Vertices, creating 1 triangle every time
- int vc = n;
- int count = 2*vc; // complex polygon detection
-
- for (int m = 0, v = vc - 1; vc > 2; ) {
- boolean snip = true;
-
- // if we start over again, is a complex polygon
- if (0 >= (count--)) {
- break; // triangulation failed
- }
-
- // get 3 consecutive vertices
- int u = v ; if (vc <= u) u = 0; // previous
- v = u+1; if (vc <= v) v = 0; // current
- int w = v+1; if (vc <= w) w = 0; // next
-
- // triangle A B C
- float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
-
- Ax = -polyVertices[tpolygon_vertex_order[u]][X];
- Ay = polyVertices[tpolygon_vertex_order[u]][Y];
- Bx = -polyVertices[tpolygon_vertex_order[v]][X];
- By = polyVertices[tpolygon_vertex_order[v]][Y];
- Cx = -polyVertices[tpolygon_vertex_order[w]][X];
- Cy = polyVertices[tpolygon_vertex_order[w]][Y];
-
- if ( EPSILON > (((Bx-Ax) * (Cy-Ay)) - ((By-Ay) * (Cx-Ax)))) {
- continue;
- }
-
- for (int p = 0; p < vc; p++) {
-
- // this part is a bit osbscure, basically what it does
- // is test if this tree vertices are and ear or not, looking for
- // intersections with the remaining vertices using a cross product
- float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
- float cCROSSap, bCROSScp, aCROSSbp;
-
- if( (p == u) || (p == v) || (p == w) ) {
- continue;
- }
-
- Px = -polyVertices[tpolygon_vertex_order[p]][X];
- Py = polyVertices[tpolygon_vertex_order[p]][Y];
-
- ax = Cx - Bx; ay = Cy - By;
- bx = Ax - Cx; by = Ay - Cy;
- cx = Bx - Ax; cy = By - Ay;
- apx= Px - Ax; apy= Py - Ay;
- bpx= Px - Bx; bpy= Py - By;
- cpx= Px - Cx; cpy= Py - Cy;
-
- aCROSSbp = ax * bpy - ay * bpx;
- cCROSSap = cx * apy - cy * apx;
- bCROSScp = bx * cpy - by * cpx;
-
- if ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)) {
- snip = false;
- }
- }
-
- if (snip) {
- // yes, the trio is an ear, render it and cut it
-
- int triangle_vertices[] = new int[3];
- int s,t;
-
- // true names of the vertices
- triangle_vertices[0] = tpolygon_vertex_order[u];
- triangle_vertices[1] = tpolygon_vertex_order[v];
- triangle_vertices[2] = tpolygon_vertex_order[w];
-
- // create triangle
- //render_triangle(triangle_vertices);
- //private final void render_triangle(int[] triangle_vertices) {
- // copy all fields of the triangle vertices
- for (int i = 0; i < 3; i++) {
- float[] src = polygon.vertices[triangle_vertices[i]];
- float[] dest = tpolygon.vertices[i];
- for (int k = 0; k < VERTEX_FIELD_COUNT; k++) {
- dest[k] = src[k];
- }
- }
- // render triangle
- tpolygon.render();
- //}
-
- m++;
-
- // remove v from remaining polygon
- for( s = v, t = v + 1; t < vc; s++, t++) {
- tpolygon_vertex_order[s] = tpolygon_vertex_order[t];
- }
-
- vc--;
-
- // resest error detection counter
- count = 2 * vc;
- }
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // RECT
-
-
- protected void rectImpl(float x1f, float y1f, float x2f, float y2f) {
-
- if (untransformed() && !fillAlpha) {
- int x1 = (int) x1f;
- int y1 = (int) y1f;
- int x2 = (int) x2f;
- int y2 = (int) y2f;
-
- rectImplFillUntranSolidRGB(x1, y1, x2, y2);
-
- if (stroke) {
- if (strokeWeight == 1) {
- thin_flat_line(x1, y1, x2, y1);
- thin_flat_line(x2, y1, x2, y2);
- thin_flat_line(x2, y2, x1, y2);
- thin_flat_line(x1, y2, x1, y1);
-
- } else {
- thick_flat_line(x1, y1, fillR, fillG, fillB, fillA,
- x2, y1, fillR, fillG, fillB, fillA);
- thick_flat_line(x2, y1, fillR, fillG, fillB, fillA,
- x2, y2, fillR, fillG, fillB, fillA);
- thick_flat_line(x2, y2, fillR, fillG, fillB, fillA,
- x1, y2, fillR, fillG, fillB, fillA);
- thick_flat_line(x1, y2, fillR, fillG, fillB, fillA,
- x1, y1, fillR, fillG, fillB, fillA);
- }
- }
-
- } else {
- beginShape(QUADS);
- vertex(x1f, y1f);
- vertex(x2f, y1f);
- vertex(x2f, y2f);
- vertex(x1f, y2f);
- endShape();
- }
- }
-
-
- /**
- * Draw an untransformed rectangle with no alpha.
- */
- private void rectImplFillUntranSolidRGB(int x1, int y1, int x2, int y2) {
- //System.out.println("flat quad");
- if (y2 < y1) {
- int temp = y1; y1 = y2; y2 = temp;
- }
- if (x2 < x1) {
- int temp = x1; x1 = x2; x2 = temp;
- }
- // checking to watch out for boogers
- if ((x1 > width1) || (x2 < 0) ||
- (y1 > height1) || (y2 < 0)) return;
-
- //if (fill) {
- int fx1 = x1;
- int fy1 = y1;
- int fx2 = x2;
- int fy2 = y2;
-
- // these only affect the fill, not the stroke
- // (otherwise strange boogers at edges b/c frame changes shape)
- if (fx1 < 0) fx1 = 0;
- if (fx2 > width) fx2 = width;
- if (fy1 < 0) fy1 = 0;
- if (fy2 > height) fy2 = height;
-
- // [toxi 031223]
- // on avg. 20-25% faster fill routine using System.arraycopy()
- int ww = fx2 - fx1;
- int hh = fy2 - fy1;
- int[] row = new int[ww];
- for (int i = 0; i < ww; i++) row[i] = fillColor;
- int idx = fy1 * width + fx1;
- for (int y = 0; y < hh; y++) {
- System.arraycopy(row, 0, pixels, idx, ww);
- idx += width;
- }
- row = null;
- //}
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // ELLIPSE AND ARC
-
-
- public void ellipseImpl(float x1, float y1, float w, float h) {
- if (!smooth && (strokeWeight == 1) &&
- !fillAlpha && !strokeAlpha && untransformed()) {
- float hradius = w / 2f;
- float vradius = h / 2f;
-
- int centerX = (int) (x1 + hradius);
- int centerY = (int) (y1 + vradius);
-
- if (hradius == vradius) {
- flat_circle(centerX, centerY, (int)hradius);
-
- } else {
- flat_ellipse(centerX, centerY, (int)hradius, (int)vradius);
- }
- } else {
- super.ellipseImpl(x1, y1, w, h);
- }
- }
-
-
- private void flat_circle(int centerX, int centerY, int radius) {
- if (unwarped()) {
- float x = m00*centerX + m01*centerY + m02;
- float y = m10*centerX + m11*centerY + m12;
- centerX = (int)x;
- centerY = (int)y;
- }
- if (fill) flat_circle_fill(centerX, centerY, radius);
- if (stroke) flat_circle_stroke(centerX, centerY, radius);
- }
-
-
- /**
- * Draw the outline around a flat circle using a bresenham-style
- * algorithm. Adapted from drawCircle function in "Computer Graphics
- * for Java Programmers" by Leen Ammeraal, p. 110.
- *
- * This function is included because the quality is so much better,
- * and the drawing significantly faster than with adaptive ellipses
- * drawn using the sine/cosine tables.
- *
- * Circle quadrants break down like so:
- *
- * @param xc x center
- * @param yc y center
- * @param r radius
- */
- private void flat_circle_stroke(int xC, int yC, int r) {
- int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0;
- while (x < y) {
- thin_point(xC + x, yC + y, 0, strokeColor); // NNE
- thin_point(xC + y, yC - x, 0, strokeColor); // ESE
- thin_point(xC - x, yC - y, 0, strokeColor); // SSW
- thin_point(xC - y, yC + x, 0, strokeColor); // WNW
-
- x++; E += u; u += 2;
- if (v < 2 * E) {
- y--; E -= v; v -= 2;
- }
- if (x > y) break;
-
- thin_point(xC + y, yC + x, 0, strokeColor); // ENE
- thin_point(xC + x, yC - y, 0, strokeColor); // SSE
- thin_point(xC - y, yC - x, 0, strokeColor); // WSW
- thin_point(xC - x, yC + y, 0, strokeColor); // NNW
- }
- }
-
- /**
- * Heavily adapted version of the above algorithm that handles
- * filling the ellipse. Works by drawing from the center and
- * outwards to the points themselves. Has to be done this way
- * because the values for the points are changed halfway through
- * the function, making it impossible to just store a series of
- * left and right edges to be drawn more quickly.
- *
- * @param xc x center
- * @param yc y center
- * @param r radius
- */
- private void flat_circle_fill(int xc, int yc, int r) {
- int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0;
- while (x < y) {
- for (int xx = xc; xx < xc + x; xx++) { // NNE
- thin_point(xx, yc + y, 0, fillColor);
- }
- for (int xx = xc; xx < xc + y; xx++) { // ESE
- thin_point(xx, yc - x, 0, fillColor);
- }
- for (int xx = xc - x; xx < xc; xx++) { // SSW
- thin_point(xx, yc - y, 0, fillColor);
- }
- for (int xx = xc - y; xx < xc; xx++) { // WNW
- thin_point(xx, yc + x, 0, fillColor);
- }
-
- x++; E += u; u += 2;
- if (v < 2 * E) {
- y--; E -= v; v -= 2;
- }
- if (x > y) break;
-
- for (int xx = xc; xx < xc + y; xx++) { // ENE
- thin_point(xx, yc + x, 0, fillColor);
- }
- for (int xx = xc; xx < xc + x; xx++) { // SSE
- thin_point(xx, yc - y, 0, fillColor);
- }
- for (int xx = xc - y; xx < xc; xx++) { // WSW
- thin_point(xx, yc - x, 0, fillColor);
- }
- for (int xx = xc - x; xx < xc; xx++) { // NNW
- thin_point(xx, yc + y, 0, fillColor);
- }
- }
- }
-
- // unfortunately this can't handle fill and stroke simultaneously,
- // because the fill will later replace some of the stroke points
-
- private final void flat_ellipse_symmetry(int centerX, int centerY,
- int ellipseX, int ellipseY,
- boolean filling) {
- if (filling) {
- for (int i = centerX - ellipseX + 1; i < centerX + ellipseX; i++) {
- thin_point(i, centerY - ellipseY, 0, fillColor);
- thin_point(i, centerY + ellipseY, 0, fillColor);
- }
- } else {
- thin_point(centerX - ellipseX, centerY + ellipseY, 0, strokeColor);
- thin_point(centerX + ellipseX, centerY + ellipseY, 0, strokeColor);
- thin_point(centerX - ellipseX, centerY - ellipseY, 0, strokeColor);
- thin_point(centerX + ellipseX, centerY - ellipseY, 0, strokeColor);
- }
- }
-
-
- /**
- * Bresenham-style ellipse drawing function, adapted from a posting to
- * comp.graphics.algortihms.
- *
- * This function is included because the quality is so much better,
- * and the drawing significantly faster than with adaptive ellipses
- * drawn using the sine/cosine tables.
- *
- * @param centerX x coordinate of the center
- * @param centerY y coordinate of the center
- * @param a horizontal radius
- * @param b vertical radius
- */
- private void flat_ellipse_internal(int centerX, int centerY,
- int a, int b, boolean filling) {
- int x, y, a2, b2, s, t;
-
- a2 = a*a;
- b2 = b*b;
- x = 0;
- y = b;
- s = a2*(1-2*b) + 2*b2;
- t = b2 - 2*a2*(2*b-1);
- flat_ellipse_symmetry(centerX, centerY, x, y, filling);
-
- do {
- if (s < 0) {
- s += 2*b2*(2*x+3);
- t += 4*b2*(x+1);
- x++;
- } else if (t < 0) {
- s += 2*b2*(2*x+3) - 4*a2*(y-1);
- t += 4*b2*(x+1) - 2*a2*(2*y-3);
- x++;
- y--;
- } else {
- s -= 4*a2*(y-1);
- t -= 2*a2*(2*y-3);
- y--;
- }
- flat_ellipse_symmetry(centerX, centerY, x, y, filling);
-
- } while (y > 0);
- }
-
-
- private void flat_ellipse(int centerX, int centerY, int a, int b) {
- if (unwarped()) {
- float x = m00*centerX + m01*centerY + m02;
- float y = m10*centerX + m11*centerY + m12;
- centerX = (int)x;
- centerY = (int)y;
- }
- if (fill) flat_ellipse_internal(centerX, centerY, a, b, true);
- if (stroke) flat_ellipse_internal(centerX, centerY, a, b, false);
- }
-
-
- // TODO really need a decent arc function in here..
-
- //protected void arcImpl(float x1, float y1, float w, float h,
- // float start, float stop)
-
-
-
- //////////////////////////////////////////////////////////////
-
- // BOX & SPHERE
-
-
- // The PGraphics superclass will throw errors for these fellas
-
-
-
- //////////////////////////////////////////////////////////////
-
- // BEZIER & CURVE
-
-
- public void bezier(float x1, float y1, float z1,
- float x2, float y2, float z2,
- float x3, float y3, float z3,
- float x4, float y4, float z4) {
- depthErrorXYZ("bezier");
- }
-
-
- public void curve(float x1, float y1, float z1,
- float x2, float y2, float z2,
- float x3, float y3, float z3,
- float x4, float y4, float z4) {
- depthErrorXYZ("curve");
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // IMAGE
-
-
- protected void imageImpl(PImage image,
- float x1, float y1, float x2, float y2,
- int u1, int v1, int u2, int v2) {
- if ((x2 - x1 == image.width) &&
- (y2 - y1 == image.height) &&
- !tint && unwarped()) {
- flat_image(image, (int) (x1 + m02), (int) (y1 + m12), u1, v1, u2, v2);
-
- } else {
- super.imageImpl(image, x1, y1, x2, y2, u1, v1, u2, v2);
- }
- }
-
-
- /**
- * Image drawn in flat "screen space", with no scaling or warping.
- * this is so common that a special routine is included for it,
- * because the alternative is much slower.
- *
- * @param image image to be drawn
- * @param sx1 x coordinate of upper-lefthand corner in screen space
- * @param sy1 y coordinate of upper-lefthand corner in screen space
- */
- private void flat_image(PImage image, int sx1, int sy1,
- int ix1, int iy1, int ix2, int iy2) {
- /*
- int ix1 = 0;
- int iy1 = 0;
- int ix2 = image.width;
- int iy2 = image.height;
- */
-
- if (imageMode == CENTER) {
- sx1 -= image.width / 2;
- sy1 -= image.height / 2;
- }
-
- int sx2 = sx1 + image.width;
- int sy2 = sy1 + image.height;
-
- // don't draw if completely offscreen
- // (without this check, ArrayIndexOutOfBoundsException)
- if ((sx1 > width1) || (sx2 < 0) ||
- (sy1 > height1) || (sy2 < 0)) return;
-
- if (sx1 < 0) { // off left edge
- ix1 -= sx1;
- sx1 = 0;
- }
- if (sy1 < 0) { // off top edge
- iy1 -= sy1;
- sy1 = 0;
- }
- if (sx2 > width) { // off right edge
- ix2 -= sx2 - width;
- sx2 = width;
- }
- if (sy2 > height) { // off bottom edge
- iy2 -= sy2 - height;
- sy2 = height;
- }
-
- int source = iy1 * image.width + ix1;
- int target = sy1 * width;
-
- if (image.format == ARGB) {
- for (int y = sy1; y < sy2; y++) {
- int tx = 0;
-
- for (int x = sx1; x < sx2; x++) {
- pixels[target + x] =
- _blend(pixels[target + x],
- image.pixels[source + tx],
- image.pixels[source + tx++] >>> 24);
- }
- source += image.width;
- target += width;
- }
- } else if (image.format == ALPHA) {
- for (int y = sy1; y < sy2; y++) {
- int tx = 0;
-
- for (int x = sx1; x < sx2; x++) {
- pixels[target + x] =
- _blend(pixels[target + x],
- fillColor,
- image.pixels[source + tx++]);
- }
- source += image.width;
- target += width;
- }
-
- } else if (image.format == RGB) {
- target += sx1;
- int tw = sx2 - sx1;
- for (int y = sy1; y < sy2; y++) {
- System.arraycopy(image.pixels, source, pixels, target, tw);
- // should set z coordinate in here
- // or maybe not, since dims=0, meaning no relevant z
- source += image.width;
- target += width;
- }
- }
- }
-
-
- //////////////////////////////////////////////////////////////
-
- // TEXT/FONTS
-
-
- // These will be handled entirely by PGraphics.
-
-
-
- //////////////////////////////////////////////////////////////
-
-
- // expects properly clipped coords, hence does
- // NOT check if x/y are in bounds [toxi]
- private void thin_pointAt(int x, int y, float z, int color) {
- int index = y*width+x; // offset values are pre-calced in constructor
- pixels[index] = color;
- zbuffer[index] = z;
- }
-
- // expects offset/index in pixelbuffer array instead of x/y coords
- // used by optimized parts of thin_flat_line() [toxi]
- private void thin_pointAtIndex(int offset, float z, int color) {
- pixels[offset] = color;
- zbuffer[offset] = z;
- }
-
- // points are inherently flat, but always tangent
- // to the screen surface. the z is only so that things
- // get scaled properly if the pt is way in back
- private void thick_point(float x, float y, float z, // note floats
- float r, float g, float b, float a) {
- spolygon.reset(4);
- spolygon.interpARGB = false; // no changes for vertices of a point
-
- float strokeWidth2 = strokeWeight/2.0f;
-
- float svertex[] = spolygon.vertices[0];
- svertex[X] = x - strokeWidth2;
- svertex[Y] = y - strokeWidth2;
- svertex[Z] = z;
-
- svertex[R] = r;
- svertex[G] = g;
- svertex[B] = b;
- svertex[A] = a;
-
- svertex = spolygon.vertices[1];
- svertex[X] = x + strokeWidth2;
- svertex[Y] = y - strokeWidth2;
- svertex[Z] = z;
-
- svertex = spolygon.vertices[2];
- svertex[X] = x + strokeWidth2;
- svertex[Y] = y + strokeWidth2;
- svertex[Z] = z;
-
- svertex = spolygon.vertices[3];
- svertex[X] = x - strokeWidth2;
- svertex[Y] = y + strokeWidth2;
- svertex[Z] = z;
-
- spolygon.render();
- }
-
-
- // new bresenham clipping code, as old one was buggy [toxi]
- private void thin_flat_line(int x1, int y1, int x2, int y2) {
- int nx1,ny1,nx2,ny2;
-
- // get the "dips" for the points to clip
- int code1 = thin_flat_lineClipCode(x1, y1);
- int code2 = thin_flat_lineClipCode(x2, y2);
-
- if ((code1 & code2)!=0) {
- return;
- } else {
- int dip = code1 | code2;
- if (dip != 0) {
- // now calculate the clipped points
- float a1 = 0, a2 = 1, a = 0;
- for (int i=0;i<4;i++) {
- if (((dip>>i)%2)==1) {
- a = thin_flat_lineSlope((float)x1, (float)y1,
- (float)x2, (float)y2, i+1);
- if (((code1>>i)%2)==1) {
- a1 = (float)Math.max(a, a1);
- } else {
- a2 = (float)Math.min(a, a2);
- }
- }
- }
- if (a1>a2) return;
- else {
- nx1=(int) (x1+a1*(x2-x1));
- ny1=(int) (y1+a1*(y2-y1));
- nx2=(int) (x1+a2*(x2-x1));
- ny2=(int) (y1+a2*(y2-y1));
- }
- // line is fully visible/unclipped
- } else {
- nx1=x1; nx2=x2;
- ny1=y1; ny2=y2;
- }
- }
-
- // new "extremely fast" line code
- // adapted from http://www.edepot.com/linee.html
-
- boolean yLonger=false;
- int shortLen=ny2-ny1;
- int longLen=nx2-nx1;
- if (Math.abs(shortLen)>Math.abs(longLen)) {
- int swap=shortLen;
- shortLen=longLen;
- longLen=swap;
- yLonger=true;
- }
- int decInc;
- if (longLen==0) decInc=0;
- else decInc = (shortLen << 16) / longLen;
-
- if (nx1==nx2) {
- // special case: vertical line
- if (ny1>ny2) { int ty=ny1; ny1=ny2; ny2=ty; }
- int offset=ny1*width+nx1;
- for(int j=ny1; j<=ny2; j++) {
- thin_pointAtIndex(offset,0,strokeColor);
- offset+=width;
- }
- return;
- } else if (ny1==ny2) {
- // special case: horizontal line
- if (nx1>nx2) { int tx=nx1; nx1=nx2; nx2=tx; }
- int offset=ny1*width+nx1;
- for(int j=nx1; j<=nx2; j++) thin_pointAtIndex(offset++,0,strokeColor);
- return;
- } else if (yLonger) {
- if (longLen>0) {
- longLen+=ny1;
- for (int j=0x8000+(nx1<<16);ny1<=longLen;++ny1) {
- thin_pointAt(j>>16, ny1, 0, strokeColor);
- j+=decInc;
- }
- return;
- }
- longLen+=ny1;
- for (int j=0x8000+(nx1<<16);ny1>=longLen;--ny1) {
- thin_pointAt(j>>16, ny1, 0, strokeColor);
- j-=decInc;
- }
- return;
- } else if (longLen>0) {
- longLen+=nx1;
- for (int j=0x8000+(ny1<<16);nx1<=longLen;++nx1) {
- thin_pointAt(nx1, j>>16, 0, strokeColor);
- j+=decInc;
- }
- return;
- }
- longLen+=nx1;
- for (int j=0x8000+(ny1<<16);nx1>=longLen;--nx1) {
- thin_pointAt(nx1, j>>16, 0, strokeColor);
- j-=decInc;
- }
- }
-
- private int thin_flat_lineClipCode(float x, float y) {
- return ((y < 0 ? 8 : 0) | (y > height1 ? 4 : 0) |
- (x < 0 ? 2 : 0) | (x > width1 ? 1 : 0));
- }
-
- private float thin_flat_lineSlope(float x1, float y1,
- float x2, float y2, int border) {
- switch (border) {
- case 4: {
- return (-y1)/(y2-y1);
- }
- case 3: {
- return (height1-y1)/(y2-y1);
- }
- case 2: {
- return (-x1)/(x2-x1);
- }
- case 1: {
- return (width1-x1)/(x2-x1);
- }
- }
- return -1f;
- }
-
-
- private boolean flat_line_retribution(float x1, float y1,
- float x2, float y2,
- float r1, float g1, float b1) {
- /*
- // assume that if it is/isn't big in one dir, then the
- // other doesn't matter, cuz that's a weird case
- float lwidth = m00*strokeWeight + m01*strokeWeight;
- //float lheight = m10*strokeWeight + m11*strokeWeight;
- // lines of stroke thickness 1 can be anywhere from -1.41 to 1.41
- if ((strokeWeight < TWO) && (!hints[SCALE_STROKE_WIDTH])) {
- //if (abs(lwidth) < 1.5f) {
- //System.out.println("flat line retribution " + r1 + " " + g1 + " " + b1);
- int strokeSaved = strokeColor;
- strokeColor = float_color(r1, g1, b1);
- thin_flat_line((int)x1, (int)y1, (int)x2, (int)y2);
- strokeColor = strokeSaved;
- return true;
- }
- */
- return false;
- }
-
-
- private void thick_flat_line(float ox1, float oy1,
- float r1, float g1, float b1, float a1,
- float ox2, float oy2,
- float r2, float g2, float b2, float a2) {
- spolygon.interpARGB = (r1 != r2) || (g1 != g2) || (b1 != b2) || (a1 != a2);
- spolygon.interpZ = false;
-
- if (!spolygon.interpARGB &&
- flat_line_retribution(ox1, oy1, ox2, oy2, r1, g1, b1)) {
- return;
- }
-
- float dX = ox2-ox1 + EPSILON;
- float dY = oy2-oy1 + EPSILON;
- float len = sqrt(dX*dX + dY*dY);
-
- // TODO strokeWidth should be transformed!
- float rh = strokeWeight / len;
-
- float dx0 = rh * dY;
- float dy0 = rh * dX;
- float dx1 = rh * dY;
- float dy1 = rh * dX;
-
- spolygon.reset(4);
-
- float svertex[] = spolygon.vertices[0];
- svertex[X] = ox1+dx0;
- svertex[Y] = oy1-dy0;
- svertex[R] = r1;
- svertex[G] = g1;
- svertex[B] = b1;
- svertex[A] = a1;
-
- svertex = spolygon.vertices[1];
- svertex[X] = ox1-dx0;
- svertex[Y] = oy1+dy0;
- svertex[R] = r1;
- svertex[G] = g1;
- svertex[B] = b1;
- svertex[A] = a1;
-
- svertex = spolygon.vertices[2];
- svertex[X] = ox2-dx1;
- svertex[Y] = oy2+dy1;
- svertex[R] = r2;
- svertex[G] = g2;
- svertex[B] = b2;
- svertex[A] = a2;
-
- svertex = spolygon.vertices[3];
- svertex[X] = ox2+dx1;
- svertex[Y] = oy2-dy1;
- svertex[R] = r2;
- svertex[G] = g2;
- svertex[B] = b2;
- svertex[A] = a2;
-
- spolygon.render();
- }
-
-
- /*
- // OPT version without z coords can save 8 multiplies and some other
- private void spatial_line(float x1, float y1,
- float r1, float g1, float b1,
- float x2, float y2,
- float r2, float g2, float b2) {
- spatial_line(x1, y1, 0, r1, g1, b1,
- x2, y2, 0, r2, g2, b2);
- }
-
-
- // the incoming values are transformed,
- // and the colors have been calculated
-
- private void spatial_line(float x1, float y1, float z1,
- float r1, float g1, float b1,
- float x2, float y2, float z2,
- float r2, float g2, float b2) {
- spolygon.interpARGB = (r1 != r2) || (g1 != g2) || (b1 != b2);
- if (!spolygon.interpARGB &&
- flat_line_retribution(x1, y1, x2, y2, r1, g1, b1)) {
- return;
- }
-
- spolygon.interpZ = true;
-
- float ox1 = x1; float oy1 = y1; float oz1 = z1;
- float ox2 = x2; float oy2 = y2; float oz2 = z2;
-
- float dX = ox2-ox1 + 0.0001f;
- float dY = oy2-oy1 + 0.0001f;
- float len = sqrt(dX*dX + dY*dY);
-
- //float x0 = m00*0 + m01*0 + m03;
-
- float rh = strokeWeight / len;
-
- float dx0 = rh * dY;
- float dy0 = rh * dX;
- float dx1 = rh * dY;
- float dy1 = rh * dX;
-
- spolygon.reset(4);
-
- float svertex[] = spolygon.vertices[0];
- svertex[X] = ox1+dx0;
- svertex[Y] = oy1-dy0;
- svertex[Z] = oz1;
- svertex[R] = r1; //calcR1;
- svertex[G] = g1; //calcG1;
- svertex[B] = b1; //calcB1;
-
- svertex = spolygon.vertices[1];
- svertex[X] = ox1-dx0;
- svertex[Y] = oy1+dy0;
- svertex[Z] = oz1;
- svertex[R] = r1; //calcR1;
- svertex[G] = g1; //calcG1;
- svertex[B] = b1; //calcB1;
-
- svertex = spolygon.vertices[2];
- svertex[X] = ox2-dx1;
- svertex[Y] = oy2+dy1;
- svertex[Z] = oz2;
- svertex[R] = r2; //calcR2;
- svertex[G] = g2; //calcG2;
- svertex[B] = b2; //calcB2;
-
- svertex = spolygon.vertices[3];
- svertex[X] = ox2+dx1;
- svertex[Y] = oy2-dy1;
- svertex[Z] = oz2;
- svertex[R] = r2; //calcR2;
- svertex[G] = g2; //calcG2;
- svertex[B] = b2; //calcB2;
-
- spolygon.render();
- }
- */
-
-
- // max is what to count to
- // offset is offset to the 'next' vertex
- // increment is how much to increment in the loop
- private void draw_lines(float vertices[][], int max,
- int offset, int increment, int skip) {
-
- if (strokeWeight < 2) {
- for (int i = 0; i < max; i += increment) {
- if ((skip != 0) && (((i+offset) % skip) == 0)) continue;
-
- float a[] = vertices[i];
- float b[] = vertices[i+offset];
-
- if (line == null) line = new PLine(this);
-
- line.reset();
- line.setIntensities(a[SR], a[SG], a[SB], a[SA],
- b[SR], b[SG], b[SB], b[SA]);
- line.setVertices(a[X], a[Y], a[Z],
- b[X], b[Y], b[Z]);
- line.draw();
- }
-
- } else { // use old line code for thickness > 1
-
- if ((strokeWeight < 2) && !strokeChanged) {
- // need to set color at least once?
-
- // THIS PARTICULAR CASE SHOULD NO LONGER BE REACHABLE
-
- for (int i = 0; i < max; i += increment) {
- if ((skip != 0) && (((i+offset) % skip) == 0)) continue;
- thin_flat_line((int) vertices[i][X],
- (int) vertices[i][Y],
- (int) vertices[i+offset][X],
- (int) vertices[i+offset][Y]);
- }
- } else {
- for (int i = 0; i < max; i += increment) {
- if ((skip != 0) && (((i+offset) % skip) == 0)) continue;
- float v1[] = vertices[i];
- float v2[] = vertices[i+offset];
- thick_flat_line(v1[X], v1[Y], v1[SR], v1[SG], v1[SB], v1[SA],
- v2[X], v2[Y], v2[SR], v2[SG], v2[SB], v2[SA]);
- }
- }
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // UGLY RENDERING SHIT
-
-
- private void thin_point(int x, int y, float z, int color) {
- // necessary? [fry] yes! [toxi]
- if (x<0 || x>width1 || y<0 || y>height1) return;
-
- int index = y*width + x;
- if ((color & 0xff000000) == 0xff000000) { // opaque
- pixels[index] = color;
-
- } else { // transparent
- // couldn't seem to get this working correctly
-
- //pixels[index] = _blend(pixels[index],
- // color & 0xffffff, (color >> 24) & 0xff);
-
- // a1 is how much of the orig pixel
- int a2 = (color >> 24) & 0xff;
- int a1 = a2 ^ 0xff;
-
- int p2 = strokeColor;
- int p1 = pixels[index];
-
- int r = (a1 * ((p1 >> 16) & 0xff) + a2 * ((p2 >> 16) & 0xff)) & 0xff00;
- int g = (a1 * ((p1 >> 8) & 0xff) + a2 * ((p2 >> 8) & 0xff)) & 0xff00;
- int b = (a1 * ( p1 & 0xff) + a2 * ( p2 & 0xff)) >> 8;
-
- pixels[index] = 0xff000000 | (r << 8) | g | b;
-
- //pixels[index] = _blend(pixels[index],
- // color & 0xffffff, (color >> 24) & 0xff);
- /*
- pixels[index] = 0xff000000 |
- ((((a1 * ((pixels[index] >> 16) & 0xff) +
- a2 * ((color >> 16) & 0xff)) & 0xff00) << 24) << 8) |
- (((a1 * ((pixels[index] >> 8) & 0xff) +
- a2 * ((color >> 8) & 0xff)) & 0xff00) << 16) |
- (((a1 * ( pixels[index] & 0xff) +
- a2 * ( color & 0xff)) >> 8));
- */
- }
- zbuffer[index] = z;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // BACKGROUND AND FRIENDS
-
-
- /**
- * Clear the pixel buffer.
- */
- protected void clear() {
- for (int i = 0; i < pixelCount; i++) {
- pixels[i] = backgroundColor;
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // INTERNAL SCHIZZLE
-
-
- private boolean untransformed() {
- return ((m00 == 1) && (m01 == 0) && (m02 == 0) &&
- (m10 == 0) && (m11 == 1) && (m12 == 0));
- }
-
-
- private boolean unwarped() {
- return ((m00 == 1) && (m01 == 0) && (m10 == 0) && (m11 == 1));
- }
-
-
-
- // doesn't really do lighting per se...
- private void calc_lighting(float r, float g, float b,
- float ix, float iy, float iz,
- float nx, float ny, float nz,
- float target[], int toffset) {
- target[toffset + 0] = r;
- target[toffset + 1] = g;
- target[toffset + 2] = b;
- }
-
-
- static private final int float_color(float r, float g, float b) {
- return (0xff000000 |
- ((int) (255.0f * r)) << 16 |
- ((int) (255.0f * g)) << 8 |
- ((int) (255.0f * b)));
- }
-
- public final static int _blend(int p1, int p2, int a2) {
- // scale alpha by alpha of incoming pixel
- a2 = (a2 * (p2 >>> 24)) >> 8;
-
- int a1 = a2 ^ 0xff;
- int r = (a1 * ((p1 >> 16) & 0xff) + a2 * ((p2 >> 16) & 0xff)) & 0xff00;
- int g = (a1 * ((p1 >> 8) & 0xff) + a2 * ((p2 >> 8) & 0xff)) & 0xff00;
- int b = (a1 * ( p1 & 0xff) + a2 * ( p2 & 0xff)) >> 8;
-
- return 0xff000000 | (r << 8) | g | b;
- }
-}
diff --git a/core/PGraphicsJava2D.java b/core/PGraphicsJava2D.java
deleted file mode 100644
index 5766addce..000000000
--- a/core/PGraphicsJava2D.java
+++ /dev/null
@@ -1,1381 +0,0 @@
-/* -*- mode: jde; 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 library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-*/
-
-package processing.core;
-
-import java.awt.*;
-import java.awt.geom.*;
-import java.awt.image.*;
-
-
-/**
- * Subclass for PGraphics that implements the graphics API
- * in Java 1.3+ using Java 2D.
- *
- *
Pixel operations too slow? As of release 0085 (the first beta),
- * the default renderer uses Java2D. It's more accurate than the renderer
- * used in alpha releases of Processing (it handles stroke caps and joins,
- * and has better polygon tessellation), but it's super slow for handling
- * pixels. At least until we get a chance to get the old 2D renderer
- * (now called P2D) working in a similar fashion, you can use
- * size(w, h, P3D) instead of size(w, h) which will
- * be faster for general pixel flipping madness.
- *
- *
To get access to the Java 2D "Graphics2D" object for the default
- * renderer, use:
- *
Graphics2D g2 = ((PGraphicsJava2D)g).g2;
- * This will let you do Java 2D stuff directly, but is not supported in
- * any way shape or form. Which just means "have fun, but don't complain
- * if it breaks."
- */
-public class PGraphicsJava2D extends PGraphics {
-
- public Graphics2D g2;
- GeneralPath gpath;
-
- int transformCount;
- AffineTransform transformStack[] =
- new AffineTransform[MATRIX_STACK_DEPTH];
- double transform[] = new double[6];
-
- Line2D.Float line = new Line2D.Float();
- Ellipse2D.Float ellipse = new Ellipse2D.Float();
- Rectangle2D.Float rect = new Rectangle2D.Float();
- Arc2D.Float arc = new Arc2D.Float();
-
- protected Color tintColorObject;
-
- protected Color fillColorObject;
- public boolean fillGradient;
- public Paint fillGradientObject;
-
- protected Color strokeColorObject;
- public boolean strokeGradient;
- public Paint strokeGradientObject;
-
-
-
- //////////////////////////////////////////////////////////////
-
- // INTERNAL
-
-
- /**
- * Constructor for the PGraphicsJava object.
- * This prototype only exists because of annoying
- * java compilers, and should not be used.
- */
- //public PGraphicsJava2D() { }
-
-
- /**
- * Constructor for the PGraphics object. Use this to ensure that
- * the defaults get set properly. In a subclass, use this(w, h)
- * as the first line of a subclass' constructor to properly set
- * the internal fields and defaults.
- *
- * @param iwidth viewport width
- * @param iheight viewport height
- */
- public PGraphicsJava2D(int iwidth, int iheight, PApplet parent) {
- super(iwidth, iheight, parent);
- //resize(iwidth, iheight);
- }
-
-
- /**
- * Called in repsonse to a resize event, handles setting the
- * new width and height internally, as well as re-allocating
- * the pixel buffer for the new size.
- *
- * Note that this will nuke any cameraMode() settings.
- */
- public void resize(int iwidth, int iheight) { // ignore
- //System.out.println("resize " + iwidth + " " + iheight);
- insideDrawWait();
- insideResize = true;
-
- width = iwidth;
- height = iheight;
- width1 = width - 1;
- height1 = height - 1;
-
- allocate();
-
- // ok to draw again
- insideResize = false;
- }
-
-
- // broken out because of subclassing for opengl
- protected void allocate() {
- image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- g2 = (Graphics2D) image.getGraphics();
- // can't un-set this because this may be only a resize (Bug #463)
- //defaultsInited = false;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // FRAME
-
-
- public void beginDraw() {
- insideResizeWait();
- insideDraw = true;
-
- // need to call defaults(), but can only be done when it's ok
- // to draw (i.e. for opengl, no drawing can be done outside
- // beginDraw/endDraw).
- if (!defaultsInited) defaults();
-
- resetMatrix(); // reset model matrix
-
- // reset vertices
- vertexCount = 0;
- }
-
-
- public void endDraw() {
- // hm, mark pixels as changed, because this will instantly do a full
- // copy of all the pixels to the surface.. so that's kind of a mess.
- //updatePixels();
-
- if (!mainDrawingSurface) {
- loadPixels();
- }
- modified = true;
- insideDraw = false;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // SHAPES
-
-
- public void beginShape(int kind) {
- //super.beginShape(kind);
- shape = kind;
- vertexCount = 0;
- splineVertexCount = 0;
-
- // set gpath to null, because when mixing curves and straight
- // lines, vertexCount will be set back to zero, so vertexCount == 1
- // is no longer a good indicator of whether the shape is new.
- // this way, just check to see if gpath is null, and if it isn't
- // then just use it to continue the shape.
- gpath = null;
- }
-
-
- public void textureMode(int mode) {
- unavailableError("textureMode(mode)");
- }
-
-
- public void texture(PImage image) {
- unavailableError("texture(image)");
- }
-
-
- public void vertex(float x, float y) {
- splineVertexCount = 0;
- //float vertex[];
-
- if (vertexCount == vertices.length) {
- float temp[][] = new float[vertexCount<<1][VERTEX_FIELD_COUNT];
- System.arraycopy(vertices, 0, temp, 0, vertexCount);
- vertices = temp;
- //message(CHATTER, "allocating more vertices " + vertices.length);
- }
- // not everyone needs this, but just easier to store rather
- // than adding another moving part to the code...
- vertices[vertexCount][MX] = x;
- vertices[vertexCount][MY] = y;
- vertexCount++;
-
- switch (shape) {
-
- case POINTS:
- point(x, y);
- break;
-
- case LINES:
- if ((vertexCount % 2) == 0) {
- line(vertices[vertexCount-2][MX],
- vertices[vertexCount-2][MY], x, y);
- }
- break;
-
-/*
- case LINE_STRIP:
- case LINE_LOOP:
- if (gpath == null) {
- gpath = new GeneralPath();
- gpath.moveTo(x, y);
- } else {
- gpath.lineTo(x, y);
- }
- break;
-*/
-
- case TRIANGLES:
- if ((vertexCount % 3) == 0) {
- triangle(vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY],
- vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY],
- x, y);
- }
- break;
-
- case TRIANGLE_STRIP:
- if (vertexCount >= 3) {
- triangle(vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY],
- vertices[vertexCount - 1][MX],
- vertices[vertexCount - 1][MY],
- vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY]);
- }
- break;
-
- case TRIANGLE_FAN:
- if (vertexCount == 3) {
- triangle(vertices[0][MX], vertices[0][MY],
- vertices[1][MX], vertices[1][MY],
- x, y);
- } else if (vertexCount > 3) {
- gpath = new GeneralPath();
- // when vertexCount > 3, draw an un-closed triangle
- // for indices 0 (center), previous, current
- gpath.moveTo(vertices[0][MX],
- vertices[0][MY]);
- gpath.lineTo(vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY]);
- gpath.lineTo(x, y);
- draw_shape(gpath);
- }
- break;
-
- case QUADS:
- if ((vertexCount % 4) == 0) {
- quad(vertices[vertexCount - 4][MX],
- vertices[vertexCount - 4][MY],
- vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY],
- vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY],
- x, y);
- }
- break;
-
- case QUAD_STRIP:
- // 0---2---4
- // | | |
- // 1---3---5
- if ((vertexCount >= 4) && ((vertexCount % 2) == 0)) {
- quad(vertices[vertexCount - 4][MX],
- vertices[vertexCount - 4][MY],
- vertices[vertexCount - 2][MX],
- vertices[vertexCount - 2][MY],
- x, y,
- vertices[vertexCount - 3][MX],
- vertices[vertexCount - 3][MY]);
- }
- break;
-
- case POLYGON:
- if (gpath == null) {
- gpath = new GeneralPath();
- gpath.moveTo(x, y);
- } else if (breakShape) {
- gpath.moveTo(x, y);
- breakShape = false;
- } else {
- gpath.lineTo(x, y);
- }
- break;
- }
- }
-
-
- public void vertex(float x, float y, float u, float v) {
- unavailableError("vertex(x, y, u, v");
- }
-
-
- public void vertex(float x, float y, float z) {
- depthErrorXYZ("vertex");
- }
-
-
- public void vertex(float x, float y, float z, float u, float v) {
- depthErrorXYZ("vertex");
- }
-
-
- public void bezierVertex(float x1, float y1,
- float x2, float y2,
- float x3, float y3) {
- if (gpath == null) {
- throw new RuntimeException("Must call vertex() at least once " +
- "before using bezierVertex()");
- }
-
- switch (shape) {
- //case LINE_LOOP:
- //case LINE_STRIP:
- case POLYGON:
- gpath.curveTo(x1, y1, x2, y2, x3, y3);
- break;
-
- default:
- throw new RuntimeException("bezierVertex() can only be used with " +
- "LINE_STRIP, LINE_LOOP, or POLYGON");
- }
- }
-
-
- float curveX[] = new float[4];
- float curveY[] = new float[4];
-
- public void curveVertex(float x, float y) {
- //if ((shape != LINE_LOOP) && (shape != LINE_STRIP) && (shape != POLYGON)) {
- if (shape != POLYGON) {
- throw new RuntimeException("curveVertex() can only be used with " +
- "POLYGON shapes");
- //"LINE_LOOP, LINE_STRIP, and POLYGON shapes");
- }
-
- if (!curve_inited) curve_init();
- vertexCount = 0;
-
- if (splineVertices == null) {
- splineVertices = new float[DEFAULT_SPLINE_VERTICES][VERTEX_FIELD_COUNT];
- }
-
- // if more than 128 points, shift everything back to the beginning
- if (splineVertexCount == DEFAULT_SPLINE_VERTICES) {
- System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES - 3], 0,
- splineVertices[0], 0, VERTEX_FIELD_COUNT);
- System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES - 2], 0,
- splineVertices[1], 0, VERTEX_FIELD_COUNT);
- System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES - 1], 0,
- splineVertices[2], 0, VERTEX_FIELD_COUNT);
- splineVertexCount = 3;
- }
-
- // this new guy will be the fourth point (or higher),
- // which means it's time to draw segments of the curve
- if (splineVertexCount >= 3) {
- curveX[0] = splineVertices[splineVertexCount-3][MX];
- curveY[0] = splineVertices[splineVertexCount-3][MY];
-
- curveX[1] = splineVertices[splineVertexCount-2][MX];
- curveY[1] = splineVertices[splineVertexCount-2][MY];
-
- curveX[2] = splineVertices[splineVertexCount-1][MX];
- curveY[2] = splineVertices[splineVertexCount-1][MY];
-
- curveX[3] = x;
- curveY[3] = y;
-
- curveToBezierMatrix.mult(curveX, curveX);
- curveToBezierMatrix.mult(curveY, curveY);
-
- // since the paths are continuous,
- // only the first point needs the actual moveto
- if (gpath == null) {
- gpath = new GeneralPath();
- gpath.moveTo(curveX[0], curveY[0]);
- }
-
- gpath.curveTo(curveX[1], curveY[1],
- curveX[2], curveY[2],
- curveX[3], curveY[3]);
- }
-
- // add the current point to the list
- splineVertices[splineVertexCount][MX] = x;
- splineVertices[splineVertexCount][MY] = y;
- splineVertexCount++;
- }
-
-
- boolean breakShape;
- public void breakShape() {
- breakShape = true;
- }
-
-
- public void endShape(int mode) {
- if (gpath != null) { // make sure something has been drawn
- if (shape == POLYGON) {
- if (mode == CLOSE) {
- gpath.closePath();
- }
- draw_shape(gpath);
- }
- }
- shape = 0;
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
-
- /*
- protected void fillGradient(Paint paint) {
- fillGradient = true;
- fillGradientObject = paint;
- }
-
-
- protected void noFillGradient() {
- fillGradient = false;
- }
- */
-
-
- //////////////////////////////////////////////////////////////
-
-
- protected void fill_shape(Shape s) {
- if (fillGradient) {
- g2.setPaint(fillGradientObject);
- g2.fill(s);
- } else if (fill) {
- g2.setColor(fillColorObject);
- g2.fill(s);
- }
- }
-
- protected void stroke_shape(Shape s) {
- if (strokeGradient) {
- g2.setPaint(strokeGradientObject);
- g2.draw(s);
- } else if (stroke) {
- g2.setColor(strokeColorObject);
- g2.draw(s);
- }
- }
-
- protected void draw_shape(Shape s) {
- if (fillGradient) {
- g2.setPaint(fillGradientObject);
- g2.fill(s);
- } else if (fill) {
- g2.setColor(fillColorObject);
- g2.fill(s);
- }
- if (strokeGradient) {
- g2.setPaint(strokeGradientObject);
- g2.draw(s);
- } else if (stroke) {
- g2.setColor(strokeColorObject);
- g2.draw(s);
- }
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void point(float x, float y) {
- line(x, y, x, y);
- }
-
-
- public void line(float x1, float y1, float x2, float y2) {
- //graphics.setColor(strokeColorObject);
- //graphics.drawLine(x1, y1, x2, y2);
- line.setLine(x1, y1, x2, y2);
- stroke_shape(line);
- }
-
-
- public void triangle(float x1, float y1, float x2, float y2,
- float x3, float y3) {
- gpath = new GeneralPath();
- gpath.moveTo(x1, y1);
- gpath.lineTo(x2, y2);
- gpath.lineTo(x3, y3);
- gpath.closePath();
-
- draw_shape(gpath);
- }
-
-
- public void quad(float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4) {
- GeneralPath gp = new GeneralPath();
- gp.moveTo(x1, y1);
- gp.lineTo(x2, y2);
- gp.lineTo(x3, y3);
- gp.lineTo(x4, y4);
- gp.closePath();
-
- draw_shape(gp);
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- protected void rectImpl(float x1, float y1, float x2, float y2) {
- rect.setFrame(x1, y1, x2-x1, y2-y1);
- draw_shape(rect);
- }
-
-
- protected void ellipseImpl(float x, float y, float w, float h) {
- ellipse.setFrame(x, y, w, h);
- draw_shape(ellipse);
- }
-
-
- protected void arcImpl(float x, float y, float w, float h,
- float start, float stop) {
- // 0 to 90 in java would be 0 to -90 for p5 renderer
- // but that won't work, so -90 to 0?
-
- if (stop - start >= TWO_PI) {
- start = 0;
- stop = 360;
-
- } else {
- start = -start * RAD_TO_DEG;
- stop = -stop * RAD_TO_DEG;
-
- // ok to do this because already checked for NaN
- while (start < 0) {
- start += 360;
- stop += 360;
- }
- if (start > stop) {
- float temp = start;
- start = stop;
- stop = temp;
- }
- }
- float span = stop - start;
-
- // stroke as Arc2D.OPEN, fill as Arc2D.PIE
- if (fill) {
- //System.out.println("filla");
- arc.setArc(x, y, w, h, start, span, Arc2D.PIE);
- fill_shape(arc);
- }
- if (stroke) {
- //System.out.println("strokey");
- arc.setArc(x, y, w, h, start, span, Arc2D.OPEN);
- stroke_shape(arc);
- }
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- /** Ignored (not needed) in Java 2D. */
- public void bezierDetail(int detail) {
- }
-
-
- /** Ignored (not needed) in Java 2D. */
- public void curveDetail(int detail) {
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- /**
- * Handle renderer-specific image drawing.
- */
- protected void imageImpl(PImage who,
- float x1, float y1, float x2, float y2,
- int u1, int v1, int u2, int v2) {
- if (who.cache != null) {
- if (!(who.cache instanceof ImageCache)) {
- // this cache belongs to another renderer.. fix me later,
- // because this is gonna make drawing *really* inefficient
- //who.cache = null;
- }
- }
-
- if (who.cache == null) {
- //System.out.println("making new image cache");
- who.cache = new ImageCache(who);
- who.updatePixels(); // mark the whole thing for update
- who.modified = true;
- }
-
- ImageCache cash = (ImageCache) who.cache;
- // if image previously was tinted, or the color changed
- // or the image was tinted, and tint is now disabled
- if ((tint && !cash.tinted) ||
- (tint && (cash.tintedColor != tintColor)) ||
- (!tint && cash.tinted)) {
- // for tint change, mark all pixels as needing update
- who.updatePixels();
- }
-
- if (who.modified) {
- cash.update(tint, tintColor);
- who.modified = false;
- }
-
- g2.drawImage(((ImageCache) who.cache).image,
- (int) x1, (int) y1, (int) x2, (int) y2,
- u1, v1, u2, v2, null);
- }
-
-
- class ImageCache {
- PImage source;
- boolean tinted;
- int tintedColor;
- int tintedPixels[];
- BufferedImage image;
-
- public ImageCache(PImage source) {
- this.source = source;
- // even if RGB, set the image type to ARGB, because the
- // image may have an alpha value for its tint().
- int type = BufferedImage.TYPE_INT_ARGB;
- //System.out.println("making new buffered image");
- image = new BufferedImage(source.width, source.height, type);
- }
-
- // for rev 0124, passing the tintColor in here. the problem is that
- // the 'parent' PGraphics object of this inner class may not be
- // the same one that's used when drawing. for instance, if this
- // is a font used by the main drawing surface, then it's later
- // used in an offscreen PGraphics, the tintColor value from the
- // original PGraphics will be used.
- public void update(boolean tint, int tintColor) {
- if (tintedPixels == null) {
- //System.out.println("tinted pixels null");
- tintedPixels = new int[source.width * source.height];
- }
-
- if ((source.format == ARGB) || (source.format == RGB)) {
- if (tint) {
- // create tintedPixels[] if necessary
- //if (tintedPixels == null) {
- // tintedPixels = new int[source.width * source.height];
- //}
-
- int a2 = (tintColor >> 24) & 0xff;
- int r2 = (tintColor >> 16) & 0xff;
- int g2 = (tintColor >> 8) & 0xff;
- int b2 = (tintColor) & 0xff;
-
- // multiply each of the color components into tintedPixels
- // if straight RGB image, don't bother multiplying
- // (also avoids problems if high bits not set)
- if (source.format == RGB) {
- int alpha = a2 << 24;
-
- for (int i = 0; i < tintedPixels.length; i++) {
- int argb1 = source.pixels[i];
- int r1 = (argb1 >> 16) & 0xff;
- int g1 = (argb1 >> 8) & 0xff;
- int b1 = (argb1) & 0xff;
-
- tintedPixels[i] = alpha |
- (((r2 * r1) & 0xff00) << 8) |
- ((g2 * g1) & 0xff00) |
- (((b2 * b1) & 0xff00) >> 8);
- }
-
- } else {
- for (int i = 0; i < tintedPixels.length; i++) {
- int argb1 = source.pixels[i];
- int a1 = (argb1 >> 24) & 0xff;
- int r1 = (argb1 >> 16) & 0xff;
- int g1 = (argb1 >> 8) & 0xff;
- int b1 = (argb1) & 0xff;
-
- tintedPixels[i] =
- (((a2 * a1) & 0xff00) << 16) |
- (((r2 * r1) & 0xff00) << 8) |
- ((g2 * g1) & 0xff00) |
- (((b2 * b1) & 0xff00) >> 8);
- }
- }
-
- tinted = true;
- tintedColor = tintColor;
-
- // finally, do a setRGB based on tintedPixels
- //image.setRGB(0, 0, source.width, source.height,
- // tintedPixels, 0, source.width);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.setDataElements(0, 0, source.width, source.height,
- tintedPixels);
-
- } else { // no tint
- // just do a setRGB like before
- // (and we'll just hope that the high bits are set)
- //image.setRGB(0, 0, source.width, source.height,
- // source.pixels, 0, source.width);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.setDataElements(0, 0, source.width, source.height,
- source.pixels);
- }
-
- } else if (source.format == ALPHA) {
- int lowbits = tintColor & 0x00ffffff;
- if (((tintColor >> 24) & 0xff) >= 254) {
- //PApplet.println(" no alfa " + PApplet.hex(tintColor));
- // no actual alpha to the tint, set the image's alpha
- // as the high 8 bits, and use the color as the low 24 bits
- for (int i = 0; i < tintedPixels.length; i++) {
- // don't bother with the math if value is zero
- tintedPixels[i] = (source.pixels[i] == 0) ?
- 0 : (source.pixels[i] << 24) | lowbits;
- }
-
- } else {
- //PApplet.println(" yes alfa " + PApplet.hex(tintColor));
- // multiply each image alpha by the tint alpha
- int alphabits = (tintColor >> 24) & 0xff;
- for (int i = 0; i < tintedPixels.length; i++) {
- tintedPixels[i] = (source.pixels[i] == 0) ?
- 0 : (((alphabits * source.pixels[i]) & 0xFF00) << 16) | lowbits;
- }
- }
-
- // mark the pixels for next time
- tinted = true;
- tintedColor = tintColor;
-
- // finally, do a setRGB based on tintedPixels
- //image.setRGB(0, 0, source.width, source.height,
- // tintedPixels, 0, source.width);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.setDataElements(0, 0, source.width, source.height, tintedPixels);
- }
- }
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public float textAscent() {
- if (textFontNative == null) {
- return super.textAscent();
- }
- return textFontNativeMetrics.getAscent();
- }
-
-
- public float textDescent() {
- if (textFontNative == null) {
- return super.textDescent();
- }
- return textFontNativeMetrics.getDescent();
- }
-
-
- /**
- * Same as parent, but override for native version of the font.
- *
- * Also gets called by textFont, so the metrics
- * will get recorded properly.
- */
- public void textSize(float size) {
- // if a native version available, subset this font
- if (textFontNative != null) {
- textFontNative = textFontNative.deriveFont(size);
- g2.setFont(textFontNative);
- textFontNativeMetrics = g2.getFontMetrics(textFontNative);
- }
-
- // take care of setting the textSize and textLeading vars
- // this has to happen second, because it calls textAscent()
- // (which requires the native font metrics to be set)
- super.textSize(size);
- }
-
-
- protected float textWidthImpl(char buffer[], int start, int stop) {
- if (textFontNative == null) {
- //System.out.println("native is null");
- return super.textWidthImpl(buffer, start, stop);
- }
- // maybe should use one of the newer/fancier functions for this?
- int length = stop - start;
- return textFontNativeMetrics.charsWidth(buffer, start, length);
- }
-
-
- protected void textLinePlacedImpl(char buffer[], int start, int stop,
- float x, float y) {
- if (textFontNative == null) {
- super.textLinePlacedImpl(buffer, start, stop, x, y);
- return;
- }
-
- /*
- // save the current setting for text smoothing. note that this is
- // different from the smooth() function, because the font smoothing
- // is controlled when the font is created, not now as it's drawn.
- // fixed a bug in 0116 that handled this incorrectly.
- Object textAntialias =
- g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
-
- // override the current text smoothing setting based on the font
- // (don't change the global smoothing settings)
- g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- textFont.smooth ?
- RenderingHints.VALUE_ANTIALIAS_ON :
- RenderingHints.VALUE_ANTIALIAS_OFF);
- */
-
- Object antialias =
- g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
- if (antialias == null) {
- // if smooth() and noSmooth() not called, this will be null (0120)
- antialias = RenderingHints.VALUE_ANTIALIAS_DEFAULT;
- }
-
- // override the current smoothing setting based on the font
- // also changes global setting for antialiasing, but this is because it's
- // not possible to enable/disable them independently in some situations.
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- textFont.smooth ?
- RenderingHints.VALUE_ANTIALIAS_ON :
- RenderingHints.VALUE_ANTIALIAS_OFF);
-
-
- g2.setColor(fillColorObject);
- // better to use drawString(float, float)?
- int length = stop - start;
- g2.drawChars(buffer, start, length, (int) (x + 0.5f), (int) (y + 0.5f));
-
- // this didn't seem to help the scaling issue
- // and creates garbage because of the new temporary object
- //java.awt.font.GlyphVector gv = textFontNative.createGlyphVector(g2.getFontRenderContext(), new String(buffer, start, stop));
- //g2.drawGlyphVector(gv, x, y);
-
- // return to previous smoothing state if it was changed
- //g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, textAntialias);
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialias);
-
- textX = x + textWidthImpl(buffer, start, stop);
- textY = y;
- textZ = 0; // this will get set by the caller if non-zero
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void translate(float tx, float ty) {
- g2.translate(tx, ty);
- }
-
-
- public void rotate(float angle) {
- g2.rotate(angle);
- }
-
-
- public void scale(float s) {
- g2.scale(s, s);
- }
-
-
- public void scale(float sx, float sy) {
- g2.scale(sx, sy);
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void pushMatrix() {
- if (transformCount == transformStack.length) {
- throw new RuntimeException("pushMatrix() cannot use push more than " +
- transformStack.length + " times");
- }
- transformStack[transformCount] = g2.getTransform();
- transformCount++;
- }
-
-
- public void popMatrix() {
- if (transformCount == 0) {
- throw new RuntimeException("missing a popMatrix() " +
- "to go with that pushMatrix()");
- }
- transformCount--;
- g2.setTransform(transformStack[transformCount]);
- }
-
-
- public void resetMatrix() {
- g2.setTransform(new AffineTransform());
- }
-
-
- public void applyMatrix(float n00, float n01, float n02,
- float n10, float n11, float n12) {
- g2.transform(new AffineTransform(n00, n10, n01, n11, n02, n12));
- }
-
-
- public void loadMatrix() {
- g2.getTransform().getMatrix(transform);
-
- m00 = (float) transform[0];
- m01 = (float) transform[2];
- m02 = (float) transform[4];
-
- m10 = (float) transform[1];
- m11 = (float) transform[3];
- m12 = (float) transform[5];
- }
-
-
- public float screenX(float x, float y) {
- loadMatrix();
- return super.screenX(x, y);
- //g2.getTransform().getMatrix(transform);
- //return (float)transform[0]*x + (float)transform[2]*y + (float)transform[4];
- }
-
-
- public float screenY(float x, float y) {
- loadMatrix();
- return super.screenY(x, y);
- //g2.getTransform().getMatrix(transform);
- //return (float)transform[1]*x + (float)transform[3]*y + (float)transform[5];
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- protected void tintFromCalc() {
- super.tintFromCalc();
- // TODO actually implement tinted images
- tintColorObject = new Color(tintColor, true);
- }
-
- protected void fillFromCalc() {
- super.fillFromCalc();
- fillColorObject = new Color(fillColor, true);
- fillGradient = false;
- }
-
- protected void strokeFromCalc() {
- super.strokeFromCalc();
- strokeColorObject = new Color(strokeColor, true);
- strokeGradient = false;
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void strokeWeight(float weight) {
- super.strokeWeight(weight);
- set_stroke();
- }
-
-
- public void strokeJoin(int join) {
- super.strokeJoin(join);
- set_stroke();
- }
-
-
- public void strokeCap(int cap) {
- super.strokeCap(cap);
- set_stroke();
- }
-
-
- protected void set_stroke() {
- int cap = BasicStroke.CAP_BUTT;
- if (strokeCap == ROUND) {
- cap = BasicStroke.CAP_ROUND;
- } else if (strokeCap == PROJECT) {
- cap = BasicStroke.CAP_SQUARE;
- }
-
- int join = BasicStroke.JOIN_BEVEL;
- if (strokeJoin == MITER) {
- join = BasicStroke.JOIN_MITER;
- } else if (strokeJoin == ROUND) {
- join = BasicStroke.JOIN_ROUND;
- }
-
- g2.setStroke(new BasicStroke(strokeWeight, cap, join));
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void background(PImage image) {
- if ((image.width != width) || (image.height != height)) {
- throw new RuntimeException("background image must be " +
- "the same size as your application");
- }
- if ((image.format != RGB) && (image.format != ARGB)) {
- throw new RuntimeException("background images should be RGB or ARGB");
- }
- // draw the image to screen without any transformations
- set(0, 0, image);
- }
-
-
- int[] clearPixels;
-
- public void clear() {
- // the only way to properly clear the screen is to re-allocate
- if (backgroundAlpha) {
- // clearRect() doesn't work because it just makes everything black.
- // instead, just wipe out the canvas to its transparent original
- //allocate();
-
- // allocate also won't work, because all the settings
- // (like smooth) will be completely reset.
- // Instead, create a small array that can be used to set the pixels
- // several times. Using a single-pixel line of length 'width' is a
- // tradeoff between speed (setting each pixel individually is too slow)
- // and memory (an array for width*height would waste lots of memory
- // if it stayed resident, and would terrify the gc if it were
- // re-created on each trip to background().
- WritableRaster raster = ((BufferedImage) image).getRaster();
- if ((clearPixels == null) || (clearPixels.length < width)) {
- clearPixels = new int[width];
- }
- for (int i = 0; i < width; i++) {
- clearPixels[i] = backgroundColor;
- }
- for (int i = 0; i < height; i++) {
- raster.setDataElements(0, i, width, 1, clearPixels);
- }
- } else {
- // in case people do transformations before background(),
- // need to handle this with a push/reset/pop
- pushMatrix();
- resetMatrix();
- g2.setColor(new Color(backgroundColor, backgroundAlpha));
- g2.fillRect(0, 0, width, height);
- popMatrix();
- }
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
- // FROM PIMAGE
-
-
- public void smooth() {
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_BICUBIC);
- }
-
-
- public void noSmooth() {
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_OFF);
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
- }
-
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void beginRaw(PGraphics recorderRaw) {
- throw new RuntimeException("beginRaw() not available with this renderer");
- }
-
-
- public void endRaw() {
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void loadPixels() {
- if ((pixels == null) || (pixels.length != width * height)) {
- pixels = new int[width * height];
- }
- //((BufferedImage) image).getRGB(0, 0, width, height, pixels, 0, width);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.getDataElements(0, 0, width, height, pixels);
- }
-
-
- /**
- * Update the pixels[] buffer to the PGraphics image.
- *
- * Unlike in PImage, where updatePixels() only requests that the
- * update happens, in PGraphicsJava2D, this will happen immediately.
- */
- public void updatePixels() {
- //updatePixels(0, 0, width, height);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.setDataElements(0, 0, width, height, pixels);
- }
-
-
- /**
- * Update the pixels[] buffer to the PGraphics image.
- *
- * Unlike in PImage, where updatePixels() only requests that the
- * update happens, in PGraphicsJava2D, this will happen immediately.
- */
- public void updatePixels(int x, int y, int c, int d) {
- if ((x == 0) && (y == 0) && (c == width) && (d == height)) {
- updatePixels();
- } else {
- throw new RuntimeException("updatePixels(x, y, c, d) not implemented");
- }
- /*
- ((BufferedImage) image).setRGB(x, y,
- (imageMode == CORNER) ? c : (c - x),
- (imageMode == CORNER) ? d : (d - y),
- pixels, 0, width);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.setDataElements(x, y,
- (imageMode == CORNER) ? c : (c - x),
- (imageMode == CORNER) ? d : (d - y),
- pixels);
- */
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- static int getset[] = new int[1];
-
-
- public int get(int x, int y) {
- if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0;
- //return ((BufferedImage) image).getRGB(x, y);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.getDataElements(x, y, getset);
- return getset[0];
- }
-
-
- public PImage get(int x, int y, int w, int h) {
- if (imageMode == CORNERS) { // if CORNER, do nothing
- // w/h are x2/y2 in this case, bring em down to size
- w = (w - x);
- h = (h - x);
- }
-
- if (x < 0) {
- w += x; // clip off the left edge
- x = 0;
- }
- if (y < 0) {
- h += y; // clip off some of the height
- y = 0;
- }
-
- if (x + w > width) w = width - x;
- if (y + h > height) h = height - y;
-
- PImage output = new PImage(w, h);
- output.parent = parent;
-
- // oops, the last parameter is the scan size of the *target* buffer
- //((BufferedImage) image).getRGB(x, y, w, h, output.pixels, 0, w);
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.getDataElements(x, y, w, h, output.pixels);
-
- return output;
- }
-
-
- /**
- * Grab a copy of the current pixel buffer.
- */
- public PImage get() {
- /*
- PImage outgoing = new PImage(width, height);
- ((BufferedImage) image).getRGB(0, 0, width, height,
- outgoing.pixels, 0, width);
- return outgoing;
- */
- return get(0, 0, width, height);
- }
-
-
- public void set(int x, int y, int argb) {
- if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return;
- //((BufferedImage) image).setRGB(x, y, argb);
- getset[0] = argb;
- WritableRaster raster = ((BufferedImage) image).getRaster();
- raster.setDataElements(x, y, getset);
- }
-
-
- protected void setImpl(int dx, int dy, int sx, int sy, int sw, int sh,
- PImage src) {
- WritableRaster raster = ((BufferedImage) image).getRaster();
- if ((sx == 0) && (sy == 0) && (sw == src.width) && (sh == src.height)) {
- raster.setDataElements(dx, dy, src.width, src.height, src.pixels);
- } else {
- int mode = src.imageMode;
- src.imageMode = CORNER;
- // TODO Optimize, incredibly inefficient to reallocate this much memory
- PImage temp = src.get(sx, sy, sw, sh);
- src.imageMode = mode;
- raster.setDataElements(dx, dy, temp.width, temp.height, temp.pixels);
- }
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void mask(int alpha[]) {
- throw new RuntimeException("mask() cannot be used with JAVA2D");
- }
-
-
- public void mask(PImage alpha) {
- throw new RuntimeException("mask() cannot be used with JAVA2D");
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void filter(int kind) {
- loadPixels();
- super.filter(kind);
- updatePixels();
- }
-
-
- public void filter(int kind, float param) {
- loadPixels();
- super.filter(kind, param);
- updatePixels();
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void copy(int sx, int sy, int sw, int sh,
- int dx, int dy, int dw, int dh) {
- if ((sw != dw) || (sh != dh)) {
- // use slow version if changing size
- copy(this, sx, sy, sw, sh, dx, dy, dw, dh);
-
- } else {
- if (imageMode == CORNERS) {
- sw -= sx;
- sh -= sy;
- }
- dx = dx - sx; // java2d's "dx" is the delta, not dest
- dy = dy - sy;
- g2.copyArea(sx, sy, sw, sh, dx, dy);
- }
- }
-
-
- public void copy(PImage src,
- int sx1, int sy1, int sx2, int sy2,
- int dx1, int dy1, int dx2, int dy2) {
- loadPixels();
- super.copy(src, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
- updatePixels();
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- /*
- public void blend(PImage src, int sx, int sy, int dx, int dy, int mode) {
- loadPixels();
- super.blend(src, sx, sy, dx, dy, mode);
- updatePixels();
- }
-
-
- public void blend(int sx, int sy, int dx, int dy, int mode) {
- loadPixels();
- super.blend(sx, sy, dx, dy, mode);
- updatePixels();
- }
- */
-
-
- public void blend(int sx1, int sy1, int sx2, int sy2,
- int dx1, int dy1, int dx2, int dy2, int mode) {
- loadPixels();
- super.blend(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2, mode);
- updatePixels();
- }
-
-
- public void blend(PImage src, int sx1, int sy1, int sx2, int sy2,
- int dx1, int dy1, int dx2, int dy2, int mode) {
- loadPixels();
- super.blend(src, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2, mode);
- updatePixels();
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void save(String filename) {
- //System.out.println("start load");
- loadPixels();
- //System.out.println("end load, start save");
- super.save(filename);
- //System.out.println("done with save");
- }
-}
diff --git a/core/PMatrix.java b/core/PMatrix.java
deleted file mode 100644
index 9b19da613..000000000
--- a/core/PMatrix.java
+++ /dev/null
@@ -1,640 +0,0 @@
-/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://Proce55ing.net
-
- Copyright (c) 2005-06 Ben Fry and Casey Reas
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-*/
-
-package processing.core;
-
-
-/**
- * 4x4 matrix implementation.
- */
-public final class PMatrix implements PConstants {
-
- public float m00, m01, m02, m03;
- public float m10, m11, m12, m13;
- public float m20, m21, m22, m23;
- public float m30, m31, m32, m33;
-
- final static int DEFAULT_STACK_DEPTH = 0;
- int maxStackDepth;
- int stackPointer = 0;
- float stack[][];
-
-
- // locally allocated version to avoid creating new memory
- static protected PMatrix inverseCopy;
-
-
- public PMatrix() {
- set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- maxStackDepth = DEFAULT_STACK_DEPTH;
- }
-
-
- public PMatrix(int stackDepth) {
- set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- stack = new float[stackDepth][16];
- maxStackDepth = stackDepth;
- }
-
-
- public PMatrix(float m00, float m01, float m02, float m03,
- float m10, float m11, float m12, float m13,
- float m20, float m21, float m22, float m23,
- float m30, float m31, float m32, float m33) {
- set(m00, m01, m02, m03,
- m10, m11, m12, m13,
- m20, m21, m22, m23,
- m30, m31, m32, m33);
- maxStackDepth = DEFAULT_STACK_DEPTH;
- }
-
-
- // Make a copy of a matrix. We copy the stack depth,
- // but we don't make a copy of the stack or the stack pointer.
- public PMatrix(PMatrix src) {
- set(src);
- maxStackDepth = src.maxStackDepth;
- stack = new float[maxStackDepth][16];
- }
-
-
- public void reset() {
- set(1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
- }
-
-
- public void clearStack() {
- stackPointer = 0;
- }
-
-
- public boolean push() {
- if (stackPointer == maxStackDepth) return false;
-
- stack[stackPointer][0] = m00;
- stack[stackPointer][1] = m01;
- stack[stackPointer][2] = m02;
- stack[stackPointer][3] = m03;
-
- stack[stackPointer][4] = m10;
- stack[stackPointer][5] = m11;
- stack[stackPointer][6] = m12;
- stack[stackPointer][7] = m13;
-
- stack[stackPointer][8] = m20;
- stack[stackPointer][9] = m21;
- stack[stackPointer][10] = m22;
- stack[stackPointer][11] = m23;
-
- stack[stackPointer][12] = m30;
- stack[stackPointer][13] = m31;
- stack[stackPointer][14] = m32;
- stack[stackPointer][15] = m33;
-
- stackPointer++;
- return true;
- }
-
-
- public boolean pop() {
- if (stackPointer == 0) return false;
- stackPointer--;
-
- m00 = stack[stackPointer][0];
- m01 = stack[stackPointer][1];
- m02 = stack[stackPointer][2];
- m03 = stack[stackPointer][3];
-
- m10 = stack[stackPointer][4];
- m11 = stack[stackPointer][5];
- m12 = stack[stackPointer][6];
- m13 = stack[stackPointer][7];
-
- m20 = stack[stackPointer][8];
- m21 = stack[stackPointer][9];
- m22 = stack[stackPointer][10];
- m23 = stack[stackPointer][11];
-
- m30 = stack[stackPointer][12];
- m31 = stack[stackPointer][13];
- m32 = stack[stackPointer][14];
- m33 = stack[stackPointer][15];
-
- return true;
- }
-
-
- public void set(PMatrix src) {
- set(src.m00, src.m01, src.m02, src.m03,
- src.m10, src.m11, src.m12, src.m13,
- src.m20, src.m21, src.m22, src.m23,
- src.m30, src.m31, src.m32, src.m33);
- }
-
-
- public void set(float m00, float m01, float m02, float m03,
- float m10, float m11, float m12, float m13,
- float m20, float m21, float m22, float m23,
- float m30, float m31, float m32, float m33) {
- this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
- this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
- this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
- this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
- }
-
-
- public void translate(float tx, float ty) {
- translate(tx, ty, 0);
- }
-
- public void invTranslate(float tx, float ty) {
- invTranslate(tx, ty, 0);
- }
-
-
- public void translate(float tx, float ty, float tz) {
- m03 += tx*m00 + ty*m01 + tz*m02;
- m13 += tx*m10 + ty*m11 + tz*m12;
- m23 += tx*m20 + ty*m21 + tz*m22;
- m33 += tx*m30 + ty*m31 + tz*m32;
- }
-
- public void invTranslate(float tx, float ty, float tz) {
- preApply(1, 0, 0, -tx,
- 0, 1, 0, -ty,
- 0, 0, 1, -tz,
- 0, 0, 0, 1);
- }
-
-
- // OPT could save several multiplies for the 0s and 1s by just
- // putting the multMatrix code here and removing uneccessary terms
-
- public void rotateX(float angle) {
- float c = cos(angle);
- float s = sin(angle);
- apply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
- }
-
-
- public void invRotateX(float angle) {
- float c = cos(-angle);
- float s = sin(-angle);
- preApply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
- }
-
-
- public void rotateY(float angle) {
- float c = cos(angle);
- float s = sin(angle);
- apply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
- }
-
-
- public void invRotateY(float angle) {
- float c = cos(-angle);
- float s = sin(-angle);
- preApply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
- }
-
-
- /**
- * Just calls rotateZ because two dimensional rotation
- * is the same as rotating along the z-axis.
- */
- public void rotate(float angle) {
- rotateZ(angle);
- }
-
-
- public void invRotate(float angle) {
- invRotateZ(angle);
- }
-
-
- public void rotateZ(float angle) {
- float c = cos(angle);
- float s = sin(angle);
- apply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- }
-
-
- public void invRotateZ(float angle) {
- float c = cos(-angle);
- float s = sin(-angle);
- preApply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- }
-
-
- public void rotate(float angle, float v0, float v1, float v2) {
- // should be in radians (i think), instead of degrees (gl uses degrees)
- // based on 15-463 code, but similar to opengl ref p.443
-
- // TODO should make sure this vector is normalized
-
- float c = cos(angle);
- float s = sin(angle);
- float t = 1.0f - c;
-
- apply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0,
- (t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0,
- (t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0,
- 0, 0, 0, 1);
- }
-
-
- public void invRotate(float angle, float v0, float v1, float v2) {
- // TODO should make sure this vector is normalized
-
- float c = cos(-angle);
- float s = sin(-angle);
- float t = 1.0f - c;
-
- preApply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0,
- (t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0,
- (t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0,
- 0, 0, 0, 1);
- }
-
-
- public void scale(float s) {
- apply(s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1);
- }
-
-
- public void invScale(float s) {
- preApply(1/s, 0, 0, 0, 0, 1/s, 0, 0, 0, 0, 1/s, 0, 0, 0, 0, 1);
- }
-
-
- public void scale(float sx, float sy) {
- apply(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- }
-
-
- public void invScale(float sx, float sy) {
- preApply(1/sx, 0, 0, 0, 0, 1/sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- }
-
-
- // OPTIMIZE: same as above
- public void scale(float x, float y, float z) {
- apply(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1);
- }
-
-
- public void invScale(float x, float y, float z) {
- preApply(1/x, 0, 0, 0, 0, 1/y, 0, 0, 0, 0, 1/z, 0, 0, 0, 0, 1);
- }
-
-
- /*
- public void transform(float n00, float n01, float n02, float n03,
- float n10, float n11, float n12, float n13,
- float n20, float n21, float n22, float n23,
- float n30, float n31, float n32, float n33) {
- apply(n00, n01, n02, n03,
- n10, n11, n12, n13,
- n20, n21, n22, n23,
- n30, n31, n32, n33);
- }
- */
-
-
- public void preApply(PMatrix lhs) {
- preApply(lhs.m00, lhs.m01, lhs.m02, lhs.m03,
- lhs.m10, lhs.m11, lhs.m12, lhs.m13,
- lhs.m20, lhs.m21, lhs.m22, lhs.m23,
- lhs.m30, lhs.m31, lhs.m32, lhs.m33);
- }
-
-
- // for inverse operations, like multiplying the matrix on the left
- public void preApply(float n00, float n01, float n02, float n03,
- float n10, float n11, float n12, float n13,
- float n20, float n21, float n22, float n23,
- float n30, float n31, float n32, float n33) {
-
- float r00 = n00*m00 + n01*m10 + n02*m20 + n03*m30;
- float r01 = n00*m01 + n01*m11 + n02*m21 + n03*m31;
- float r02 = n00*m02 + n01*m12 + n02*m22 + n03*m32;
- float r03 = n00*m03 + n01*m13 + n02*m23 + n03*m33;
-
- float r10 = n10*m00 + n11*m10 + n12*m20 + n13*m30;
- float r11 = n10*m01 + n11*m11 + n12*m21 + n13*m31;
- float r12 = n10*m02 + n11*m12 + n12*m22 + n13*m32;
- float r13 = n10*m03 + n11*m13 + n12*m23 + n13*m33;
-
- float r20 = n20*m00 + n21*m10 + n22*m20 + n23*m30;
- float r21 = n20*m01 + n21*m11 + n22*m21 + n23*m31;
- float r22 = n20*m02 + n21*m12 + n22*m22 + n23*m32;
- float r23 = n20*m03 + n21*m13 + n22*m23 + n23*m33;
-
- float r30 = n30*m00 + n31*m10 + n32*m20 + n33*m30;
- float r31 = n30*m01 + n31*m11 + n32*m21 + n33*m31;
- float r32 = n30*m02 + n31*m12 + n32*m22 + n33*m32;
- float r33 = n30*m03 + n31*m13 + n32*m23 + n33*m33;
-
- m00 = r00; m01 = r01; m02 = r02; m03 = r03;
- m10 = r10; m11 = r11; m12 = r12; m13 = r13;
- m20 = r20; m21 = r21; m22 = r22; m23 = r23;
- m30 = r30; m31 = r31; m32 = r32; m33 = r33;
- }
-
-
- public boolean invApply(PMatrix rhs) {
- PMatrix copy = new PMatrix(rhs);
- PMatrix inverse = copy.invert();
- if (inverse == null) return false;
- preApply(inverse);
- return true;
- }
-
-
- public boolean invApply(float n00, float n01, float n02, float n03,
- float n10, float n11, float n12, float n13,
- float n20, float n21, float n22, float n23,
- float n30, float n31, float n32, float n33) {
- if (inverseCopy == null) {
- inverseCopy = new PMatrix();
- }
- inverseCopy.set(n00, n01, n02, n03,
- n10, n11, n12, n13,
- n20, n21, n22, n23,
- n30, n31, n32, n33);
- PMatrix inverse = inverseCopy.invert();
- if (inverse == null) return false;
- preApply(inverse);
- return true;
- }
-
-
- public void apply(PMatrix rhs) {
- apply(rhs.m00, rhs.m01, rhs.m02, rhs.m03,
- rhs.m10, rhs.m11, rhs.m12, rhs.m13,
- rhs.m20, rhs.m21, rhs.m22, rhs.m23,
- rhs.m30, rhs.m31, rhs.m32, rhs.m33);
- }
-
-
- public void apply(float n00, float n01, float n02, float n03,
- float n10, float n11, float n12, float n13,
- float n20, float n21, float n22, float n23,
- float n30, float n31, float n32, float n33) {
-
- float r00 = m00*n00 + m01*n10 + m02*n20 + m03*n30;
- float r01 = m00*n01 + m01*n11 + m02*n21 + m03*n31;
- float r02 = m00*n02 + m01*n12 + m02*n22 + m03*n32;
- float r03 = m00*n03 + m01*n13 + m02*n23 + m03*n33;
-
- float r10 = m10*n00 + m11*n10 + m12*n20 + m13*n30;
- float r11 = m10*n01 + m11*n11 + m12*n21 + m13*n31;
- float r12 = m10*n02 + m11*n12 + m12*n22 + m13*n32;
- float r13 = m10*n03 + m11*n13 + m12*n23 + m13*n33;
-
- float r20 = m20*n00 + m21*n10 + m22*n20 + m23*n30;
- float r21 = m20*n01 + m21*n11 + m22*n21 + m23*n31;
- float r22 = m20*n02 + m21*n12 + m22*n22 + m23*n32;
- float r23 = m20*n03 + m21*n13 + m22*n23 + m23*n33;
-
- float r30 = m30*n00 + m31*n10 + m32*n20 + m33*n30;
- float r31 = m30*n01 + m31*n11 + m32*n21 + m33*n31;
- float r32 = m30*n02 + m31*n12 + m32*n22 + m33*n32;
- float r33 = m30*n03 + m31*n13 + m32*n23 + m33*n33;
-
- m00 = r00; m01 = r01; m02 = r02; m03 = r03;
- m10 = r10; m11 = r11; m12 = r12; m13 = r13;
- m20 = r20; m21 = r21; m22 = r22; m23 = r23;
- m30 = r30; m31 = r31; m32 = r32; m33 = r33;
- }
-
-
- public void mult3(float vec[], float out[]) {
- // must use these temp vars because vec may be the same as out
- float tmpx = m00*vec[0] + m01*vec[1] + m02*vec[2] + m03;
- float tmpy = m10*vec[0] + m11*vec[1] + m12*vec[2] + m13;
- float tmpz = m20*vec[0] + m21*vec[1] + m22*vec[2] + m23;
-
- out[0] = tmpx;
- out[1] = tmpy;
- out[2] = tmpz;
- }
-
-
- public void mult(float vec[], float out[]) {
- // must use these temp vars because vec may be the same as out
- float tmpx = m00*vec[0] + m01*vec[1] + m02*vec[2] + m03*vec[3];
- float tmpy = m10*vec[0] + m11*vec[1] + m12*vec[2] + m13*vec[3];
- float tmpz = m20*vec[0] + m21*vec[1] + m22*vec[2] + m23*vec[3];
- float tmpw = m30*vec[0] + m31*vec[1] + m32*vec[2] + m33*vec[3];
-
- out[0] = tmpx;
- out[1] = tmpy;
- out[2] = tmpz;
- out[3] = tmpw;
- }
-
-
- /**
- * @return the determinant of the matrix
- */
- public float determinant() {
- float f =
- m00
- * ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32)
- - m13 * m22 * m31
- - m11 * m23 * m32
- - m12 * m21 * m33);
- f -= m01
- * ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32)
- - m13 * m22 * m30
- - m10 * m23 * m32
- - m12 * m20 * m33);
- f += m02
- * ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31)
- - m13 * m21 * m30
- - m10 * m23 * m31
- - m11 * m20 * m33);
- f -= m03
- * ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31)
- - m12 * m21 * m30
- - m10 * m22 * m31
- - m11 * m20 * m32);
- return f;
- }
-
-
- /**
- * Calculate the determinant of a 3x3 matrix
- * @return result
- */
- private float determinant3x3(float t00, float t01, float t02,
- float t10, float t11, float t12,
- float t20, float t21, float t22) {
- return (t00 * (t11 * t22 - t12 * t21) +
- t01 * (t12 * t20 - t10 * t22) +
- t02 * (t10 * t21 - t11 * t20));
- }
-
-
- public PMatrix transpose() {
- float temp;
- temp = m01; m01 = m10; m10 = temp;
- temp = m02; m02 = m20; m20 = temp;
- temp = m03; m03 = m30; m30 = temp;
- temp = m12; m12 = m21; m21 = temp;
- temp = m13; m13 = m31; m31 = temp;
- temp = m23; m23 = m32; m32 = temp;
- return this;
- }
-
-
- /**
- * Invert this matrix
- * @return this if successful, null otherwise
- */
- public PMatrix invert() {
-
- float determinant = determinant();
-
- if (determinant != 0) {
- // m00 m01 m02 m03
- // m10 m11 m12 m13
- // m20 m21 m22 m23
- // m30 m31 m32 m33
- float determinant_inv = 1f / determinant;
-
- // first row
- float t00 = determinant3x3(m11, m12, m13, m21, m22, m23, m31, m32, m33);
- float t01 = -determinant3x3(m10, m12, m13, m20, m22, m23, m30, m32, m33);
- float t02 = determinant3x3(m10, m11, m13, m20, m21, m23, m30, m31, m33);
- float t03 = -determinant3x3(m10, m11, m12, m20, m21, m22, m30, m31, m32);
-
- // second row
- float t10 = -determinant3x3(m01, m02, m03, m21, m22, m23, m31, m32, m33);
- float t11 = determinant3x3(m00, m02, m03, m20, m22, m23, m30, m32, m33);
- float t12 = -determinant3x3(m00, m01, m03, m20, m21, m23, m30, m31, m33);
- float t13 = determinant3x3(m00, m01, m02, m20, m21, m22, m30, m31, m32);
-
- // third row
- float t20 = determinant3x3(m01, m02, m03, m11, m12, m13, m31, m32, m33);
- float t21 = -determinant3x3(m00, m02, m03, m10, m12, m13, m30, m32, m33);
- float t22 = determinant3x3(m00, m01, m03, m10, m11, m13, m30, m31, m33);
- float t23 = -determinant3x3(m00, m01, m02, m10, m11, m12, m30, m31, m32);
-
- // fourth row
- float t30 = -determinant3x3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
- float t31 = determinant3x3(m00, m02, m03, m10, m12, m13, m20, m22, m23);
- float t32 = -determinant3x3(m00, m01, m03, m10, m11, m13, m20, m21, m23);
- float t33 = determinant3x3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
-
- // transpose and divide by the determinant
- m00 = t00*determinant_inv;
- m11 = t11*determinant_inv;
- m22 = t22*determinant_inv;
- m33 = t33*determinant_inv;
- m01 = t10*determinant_inv;
- m10 = t01*determinant_inv;
- m20 = t02*determinant_inv;
- m02 = t20*determinant_inv;
- m12 = t21*determinant_inv;
- m21 = t12*determinant_inv;
- m03 = t30*determinant_inv;
- m30 = t03*determinant_inv;
- m13 = t31*determinant_inv;
- m31 = t13*determinant_inv;
- m32 = t23*determinant_inv;
- m23 = t32*determinant_inv;
- return this;
- }
- return null;
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- public void print() {
- int big = (int) Math.abs(max(max(max(max(abs(m00), abs(m01)),
- max(abs(m02), abs(m03))),
- max(max(abs(m10), abs(m11)),
- max(abs(m12), abs(m13)))),
- max(max(max(abs(m20), abs(m21)),
- max(abs(m22), abs(m23))),
- max(max(abs(m30), abs(m31)),
- max(abs(m32), abs(m33))))));
-
- // avoid infinite loop
- if (Float.isNaN(big) || Float.isInfinite(big)) {
- big = 1000000; // set to something arbitrary
- }
-
- int d = 1;
- while ((big /= 10) != 0) d++; // cheap log()
-
- System.out.println(PApplet.nfs(m00, d, 4) + " " +
- PApplet.nfs(m01, d, 4) + " " +
- PApplet.nfs(m02, d, 4) + " " +
- PApplet.nfs(m03, d, 4));
-
- System.out.println(PApplet.nfs(m10, d, 4) + " " +
- PApplet.nfs(m11, d, 4) + " " +
- PApplet.nfs(m12, d, 4) + " " +
- PApplet.nfs(m13, d, 4));
-
- System.out.println(PApplet.nfs(m20, d, 4) + " " +
- PApplet.nfs(m21, d, 4) + " " +
- PApplet.nfs(m22, d, 4) + " " +
- PApplet.nfs(m23, d, 4));
-
- System.out.println(PApplet.nfs(m30, d, 4) + " " +
- PApplet.nfs(m31, d, 4) + " " +
- PApplet.nfs(m32, d, 4) + " " +
- PApplet.nfs(m33, d, 4));
-
- System.out.println();
- }
-
-
- //////////////////////////////////////////////////////////////
-
-
- private final float max(float a, float b) {
- return (a > b) ? a : b;
- }
-
- private final float abs(float a) {
- return (a < 0) ? -a : a;
- }
-
- private final float sin(float angle) {
- return (float)Math.sin(angle);
- }
-
- private final float cos(float angle) {
- return (float)Math.cos(angle);
- }
-}
diff --git a/core/PShape.java b/core/PShape.java
deleted file mode 100644
index 0046b975f..000000000
--- a/core/PShape.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/* -*- mode: jde; 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 library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-*/
-
-package processing.core;
-
-
-// take a look at the obj loader to see how this fits with things
-
-// PShape.line() PShape.ellipse()?
-// PShape s = beginShape()
-// line()
-// endShape(s)
-
-public class PShape {
-
- int kind;
- PMatrix matrix;
-
- int[] opcode;
- int opcodeCount;
- // need to reorder vertex fields to make a VERTEX_SHORT_COUNT
- // that puts all the non-rendering fields into later indices
- float[][] data; // second param is the VERTEX_FIELD_COUNT
- // should this be called vertices (consistent with PGraphics internals)
- // or does that hurt flexibility?
-
- int childCount;
- PShape[] children;
-
- // POINTS, LINES, xLINE_STRIP, xLINE_LOOP
- // TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN
- // QUADS, QUAD_STRIP
- // xPOLYGON
- static final int PATH = 1; // POLYGON, LINE_LOOP, LINE_STRIP
- static final int GROUP = 2;
-
- // how to handle rectmode/ellipsemode?
- // are they bitshifted into the constant?
- // CORNER, CORNERS, CENTER, (CENTER_RADIUS?)
- static final int RECT = 3; // could just be QUAD, but would be x1/y1/x2/y2
- static final int ELLIPSE = 4;
-
- static final int VERTEX = 7;
- static final int CURVE = 5;
- static final int BEZIER = 6;
-
-
- // fill and stroke functions will need a pointer to the parent
- // PGraphics object.. may need some kind of createShape() fxn
- // or maybe the values are stored until draw() is called?
-
- // attaching images is very tricky.. it's a different type of data
-
- // material parameters will be thrown out,
- // except those currently supported (kinds of lights)
-
- // setAxis -> .x and .y to move x and y coords of origin
- public float x;
- public float y;
-
- // pivot point for transformations
- public float px;
- public float py;
-
-
- public PShape() {
- }
-
-
- public PShape(float x, float y) {
- this.x = x;
- this.y = y;
- }
-
-
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
-
- /**
- * Called by the following (the shape() command adds the g)
- * PShape s = loadShapes("blah.svg");
- * shape(s);
- */
- public void draw(PGraphics g) {
- boolean flat = g instanceof PGraphics3D;
-
- if (matrix != null) {
- g.pushMatrix();
- if (flat) {
- g.applyMatrix(matrix.m00, matrix.m01, matrix.m02,
- matrix.m10, matrix.m11, matrix.m12);
- } else {
- g.applyMatrix(matrix.m00, matrix.m01, matrix.m02, matrix.m03,
- matrix.m10, matrix.m11, matrix.m12, matrix.m13,
- matrix.m20, matrix.m21, matrix.m22, matrix.m23,
- matrix.m30, matrix.m31, matrix.m32, matrix.m33);
- }
- }
-
- // if g subclasses PGraphics2, ignore all lighting stuff and z coords
- // otherwise if PGraphics3, need to call diffuse() etc
-
- // unfortunately, also a problem with no way to encode stroke/fill
- // being enabled/disabled.. this quickly gets into just having opcodes
- // for the entire api, to deal with things like textures and images
-
- switch (kind) {
- case PATH:
- for (int i = 0; i < opcodeCount; i++) {
- switch (opcode[i]) {
- case VERTEX:
- break;
- }
- }
- break;
-
- case GROUP:
- break;
-
- case RECT:
- break;
- }
-
- if (matrix != null) {
- g.popMatrix();
- }
- }
-
-
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
-
- // can't be 'add' because that suggests additive geometry
- public void addChild(PShape who) {
- }
-
-
- public PShape createGroup() {
- PShape group = new PShape();
- group.kind = GROUP;
- addChild(group);
- return group;
- }
-
-
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
-
- // translate, rotate, scale, apply (no push/pop)
- // these each call matrix.translate, etc
- // if matrix is null when one is called,
- // it is created and set to identity
-
-
- public void translate(float tx, float ty) {
- translate(tx, ty, 0);
- }
-
- public void translate(float tx, float ty, float tz) {
- checkMatrix();
- matrix.translate(tx, ty, 0);
- }
-
-
- //
-
-
- public void rotateX(float angle) {
- rotate(angle, 1, 0, 0);
- }
-
- public void rotateY(float angle) {
- rotate(angle, 0, 1, 0);
- }
-
- public void rotateZ(float angle) {
- rotate(angle, 0, 0, 1);
- }
-
- public void rotate(float angle) {
- rotateZ(angle);
- }
-
- public void rotate(float angle, float v0, float v1, float v2) {
- checkMatrix();
- matrix.rotate(angle, v0, v1, v2);
- }
-
-
- //
-
-
- public void scale(float s) {
- scale(s, s, s);
- }
-
- public void scale(float sx, float sy) {
- scale(sx, sy, 1);
- }
-
- public void scale(float x, float y, float z) {
- checkMatrix();
- matrix.scale(x, y, z);
- }
-
-
- //
-
-
- public void applyMatrix(float n00, float n01, float n02,
- float n10, float n11, float n12) {
- checkMatrix();
- matrix.apply(n00, n01, n02, 0,
- n10, n11, n12, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
- }
-
- public void applyMatrix(float n00, float n01, float n02, float n03,
- float n10, float n11, float n12, float n13,
- float n20, float n21, float n22, float n23,
- float n30, float n31, float n32, float n33) {
- checkMatrix();
- matrix.apply(n00, n01, n02, n03,
- n10, n11, n12, n13,
- n20, n21, n22, n23,
- n30, n31, n32, n33);
- }
-
-
- //
-
-
- protected void checkMatrix() {
- if (matrix == null) {
- matrix = new PMatrix();
- }
- }
-
-
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
-
- /**
- * Center the shape based on its bounding box. Can't assume
- * that the bounding box is 0, 0, width, height. Common case will be
- * opening a letter size document in Illustrator, and drawing something
- * in the middle, then reading it in as an svg file.
- * This will also need to flip the y axis (scale(1, -1)) in cases
- * like Adobe Illustrator where the coordinates start at the bottom.
- */
- public void center() {
- }
-
-
- /**
- * Set the pivot point for all transformations.
- */
- public void pivot(float x, float y) {
- px = x;
- py = y;
- }
-
-
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
-
-
-}
\ No newline at end of file
diff --git a/core/PTriangle.java b/core/PTriangle.java
deleted file mode 100644
index 7142af5b6..000000000
--- a/core/PTriangle.java
+++ /dev/null
@@ -1,3827 +0,0 @@
-/* -*- mode: jde; 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 library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
- */
-
-package processing.core;
-
-/**
- * Handles rendering of single (tesselated) triangles in 3D.
- *
- * Written by sami www.sumea.com
- */
-public class PTriangle implements PConstants
-{
- static final int R_GOURAUD = 0x1;
- static final int R_TEXTURE8 = 0x2;
- static final int R_TEXTURE24 = 0x4;
- static final int R_TEXTURE32 = 0x8;
- static final int R_ALPHA = 0x10;
-
- private int[] m_pixels;
- private int[] m_texture;
- private int[] m_stencil;
- private float[] m_zbuffer;
-
- private int SCREEN_WIDTH;
- private int SCREEN_HEIGHT;
- //private int SCREEN_WIDTH1;
- //private int SCREEN_HEIGHT1;
-
- private int TEX_WIDTH;
- private int TEX_HEIGHT;
- private float F_TEX_WIDTH;
- private float F_TEX_HEIGHT;
-
- public boolean INTERPOLATE_UV;
- public boolean INTERPOLATE_RGB;
- public boolean INTERPOLATE_ALPHA;
-
- // the power of 2 that tells how many pixels to interpolate
- // for between exactly computed texture coordinates
- private static final int DEFAULT_INTERP_POWER = 3;
- private static int TEX_INTERP_POWER = DEFAULT_INTERP_POWER;
-
- // Vertex coordinates
- private float[] x_array;
- private float[] y_array;
- private float[] z_array;
-
- private float[] camX;
- private float[] camY;
- private float[] camZ;
-
- // U,V coordinates
- private float[] u_array;
- private float[] v_array;
-
- // Vertex Intensity
- private float[] r_array;
- private float[] g_array;
- private float[] b_array;
- private float[] a_array;
-
- // vertex offsets
- private int o0;
- private int o1;
- private int o2;
-
- /* rgb & a */
- private float r0;
- private float r1;
- private float r2;
- private float g0;
- private float g1;
- private float g2;
- private float b0;
- private float b1;
- private float b2;
- private float a0;
- private float a1;
- private float a2;
-
- /* accurate texture uv coordinates */
- private float u0;
- private float u1;
- private float u2;
- private float v0;
- private float v1;
- private float v2;
-
- /* deltas */
- //private float dx0;
- //private float dx1;
- private float dx2;
- private float dy0;
- private float dy1;
- private float dy2;
- private float dz0;
- //private float dz1;
- private float dz2;
-
- /* texture deltas */
- private float du0;
- //private float du1;
- private float du2;
- private float dv0;
- //private float dv1;
- private float dv2;
-
- /* rgba deltas */
- private float dr0;
- //private float dr1;
- private float dr2;
- private float dg0;
- //private float dg1;
- private float dg2;
- private float db0;
- //private float db1;
- private float db2;
- private float da0;
- //private float da1;
- private float da2;
-
- /* */
- private float uleft;
- private float vleft;
- private float uleftadd;
- private float vleftadd;
-
- /* polyedge positions & adds */
- private float xleft;
- private float xrght;
- private float xadd1;
- private float xadd2;
- private float zleft;
- private float zleftadd;
-
- /* rgba positions & adds */
- private float rleft;
- private float gleft;
- private float bleft;
- private float aleft;
- private float rleftadd;
- private float gleftadd;
- private float bleftadd;
- private float aleftadd;
-
- /* other somewhat useful variables :) */
- private float dta;
- //private float dta2;
- private float temp;
- private float width;
-
- /* integer poly UV adds */
- private int iuadd;
- private int ivadd;
- private int iradd;
- private int igadd;
- private int ibadd;
- private int iaadd;
- private float izadd;
-
- /* fill color */
- private int m_fill;
-
- /* draw flags */
- public int m_drawFlags;
-
- /* current poly number */
- private int m_index;
-
- /** */
- private PGraphics3D parent;
-
- private boolean noDepthTest;
-
- /** */
- private boolean m_culling;
-
- /** */
- private boolean m_singleRight;
-
- /** */
- private boolean m_bilinear;
-
-
- //Vectors needed in accurate texture code
- //We store them as class members to avoid too much code duplication
- private float ax,ay,az;
- private float bx,by,bz;
- private float cx,cy,cz;
- private float nearPlaneWidth;
- private float nearPlaneHeight;
- private float nearPlaneDepth;
- private float xmult;
- private float ymult;
- private float newax,newbx,newcx; //optimization vars...not pretty, but save a couple mults per pixel
- private boolean firstSegment; //are we currently drawing the first piece of the triangle, or have we already done so?
-
-
-
-
- public PTriangle(PGraphics3D g) {
- //SCREEN_WIDTH = g.width;
- //SCREEN_HEIGHT = g.height;
- //SCREEN_WIDTH1 = SCREEN_WIDTH-1;
- //SCREEN_HEIGHT1 = SCREEN_HEIGHT-1;
-
- //m_pixels = g.pixels;
- //m_stencil = g.stencil;
- //m_zbuffer = g.zbuffer;
-
- x_array = new float[3];
- y_array = new float[3];
- z_array = new float[3];
- u_array = new float[3];
- v_array = new float[3];
- r_array = new float[3];
- g_array = new float[3];
- b_array = new float[3];
- a_array = new float[3];
-
- camX = new float[3];
- camY = new float[3];
- camZ = new float[3];
-
- this.parent = g;
- reset();
- }
-
- /**
- * Resets polygon attributes
- */
- public void reset() {
- // reset these in case PGraphics was resized
-
- SCREEN_WIDTH = parent.width;
- SCREEN_HEIGHT = parent.height;
- //SCREEN_WIDTH1 = SCREEN_WIDTH-1;
- //SCREEN_HEIGHT1 = SCREEN_HEIGHT-1;
-
- m_pixels = parent.pixels;
- m_stencil = parent.stencil;
- m_zbuffer = parent.zbuffer;
-
- noDepthTest = parent.hints[DISABLE_DEPTH_TEST];
-
- // other things to reset
-
- INTERPOLATE_UV = false;
- INTERPOLATE_RGB = false;
- INTERPOLATE_ALPHA = false;
- //m_tImage = null;
- m_texture = null;
- m_drawFlags = 0;
- }
-
- /**
- * Sets backface culling on/off
- */
- public void setCulling(boolean tf) {
- m_culling = tf;
- }
-
-
- /**
- * Sets vertex coordinates for the triangle
- */
- public void setVertices(float x0, float y0, float z0,
- float x1, float y1, float z1,
- float x2, float y2, float z2) {
- x_array[0] = x0;
- x_array[1] = x1;
- x_array[2] = x2;
-
- y_array[0] = y0;
- y_array[1] = y1;
- y_array[2] = y2;
-
- z_array[0] = z0;
- z_array[1] = z1;
- z_array[2] = z2;
- }
-
- /**
- * Pass camera-space coordinates for the triangle (needed to render if ENABLE_ACCURATE_TEXTURES is hinted).
- */
- public void setCamVertices(float x0, float y0, float z0,
- float x1, float y1, float z1,
- float x2, float y2, float z2) {
- //Generally this will not need to be called manually, currently called if hints[ENABLE_ACCURATE_TEXTURES]
- //from PGraphics3D.render_triangles()
-
- camX[0] = x0;
- camX[1] = x1;
- camX[2] = x2;
-
- camY[0] = y0;
- camY[1] = y1;
- camY[2] = y2;
-
- camZ[0] = z0;
- camZ[1] = z1;
- camZ[2] = z2;
- }
-
- /**
- * Sets the UV coordinates of the texture
- */
- public void setUV(float u0, float v0,
- float u1, float v1,
- float u2, float v2) {
- // sets & scales uv texture coordinates to center of the pixel
- u_array[0] = (u0 * F_TEX_WIDTH + 0.5f) * 65536f;
- u_array[1] = (u1 * F_TEX_WIDTH + 0.5f) * 65536f;
- u_array[2] = (u2 * F_TEX_WIDTH + 0.5f) * 65536f;
- v_array[0] = (v0 * F_TEX_HEIGHT + 0.5f) * 65536f;
- v_array[1] = (v1 * F_TEX_HEIGHT + 0.5f) * 65536f;
- v_array[2] = (v2 * F_TEX_HEIGHT + 0.5f) * 65536f;
- }
-
- /**
- * Sets vertex intensities in 0xRRGGBBAA format
- */
- public void setIntensities( float r0, float g0, float b0, float a0,
- float r1, float g1, float b1, float a1,
- float r2, float g2, float b2, float a2) {
- // Check if we need alpha or not?
- if ((a0 != 1.0f) || (a1 != 1.0f) || (a2 != 1.0f)) {
- INTERPOLATE_ALPHA = true;
- a_array[0] = (a0 * 253f + 1.0f) * 65536f;
- a_array[1] = (a1 * 253f + 1.0f) * 65536f;
- a_array[2] = (a2 * 253f + 1.0f) * 65536f;
- m_drawFlags|=R_ALPHA;
- } else {
- INTERPOLATE_ALPHA = false;
- m_drawFlags&=~R_ALPHA;
- }
-
- // Check if we need to interpolate the intensity values
- if ((r0 != r1) || (r1 != r2)) {
- INTERPOLATE_RGB = true;
- m_drawFlags|=R_GOURAUD;
- } else if ((g0 != g1) || (g1 != g2)) {
- INTERPOLATE_RGB = true;
- m_drawFlags|=R_GOURAUD;
- } else if ((b0 != b1) || (b1 != b2)) {
- INTERPOLATE_RGB = true;
- m_drawFlags|=R_GOURAUD;
- } else {
- //m_fill = parent.filli;
- m_drawFlags&=~R_GOURAUD;
- }
-
- // push values to arrays.. some extra scaling is added
- // to prevent possible color "overflood" due to rounding errors
- r_array[0] = (r0 * 253f + 1.0f) * 65536f;
- r_array[1] = (r1 * 253f + 1.0f) * 65536f;
- r_array[2] = (r2 * 253f + 1.0f) * 65536f;
-
- g_array[0] = (g0 * 253f + 1.0f) * 65536f;
- g_array[1] = (g1 * 253f + 1.0f) * 65536f;
- g_array[2] = (g2 * 253f + 1.0f) * 65536f;
-
- b_array[0] = (b0 * 253f + 1.0f) * 65536f;
- b_array[1] = (b1 * 253f + 1.0f) * 65536f;
- b_array[2] = (b2 * 253f + 1.0f) * 65536f;
-
- // for plain triangles
- m_fill = ((int)(255*r0) << 16) | ((int)(255*g0) << 8) | (int)(255*b0);
- }
-
-
- /**
- * Sets texture image used for the polygon
- */
- public void setTexture(PImage image) {
- //m_tImage = image;
- m_texture = image.pixels;
- TEX_WIDTH = image.width;
- TEX_HEIGHT = image.height;
- F_TEX_WIDTH = TEX_WIDTH-1;
- F_TEX_HEIGHT = TEX_HEIGHT-1;
- INTERPOLATE_UV = true;
-
- if (image.format == ARGB) {
- m_drawFlags|=R_TEXTURE32;
- } else if (image.format == RGB) {
- m_drawFlags|=R_TEXTURE24;
- } else if (image.format == ALPHA) {
- m_drawFlags|=R_TEXTURE8;
- }
-
- //if (parent.hints[SMOOTH_IMAGES]) {
- /*
- if (parent.smooth) {
- m_bilinear = true;
- } else {
- m_bilinear = false;
- }
- */
- m_bilinear = true;
- }
-
- /**
- *
- */
- public void setUV(float[] u, float[] v) {
- if (m_bilinear) {
- // sets & scales uv texture coordinates to edges of pixels
- u_array[0] = (u[0] * F_TEX_WIDTH) * 65500f;
- u_array[1] = (u[1] * F_TEX_WIDTH) * 65500f;
- u_array[2] = (u[2] * F_TEX_WIDTH) * 65500f;
- v_array[0] = (v[0] * F_TEX_HEIGHT) * 65500f;
- v_array[1] = (v[1] * F_TEX_HEIGHT) * 65500f;
- v_array[2] = (v[2] * F_TEX_HEIGHT) * 65500f;
- } else {
- // sets & scales uv texture coordinates to center of the pixel
- u_array[0] = (u[0] * TEX_WIDTH) * 65500f;
- u_array[1] = (u[1] * TEX_WIDTH) * 65500f;
- u_array[2] = (u[2] * TEX_WIDTH) * 65500f;
- v_array[0] = (v[0] * TEX_HEIGHT) * 65500f;
- v_array[1] = (v[1] * TEX_HEIGHT) * 65500f;
- v_array[2] = (v[2] * TEX_HEIGHT) * 65500f;
- }
- }
-
- public void setIndex(int index) {
- m_index = index;
- }
-
- /**
- * Renders the polygon
- */
- public void render() {
- // removed. done in PGraphics [rocha]
- // increase polygon offset
- //m_index = (m_index + 1) & 0xFFFFFFF;
-
- // draw the polygon
- draw();
-
- // removed. replaced by external antialiasing [rocha]
- // smooth edges?
- //if (parent.smooth )
- //{
- // drawline_blender(x_array[0], y_array[0], x_array[1], y_array[1]);
- // drawline_blender(x_array[1], y_array[1], x_array[2], y_array[2]);
- // drawline_blender(x_array[2], y_array[2], x_array[0], y_array[0]);
- //}
- }
-
- private void draw() {
- // y-coordinates
- float x0;
- float x1;
- float x2;
-
- //
- float z0;
- float z1;
- float z2;
-
- //
- float y0 = y_array[0];
- float y1 = y_array[1];
- float y2 = y_array[2];
-
- // For accurate texture interpolation, need to mark whether
- // we've already pre-calculated for the triangle
- firstSegment = true;
-
- // do backface culling?
- if (m_culling) {
- x0 = x_array[0];
- if ((x_array[2]-x0)*(y1-y0) < (x_array[1]-x0)*(y2-y0))
- return;
- }
-
- /* get vertex order from top -> down */
- if (y0y1) {
- if (y2 SCREEN_HEIGHT) {
- return;
- } else if (yi0 < 0) {
- yi0 = 0;
- }
-
- y2 = y_array[o2];
- int yi2 = (int) (y2 + PIXEL_CENTER);
- if (yi2 < 0) {
- return;
- } else if (yi2 > SCREEN_HEIGHT) {
- yi2 = SCREEN_HEIGHT;
- }
-
- // Does the poly actually cross a scanline?
- if (yi2 > yi0) {
- x0 = x_array[o0];
- x1 = x_array[o1];
- x2 = x_array[o2];
-
- // get mid Y and clip it
- y1 = y_array[o1];
- int yi1 = (int) (y1 + PIXEL_CENTER);
- if (yi1 < 0)
- yi1 = 0;
- if (yi1 > SCREEN_HEIGHT)
- yi1 = SCREEN_HEIGHT;
-
- // calculate deltas etc.
- dx2 = x2 - x0;
- dy0 = y1 - y0;
- dy2 = y2 - y0;
- xadd2 = dx2 / dy2; // xadd for "single" edge
- temp = dy0 / dy2;
- width = temp * dx2 + x0 - x1;
-
- // calculate alpha blend interpolation
- if (INTERPOLATE_ALPHA) {
- a0 = a_array[o0];
- a1 = a_array[o1];
- a2 = a_array[o2];
- da0 = a1-a0;
- da2 = a2-a0;
- iaadd = (int) ((temp * da2 - da0) / width); // alpha add
- }
-
- // calculate intensity interpolation
- if (INTERPOLATE_RGB) {
- r0 = r_array[o0];
- r1 = r_array[o1];
- r2 = r_array[o2];
-
- g0 = g_array[o0];
- g1 = g_array[o1];
- g2 = g_array[o2];
-
- b0 = b_array[o0];
- b1 = b_array[o1];
- b2 = b_array[o2];
-
- dr0 = r1-r0;
- dg0 = g1-g0;
- db0 = b1-b0;
-
- dr2 = r2-r0;
- dg2 = g2-g0;
- db2 = b2-b0;
-
- iradd = (int) ((temp * dr2 - dr0) / width); // r add
- igadd = (int) ((temp * dg2 - dg0) / width); // g add
- ibadd = (int) ((temp * db2 - db0) / width); // b add
- }
-
- // calculate UV interpolation
- if (INTERPOLATE_UV) {
- u0 = u_array[o0];
- u1 = u_array[o1];
- u2 = u_array[o2];
- v0 = v_array[o0];
- v1 = v_array[o1];
- v2 = v_array[o2];
- du0 = u1-u0;
- dv0 = v1-v0;
- du2 = u2-u0;
- dv2 = v2-v0;
- iuadd = (int) ((temp * du2 - du0) / width); // u add
- ivadd = (int) ((temp * dv2 - dv0) / width); // v add
- }
-
- z0 = z_array[o0];
- z1 = z_array[o1];
- z2 = z_array[o2];
- dz0 = z1-z0;
- dz2 = z2-z0;
- izadd = (temp * dz2 - dz0) / width;
-
- // draw the upper poly segment if it's visible
- if (yi1 > yi0) {
- dta = (yi0 + PIXEL_CENTER) - y0;
- xadd1 = (x1 - x0) / dy0;
-
- // we can determine which side is "single" side by comparing left/right edge adds
- if (xadd2 > xadd1) {
- xleft = x0 + dta * xadd1;
- xrght = x0 + dta * xadd2;
- zleftadd = dz0 / dy0;
- zleft = dta*zleftadd+z0;
-
- //
- if (INTERPOLATE_UV) {
- uleftadd = du0 / dy0;
- vleftadd = dv0 / dy0;
- uleft = dta*uleftadd+u0;
- vleft = dta*vleftadd+v0;
- }
-
- //
- if (INTERPOLATE_RGB) {
- rleftadd = dr0 / dy0;
- gleftadd = dg0 / dy0;
- bleftadd = db0 / dy0;
- rleft = dta*rleftadd+r0;
- gleft = dta*gleftadd+g0;
- bleft = dta*bleftadd+b0;
- }
-
- //
- if (INTERPOLATE_ALPHA) {
- aleftadd = da0 / dy0;
- aleft = dta*aleftadd+a0;
-
- if (m_drawFlags == R_ALPHA) {
- drawsegment_plain_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) {
- drawsegment_gouraud_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) {
- drawsegment_texture8_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) {
- drawsegment_texture24_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) {
- drawsegment_texture32_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) {
- drawsegment_gouraud_texture8_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) {
- drawsegment_gouraud_texture24_alpha(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) {
- drawsegment_gouraud_texture32_alpha(xadd1,xadd2, yi0,yi1);
- }
- } else {
- if (m_drawFlags == 0) {
- drawsegment_plain(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == R_GOURAUD) {
- drawsegment_gouraud(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == R_TEXTURE8) {
- drawsegment_texture8(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == R_TEXTURE24) {
- drawsegment_texture24(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == R_TEXTURE32) {
- drawsegment_texture32(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) {
- drawsegment_gouraud_texture8(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) {
- drawsegment_gouraud_texture24(xadd1,xadd2, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) {
- drawsegment_gouraud_texture32(xadd1,xadd2, yi0,yi1);
- }
- }
- m_singleRight = true;
- } else {
- xleft = x0 + dta * xadd2;
- xrght = x0 + dta * xadd1;
- zleftadd = dz2 / dy2;
- zleft = dta*zleftadd+z0;
- //
- if (INTERPOLATE_UV) {
- uleftadd = du2 / dy2;
- vleftadd = dv2 / dy2;
- uleft = dta*uleftadd+u0;
- vleft = dta*vleftadd+v0;
- }
-
- //
- if (INTERPOLATE_RGB) {
- rleftadd = dr2 / dy2;
- gleftadd = dg2 / dy2;
- bleftadd = db2 / dy2;
- rleft = dta*rleftadd+r0;
- gleft = dta*gleftadd+g0;
- bleft = dta*bleftadd+b0;
- }
-
-
- if (INTERPOLATE_ALPHA) {
- aleftadd = da2 / dy2;
- aleft = dta*aleftadd+a0;
-
- if (m_drawFlags == R_ALPHA) {
- drawsegment_plain_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) {
- drawsegment_gouraud_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) {
- drawsegment_texture8_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) {
- drawsegment_texture24_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) {
- drawsegment_texture32_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) {
- drawsegment_gouraud_texture8_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) {
- drawsegment_gouraud_texture24_alpha(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) {
- drawsegment_gouraud_texture32_alpha(xadd2, xadd1, yi0,yi1);
- }
- } else {
- if (m_drawFlags == 0) {
- drawsegment_plain(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == R_GOURAUD) {
- drawsegment_gouraud(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == R_TEXTURE8) {
- drawsegment_texture8(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == R_TEXTURE24) {
- drawsegment_texture24(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == R_TEXTURE32) {
- drawsegment_texture32(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) {
- drawsegment_gouraud_texture8(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) {
- drawsegment_gouraud_texture24(xadd2, xadd1, yi0,yi1);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) {
- drawsegment_gouraud_texture32(xadd2, xadd1, yi0,yi1);
- }
- }
- m_singleRight = false;
- }
-
- // if bottom segment height is zero, return
- if (yi2 == yi1)
- return;
-
- // calculate xadd 1
- dy1 = y2 - y1;
- xadd1 = (x2 - x1) / dy1;
- } else {
- // top seg height was zero, calculate & clip single edge X
- dy1 = y2 - y1;
- xadd1 = (x2 - x1) / dy1;
-
- // which edge is left?
- if (xadd2 < xadd1) {
- xrght = ((yi1 + PIXEL_CENTER) - y0) * xadd2 + x0;
- m_singleRight = true;
- } else {
- dta = (yi1 + PIXEL_CENTER) - y0;
- xleft = dta * xadd2 + x0;
- zleftadd = dz2 / dy2;
- zleft = dta * zleftadd + z0;
-
- if (INTERPOLATE_UV) {
- uleftadd = du2 / dy2;
- vleftadd = dv2 / dy2;
- uleft = dta * uleftadd + u0;
- vleft = dta * vleftadd + v0;
- }
-
- if (INTERPOLATE_RGB) {
- rleftadd = dr2 / dy2;
- gleftadd = dg2 / dy2;
- bleftadd = db2 / dy2;
- rleft = dta * rleftadd + r0;
- gleft = dta * gleftadd + g0;
- bleft = dta * bleftadd + b0;
- }
-
- //
- if (INTERPOLATE_ALPHA) {
- aleftadd = da2 / dy2;
- aleft = dta * aleftadd + a0;
- }
- m_singleRight = false;
- }
- }
-
- // draw the lower segment
- if (m_singleRight) {
- dta = (yi1 + PIXEL_CENTER) - y1;
- xleft = dta * xadd1 + x1;
- zleftadd = (z2 - z1) / dy1;
- zleft = dta * zleftadd + z1;
-
- if (INTERPOLATE_UV) {
- uleftadd = (u2 - u1) / dy1;
- vleftadd = (v2 - v1) / dy1;
- uleft = dta * uleftadd + u1;
- vleft = dta * vleftadd + v1;
- }
-
- if (INTERPOLATE_RGB) {
- rleftadd = (r2 - r1) / dy1;
- gleftadd = (g2 - g1) / dy1;
- bleftadd = (b2 - b1) / dy1;
- rleft = dta * rleftadd + r1;
- gleft = dta * gleftadd + g1;
- bleft = dta * bleftadd + b1;
- }
-
- if (INTERPOLATE_ALPHA) {
- aleftadd = (a2 - a1) / dy1;
- aleft = dta * aleftadd + a1;
-
- if (m_drawFlags == R_ALPHA) {
- drawsegment_plain_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) {
- drawsegment_gouraud_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) {
- drawsegment_texture8_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) {
- drawsegment_texture24_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) {
- drawsegment_texture32_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) {
- drawsegment_gouraud_texture8_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) {
- drawsegment_gouraud_texture24_alpha(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) {
- drawsegment_gouraud_texture32_alpha(xadd1, xadd2, yi1,yi2);
- }
- } else {
- if (m_drawFlags == 0) {
- drawsegment_plain(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == R_GOURAUD) {
- drawsegment_gouraud(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == R_TEXTURE8) {
- drawsegment_texture8(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == R_TEXTURE24) {
- drawsegment_texture24(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == R_TEXTURE32) {
- drawsegment_texture32(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) {
- drawsegment_gouraud_texture8(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) {
- drawsegment_gouraud_texture24(xadd1, xadd2, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) {
- drawsegment_gouraud_texture32(xadd1, xadd2, yi1,yi2);
- }
- }
- } else {
- xrght = ((yi1 + PIXEL_CENTER)- y1) * xadd1 + x1;
-
- if (INTERPOLATE_ALPHA) {
- if (m_drawFlags == R_ALPHA) {
- drawsegment_plain_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) {
- drawsegment_gouraud_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) {
- drawsegment_texture8_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) {
- drawsegment_texture24_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) {
- drawsegment_texture32_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) {
- drawsegment_gouraud_texture8_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) {
- drawsegment_gouraud_texture24_alpha(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) {
- drawsegment_gouraud_texture32_alpha(xadd2, xadd1, yi1,yi2);
- }
- } else {
- if (m_drawFlags == 0) {
- drawsegment_plain(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == R_GOURAUD) {
- drawsegment_gouraud(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == R_TEXTURE8) {
- drawsegment_texture8(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == R_TEXTURE24) {
- drawsegment_texture24(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == R_TEXTURE32) {
- drawsegment_texture32(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) {
- drawsegment_gouraud_texture8(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) {
- drawsegment_gouraud_texture24(xadd2, xadd1, yi1,yi2);
- } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) {
- drawsegment_gouraud_texture32(xadd2, xadd1, yi1,yi2);
- }
- }
- }
- }
- }
-
-
- /*
- Accurate texturing code by ewjordan@gmail.com, April 14, 2007
- The getColorFromTexture() function should be inlined and optimized so that most of the heavy lifting
- happens outside the per-pixel loop. The unoptimized generic algorithm looks like this (unless noted,
- all of these variables are vectors, so the actual code will look messier):
-
- p = camera space vector where u == 0, v == 0;
- m = vector from p to location where u == TEX_WIDTH;
- n = vector from p to location where v == TEX_HEIGHT;
-
- A = p cross n;
- B = m cross p;
- C = n cross m;
- A *= texture.width;
- B *= texture.height;
-
- for (scanlines in triangle){
- float a = S * A;
- float b = S * B;
- float c = S * C;
- for (pixels in scanline){
- int u = a/c;
- int v = b/c;
- color = texture[v * texture.width + u];
- a += A.x;
- b += B.x;
- c += C.x;
- }
- }
-
- We don't use this exact algorithm here, however, because of the extra overhead from the divides.
- Instead we compute the exact u and v (labelled iu and iv in the code) at the start of each scanline
- and we perform a linear interpolation for every linearInterpLength = 1 << TEX_INTERP_POWER pixels.
- This means that we only perform the true calculation once in a while, and the rest of the time
- the algorithm functions exactly as in the fast inaccurate case, at least in theory. In practice,
- even if we set linearInterpLength very high we still incur some speed penalty due to the preprocessing
- that must take place per-scanline. A similar method could be applied per scanline to avoid this, but
- it would only be worthwhile in the case that we never compute more than one exact calculation per
- scanline. If we want something like this, however, it would be best to create another mode of calculation
- called "constant-z" interpolation, which could be used for things like floors and ceilings where the
- distance from the camera plane never changes over the course of a scanline. We could also add the
- vertical analogue for drawing vertical walls. In any case, these are not critical as the current
- algorithm runs fairly well, perhaps ~10% slower than the default perspective-less one.
-
- */
-
- /**
- * Solve for camera space coordinates of critical texture points and set up per-triangle variables for accurate texturing
- */
- private boolean precomputeAccurateTexturing(){
- //Sets all class variables relevant to accurate texture computation
- //Should be called once per triangle - checks firstSegment to see if we've already called
-
- float myFact = 65500.0f; //rescale u/v_array values when inverting matrix and performing other calcs
- float myFact2 = 65500.0f;
-
- //Matrix inversion to find affine transform between (u,v,(1)) -> (x,y,z)
-
- //OPTIMIZE: There should be a way to avoid the inversion here, which is
- //quite expensive (~150 mults). Also it might crap out due to loss of precision depending
- //on the scaling of the u/v_arrays. Nothing clever currently happens if the inversion
- //fails, since this means the transformation is degenerate - we just pass false back to
- //the caller and let it handle the situation. [There is no good solution to this
- //case from within this function, since the way the calculation proceeds presumes a non-
- //degenerate transformation matrix between camera space and uv space]
-
- //Obvious optimization: if the vertices are actually at the appropriate texture coordinates
- //(e.g. (0,0), (TEX_WIDTH,0), and (0,TEX_HEIGHT)) then we can immediately return the
- //right solution without the inversion. This is fairly common, so could speed up
- //many cases of drawing. [not implemented]
-
- //Furthermore, we could cache the p,resultT0,result0T vectors in the triangle's
- //basis, since we could then do a look-up and generate the resulting coordinates very simply.
- //This would include the above optimization as a special case - we could pre-populate the
- //cache with special cases like that and dynamically add more. The idea here is
- //that most people simply paste textures onto triangles and move the triangles from
- //frame to frame, so any per-triangle-per-frame code is likely wasted effort.
- //[not implemented]
-
- //Note: o0, o1, and o2 vary depending on view angle to triangle, but p, n, and m should not depend on ordering differences
-
- if(firstSegment){
-
- PMatrix myMatrix = new PMatrix( u_array[o0]/myFact, v_array[o0]/myFact2, 1, 0,
- u_array[o1]/myFact, v_array[o1]/myFact2, 1, 0,
- u_array[o2]/myFact, v_array[o2]/myFact2, 1, 0,
- 0, 0, 0, 1);
- myMatrix = myMatrix.invert(); //A 3x3 inversion would be more efficient here, given that the fourth r/c are unity
- if (myMatrix == null) {return false;} //if the matrix inversion had trouble, let the caller know
- float m00, m01, m02, m10, m11, m12, m20, m21, m22;
- m00 = myMatrix.m00*camX[o0]+myMatrix.m01*camX[o1]+myMatrix.m02*camX[o2];
- m01 = myMatrix.m10*camX[o0]+myMatrix.m11*camX[o1]+myMatrix.m12*camX[o2];
- m02 = myMatrix.m20*camX[o0]+myMatrix.m21*camX[o1]+myMatrix.m22*camX[o2];
- m10 = myMatrix.m00*camY[o0]+myMatrix.m01*camY[o1]+myMatrix.m02*camY[o2];
- m11 = myMatrix.m10*camY[o0]+myMatrix.m11*camY[o1]+myMatrix.m12*camY[o2];
- m12 = myMatrix.m20*camY[o0]+myMatrix.m21*camY[o1]+myMatrix.m22*camY[o2];
- m20 = -(myMatrix.m00*camZ[o0]+myMatrix.m01*camZ[o1]+myMatrix.m02*camZ[o2]);
- m21 = -(myMatrix.m10*camZ[o0]+myMatrix.m11*camZ[o1]+myMatrix.m12*camZ[o2]);
- m22 = -(myMatrix.m20*camZ[o0]+myMatrix.m21*camZ[o1]+myMatrix.m22*camZ[o2]);
-
- float px = m02;
- float py = m12;
- float pz = m22;
- float resultT0x = m00*TEX_WIDTH+m02; //Bugfix: possibly we should use F_TEX_WIDTH/HEIGHT instead? Seems to read off end of array in that case, though...
- float resultT0y = m10*TEX_WIDTH+m12;
- float resultT0z = m20*TEX_WIDTH+m22;
- float result0Tx = m01*TEX_HEIGHT+m02;
- float result0Ty = m11*TEX_HEIGHT+m12;
- float result0Tz = m21*TEX_HEIGHT+m22;
- float mx = resultT0x-m02;
- float my = resultT0y-m12;
- float mz = resultT0z-m22;
- float nx = result0Tx-m02;
- float ny = result0Ty-m12;
- float nz = result0Tz-m22;
-
- //avec = p x n
- ax = (py*nz-pz*ny)*TEX_WIDTH; //F_TEX_WIDTH/HEIGHT?
- ay = (pz*nx-px*nz)*TEX_WIDTH;
- az = (px*ny-py*nx)*TEX_WIDTH;
- //bvec = m x p
- bx = (my*pz-mz*py)*TEX_HEIGHT;
- by = (mz*px-mx*pz)*TEX_HEIGHT;
- bz = (mx*py-my*px)*TEX_HEIGHT;
- //cvec = n x m
- cx = ny*mz-nz*my;
- cy = nz*mx-nx*mz;
- cz = nx*my-ny*mx;
- }
-
- nearPlaneWidth = parent.rightScreen-parent.leftScreen;
- nearPlaneHeight = parent.topScreen-parent.bottomScreen;
- nearPlaneDepth = parent.nearPlane;
- xmult = nearPlaneWidth / SCREEN_WIDTH; //one pixel width in nearPlane coordinates
- ymult = nearPlaneHeight / SCREEN_HEIGHT;
- newax = ax*xmult;//Extra scalings to map screen plane units to pixel units
- newbx = bx*xmult;
- newcx = cx*xmult;
- return true;
- }
-
- /**
- * Set the power of two used for linear interpolation of texture coordinates.
- * A true texture coordinate is computed every 2^pwr pixels along a scanline.
- */
- static public void setInterpPower(int pwr){
- //Currently must be invoked from P5 as PTriangle.setInterpPower(...)
- TEX_INTERP_POWER = pwr;
- }
-
-
-
- /**
- * Plain color
- */
- private void drawsegment_plain
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int f = m_fill;
- int p = m_index;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- float iz = izadd * xdiff + zleft;
- xstart+=ytop;
- xend+=ytop;
-
- for ( ; xstart < xend; xstart++ ) {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- m_zbuffer[xstart] = iz;
- m_pixels[xstart] = f;
- m_stencil[xstart] = p;
- }
- iz+=izadd;
- }
-
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- zleft+=zleftadd;
- }
- }
-
- /**
- * Plain color, interpolated alpha
- */
- private void drawsegment_plain_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
-
- int pr = m_fill & 0xFF0000;
- int pg = m_fill & 0xFF00;
- int pb = m_fill & 0xFF;
-
- int p = m_index;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- float iz = izadd * xdiff + zleft;
- int ia = (int) (iaf * xdiff + aleft);
- xstart+=ytop;
- xend+=ytop;
-
- for ( ; xstart < xend; xstart++ ) {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- int alpha = ia >> 16;
- int mr0 = m_pixels[xstart];
- int mg0 = mr0 & 0xFF00;
- int mb0 = mr0 & 0xFF;
- mr0 &= 0xFF0000;
-
- mr0 = mr0 + (((pr - mr0) * alpha) >> 8);
- mg0 = mg0 + (((pg - mg0) * alpha) >> 8);
- mb0 = mb0 + (((pb - mb0) * alpha) >> 8);
- m_pixels[xstart] = (mr0 & 0xFF0000) | (mg0 & 0xFF00) | (mb0 & 0xFF);
-
- m_stencil[xstart] = p;
- }
- iz += izadd;
- ia += iaadd;
- }
- ytop += SCREEN_WIDTH;
- xleft += leftadd;
- xrght += rghtadd;
- zleft += zleftadd;
- }
- }
-
-
- /**
- * RGB gouraud
- */
- private void drawsegment_gouraud
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- for ( ; xstart < xend; xstart++ ) {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- m_zbuffer[xstart] = iz;
- m_pixels[xstart]=((ir & 0xFF0000) | ((ig >> 8) & 0xFF00) | (ib >> 16));
- m_stencil[xstart] = p;
- }
-
- //
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- iz+=izadd;
- }
-
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * RGB gouraud + interpolated alpha
- */
- private void drawsegment_gouraud_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- for ( ; xstart < xend; xstart++ ) {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- //
- int red = (ir & 0xFF0000);
- int grn = (ig >> 8) & 0xFF00;
- int blu = (ib >> 16);
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
-
- // blend alpha
- int al = ia >> 16;
-
- //
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) | ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- m_stencil[xstart] = p;
- }
-
- //
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- ia+=iaadd;
- iz+=izadd;
- }
-
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- aleft+=aleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * 8-bit plain texture
- */
-
- //THIS IS MESSED UP, NEED TO GRAB ORIGINAL VERSION!!!
- private void drawsegment_texture8
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
-
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
-
- int red = m_fill & 0xFF0000;
- int grn = m_fill & 0xFF00;
- int blu = m_fill & 0xFF;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
- // try-catch just in case pixel offset it out of range
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- int al0;
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = iu & 0xFFFF;
- al0 = m_texture[ofs] & 0xFF;
- int al1 = m_texture[ofs + 1] & 0xFF;
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int al2 = m_texture[ofs] & 0xFF;
- int al3 = m_texture[ofs + 1] & 0xFF;
- al0 = al0 + (((al1-al0) * iui) >> 16);
- al2 = al2 + (((al3-al2) * iui) >> 16);
- al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16);
- } else {
- al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF;
- }
-
- int br = m_pixels[xstart];
- int bg = (br & 0xFF00);
- int bb = (br & 0xFF);
- br = (br & 0xFF0000);
- m_pixels[xstart] = ((br + (((red - br) * al0) >> 8)) & 0xFF0000) | ((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al0) >> 8)) & 0xFF);
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- iz+=izadd;
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- zleft+=zleftadd;
- }
- }
-
-
-
- /**
- * 8-bit texutre + alpha
- */
- private void drawsegment_texture8_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
-
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float iaf = iaadd;
-
- int red = m_fill & 0xFF0000;
- int grn = m_fill & 0xFF00;
- int blu = m_fill & 0xFF;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
- // try-catch just in case pixel offset it out of range
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- int al0;
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = iu & 0xFFFF;
- al0 = m_texture[ofs] & 0xFF;
- int al1 = m_texture[ofs + 1] & 0xFF;
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int al2 = m_texture[ofs] & 0xFF;
- int al3 = m_texture[ofs + 1] & 0xFF;
- al0 = al0 + (((al1-al0) * iui) >> 16);
- al2 = al2 + (((al3-al2) * iui) >> 16);
- al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16);
- } else {
- al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF;
- }
- al0 = (al0 * (ia >> 16)) >> 8;
-
- int br = m_pixels[xstart];
- int bg = (br & 0xFF00);
- int bb = (br & 0xFF);
- br = (br & 0xFF0000);
- m_pixels[xstart] = ((br + (((red - br) * al0) >> 8)) & 0xFF0000) | ((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al0) >> 8)) & 0xFF);
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- iz+=izadd;
- ia+=iaadd;
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- zleft+=zleftadd;
- aleft+=aleftadd;
- }
- }
-
- /**
- * Plain 24-bit texture
- */
- private void drawsegment_texture24
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
- float iuf = iuadd;
- float ivf = ivadd;
-
- int ypixel = ytop/SCREEN_WIDTH;//ACCTEX
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;//If we're past this index, we can't shift down a row w/o throwing an exception
-// int exCount = 0;//counter for exceptions caught
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; //bring this local since it will be accessed often
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
-
- //Interpolation length of 16 tends to look good except at a small angle; 8 looks okay then, except for the
- //above issue. When viewing close to flat, as high as 32 is often acceptable. Could add dynamic interpolation
- //settings based on triangle angle - currently we just pick a value and leave it (by default I have the
- //power set at 3, so every 8 pixels a true coordinate is calculated, which seems a decent compromise).
-
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion gave us garbage, revert to normal rendering (something is degenerate)
- }
- }
-
-
- while (ytop < ybottom) {//scanline loop
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0){ xstart = 0; }
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH){ xend = SCREEN_WIDTH; }
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- float iz = izadd * xdiff + zleft;
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- //off by one (half, I guess) hack, w/o it the first rows are outside the texture - maybe a mistake somewhere?
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;//OPT - some of this could be brought out of the y-loop since
- b = screenx*bx+screeny*by+screenz*bz;//xpixel and ypixel just increment by the same numbers each iteration.
- c = screenx*cx+screeny*cy+screenz*cz;//Probably not a big bottleneck, though.
- }
-
- //Figure out whether triangle is going further into the screen or not as we move along scanline
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
-
- //Set up linear interpolation between calculated texture points
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- //float fdeltaU = 0; float fdeltaV = 0;//vars for floating point interpolating version of algorithm
- //float fiu = 0; float fiv = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
-
- //Bugfix (done): it's a Really Bad Thing to interpolate along a scanline when the triangle goes deeper into the screen,
- //because if the angle is severe enough the last control point for interpolation may cross the vanishing
- //point. This leads to some pretty nasty artifacts, and ideally we should scan from right to left if the
- //triangle is better served that way, or (what we do now) precompute the offset that we'll need so that we end up
- //with a control point exactly at the furthest edge of the triangle.
-
- if (accurateMode&&goingIn){
- //IMPORTANT!!! Results are horrid without this hack!
- //If polygon goes into the screen along scan line, we want to match the control point to the furthest point drawn
- //since the control points are less meaningful the closer you are to the vanishing point.
- //We'll do this by making the first control point lie before the start of the scanline (safe since it's closer to us)
-
- int rightOffset = (xend-xstart-1)%linearInterpLength; //"off by one" hack...probably means there's a small bug somewhere
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
-
- //Take step to control point to the left of start pixel
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
-
- //Now step to right control point
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
-
- //Get deltas for interpolation
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- //Otherwise the left edge is further, and we pin the first control point to it
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
- for ( ; xstart < xend; xstart++ ) {//pixel loop - keep trim, can execute thousands of times per frame
- //boolean drawBlack = false; //used to display control points
- if(accurateMode){
- /* //Non-interpolating algorithm - slowest version, calculates exact coordinate for each pixel,
- //and casts from float->int
- float oneoverc = 65536.0f/c; //a bit faster to pre-divide for next two steps
- iu = (int)(a*oneoverc);
- iv = (int)(b*oneoverc);
- a += newax;
- b += newbx;
- c += newcx;
- */
-
- //Float while calculating, int while interpolating
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- //drawBlack = true;
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv; //ints are used for interpolation, not actual computation
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{ //race through using linear interpolation if we're not at a control point
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
-
- /* //Floating point interpolating version - slower than int thanks to casts during interpolation steps
- if (interpCounter == 0) {
- interpCounter = linearInterpLength;
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu;
- oldfv = fv;
- fu = (a*oneoverc);
- fv = (b*oneoverc);
- //oldu = u; oldv = v;
- fiu = oldfu;
- fiv = oldfv;
- fdeltaU = (fu-oldfu)/linearInterpLength;
- fdeltaV = (fv-oldfv)/linearInterpLength;
- }
- else{
- fiu += fdeltaU;
- fiv += fdeltaV;
- }
- interpCounter--;
- iu = (int)(fiu); iv = (int)(fiv);*/
-
- }
-
- // try-catch just in case pixel offset is out of range
- try{
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- m_zbuffer[xstart] = iz;
- if (m_bilinear) {
- //We could (should?) add bounds checking on iu and iv here (keep in mind the 16 bit shift!).
- //This would also be the place to add looping texture mode (bounds check == clamped).
- //For looping/clamped textures, we'd also need to change PGraphics.textureVertex() to remove
- //the texture range check there (it constrains normalized texture coordinates from 0->1).
-
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- //if(ofs < 0) { ofs += TEX_WIDTH; }
- //if(ofs > m_texture.length-2) {ofs -= TEX_WIDTH; }
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH; //quick hack to thwart exceptions
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- int red = up + (((dn-up) * ivi) >> 7);
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- int grn = up + (((dn-up) * ivi) >> 7);
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- int blu = up + (((dn-up) * ivi) >> 7);
-
- m_pixels[xstart] = (red & 0xFF0000) | (grn & 0xFF00) | (blu & 0xFF);
- //if (drawBlack){ m_pixels[xstart] = 0; }
-
- } else{
- m_pixels[xstart] = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- }
- m_stencil[xstart] = p;
- }
- } catch (Exception e) {/*exCount++;*/}
- iz+=izadd;
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- zleft+=zleftadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- }
-// if (exCount>0) System.out.println(exCount+" exceptions in this segment");
- }
-
-
- /**
- * Alpha 24-bit texture
- */
- private void drawsegment_texture24_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- // get alpha
- int al = ia >> 16;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- int red = up + (((dn-up) * ivi) >> 7);
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- int grn = up + (((dn-up) * ivi) >> 7);
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- int blu = up + (((dn-up) * ivi) >> 7);
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |( (bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- } else {
- int red = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- int grn = red & 0xFF00;
- int blu = red & 0xFF;
- red&=0xFF0000;
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- }
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {}
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ia+=iaadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
-
- ytop+=SCREEN_WIDTH;
-
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- zleft+=zleftadd;
- aleft+=aleftadd;
- }
- }
-
- /**
- * Plain 32-bit texutre
- */
- private void drawsegment_texture32
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- // try-catch just in case pixel offset it out of range
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- int red = up + (((dn-up) * ivi) >> 7);
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- int grn = up + (((dn-up) * ivi) >> 7);
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- int blu = up + (((dn-up) * ivi) >> 7);
-
- // alpha
- pix0>>>=24;
- pix2>>>=24;
- up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7);
- dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7);
- int al = up + (((dn-up) * ivi) >> 7);
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- } else {
- int red = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- int al = red >>> 24;
- int grn = red & 0xFF00;
- int blu = red & 0xFF;
- red&=0xFF0000;
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- }
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- iz+=izadd;
- }
- ypixel++;//accurate mode
-
- ytop+=SCREEN_WIDTH;
-
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- zleft+=zleftadd;
- aleft+=aleftadd;
- }
-
-
- }
-
- /**
- * Alpha 32-bit texutre
- */
- private void drawsegment_texture32_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
-
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- // try-catch just in case pixel offset it out of range
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- // get alpha
- int al = ia >> 16;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- int red = up + (((dn-up) * ivi) >> 7);
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- int grn = up + (((dn-up) * ivi) >> 7);
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- int blu = up + (((dn-up) * ivi) >> 7);
-
- // alpha
- pix0>>>=24;
- pix2>>>=24;
- up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7);
- dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7);
- al = al * (up + (((dn-up) * ivi) >> 7)) >> 8;
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- } else {
- int red = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- al = al * (red >>> 24) >> 8;
- int grn = red & 0xFF00;
- int blu = red & 0xFF;
- red&=0xFF0000;
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- }
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ia+=iaadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
-
- ytop+=SCREEN_WIDTH;
-
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- zleft+=zleftadd;
- aleft+=aleftadd;
- }
-
-
- }
-
-
- /**
- * Gouraud blended with 8-bit alpha texture
- */
- private void drawsegment_gouraud_texture8
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- int al0;
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = iu & 0xFFFF;
- al0 = m_texture[ofs] & 0xFF;
- int al1 = m_texture[ofs + 1] & 0xFF;
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int al2 = m_texture[ofs] & 0xFF;
- int al3 = m_texture[ofs + 1] & 0xFF;
- al0 = al0 + (((al1-al0) * iui) >> 16);
- al2 = al2 + (((al3-al2) * iui) >> 16);
- al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16);
- } else {
- al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF;
- }
-
- // get RGB colors
- int red = ir & 0xFF0000;
- int grn = (ig >> 8) & 0xFF00;
- int blu = (ib >> 16);
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al0) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al0) >> 8)) & 0xFF);
-
- // write stencil
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
-
- }
-
- //
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
-
- uleft+=uleftadd;
- vleft+=vleftadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * Texture multiplied with gouraud
- */
- private void drawsegment_gouraud_texture8_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- int al0;
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = iu & 0xFFFF;
- al0 = m_texture[ofs] & 0xFF;
- int al1 = m_texture[ofs + 1] & 0xFF;
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int al2 = m_texture[ofs] & 0xFF;
- int al3 = m_texture[ofs + 1] & 0xFF;
- al0 = al0 + (((al1-al0) * iui) >> 16);
- al2 = al2 + (((al3-al2) * iui) >> 16);
- al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16);
- } else {
- al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF;
- }
- al0 = (al0 * (ia >> 16)) >> 8;
-
- // get RGB colors
- int red = ir & 0xFF0000;
- int grn = (ig >> 8) & 0xFF00;
- int blu = (ib >> 16);
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
- m_pixels[xstart] = ((br + (((red - br) * al0) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al0) >> 8)) & 0xFF);
-
- // write stencil
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
-
- }
-
- //
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- ia+=iaadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- aleft+=aleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * Texture multiplied with gouraud
- */
- private void drawsegment_gouraud_texture24
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- m_zbuffer[xstart] = iz;
-
- int red;
- int grn;
- int blu;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- red = up + (((dn-up) * ivi) >> 7);
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- grn = up + (((dn-up) * ivi) >> 7);
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- blu = up + (((dn-up) * ivi) >> 7);
- } else {
- // get texture pixel color
- blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- red = (blu & 0xFF0000);
- grn = (blu & 0xFF00);
- blu = blu & 0xFF;
- }
-
- //
- int r = (ir >> 16);
- int g = (ig >> 16);
- int bb2 = (ib >> 16); //oops, namespace collision with accurate texture vector b...sorry [ewjordan]
-
- //
- m_pixels[xstart] = ( ((red * r) & 0xFF000000) | ((grn * g) & 0xFF0000) | (blu * bb2) ) >> 8;
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
-
- //
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
-
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * Gouraud*texture blended with interpolating alpha
- */
- private void drawsegment_gouraud_texture24_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
-
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
-
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
- for ( ;xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- // get texture pixel color
- try
- {
- //if (iz < m_zbuffer[xstart]) {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) { // [fry 041114]
- //m_zbuffer[xstart] = iz;
-
- // blend
- int al = ia >> 16;
-
- int red;
- int grn;
- int blu;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- red = (up + (((dn-up) * ivi) >> 7)) >> 16;
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- grn = (up + (((dn-up) * ivi) >> 7)) >> 8;
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- blu = up + (((dn-up) * ivi) >> 7);
- } else {
- blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- red = (blu & 0xFF0000) >> 16; // 0 - 255
- grn = (blu & 0xFF00) >> 8; // 0 - 255
- blu = (blu & 0xFF); // 0 - 255
- }
-
- // multiply with gouraud color
- red = (red * ir) >>> 8; // 0x00FF????
- grn = (grn * ig) >>> 16; // 0x0000FF??
- blu = (blu * ib) >>> 24; // 0x000000FF
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
-
- //
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
-
- //
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- ia+=iaadd;
- iz+=izadd;
- }
-
- ypixel++;//accurate mode
-
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- aleft+=aleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * Gouraud*texture blended with interpolating alpha
- */
- private void drawsegment_gouraud_texture32
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
-
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- //int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
-
- for ( ; xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- try
- {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) {
- //m_zbuffer[xstart] = iz;
-
- int red;
- int grn;
- int blu;
- int al;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- red = (up + (((dn-up) * ivi) >> 7)) >> 16;
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- grn = (up + (((dn-up) * ivi) >> 7)) >> 8;
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- blu = up + (((dn-up) * ivi) >> 7);
-
- // alpha
- pix0>>>=24;
- pix2>>>=24;
- up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7);
- dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7);
- al = up + (((dn-up) * ivi) >> 7);
- } else {
- // get texture pixel color
- blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- al = (blu >>> 24);
- red = (blu & 0xFF0000) >> 16;
- grn = (blu & 0xFF00) >> 8;
- blu = blu & 0xFF;
- }
-
- // multiply with gouraud color
- red = (red * ir) >>> 8; // 0x00FF????
- grn = (grn * ig) >>> 16; // 0x0000FF??
- blu = (blu * ib) >>> 24; // 0x000000FF
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
-
- //
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- }
- }
- catch (Exception e) {
- }
-
- //
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- zleft+=zleftadd;
- }
- }
-
-
- /**
- * Gouraud*texture blended with interpolating alpha
- */
- private void drawsegment_gouraud_texture32_alpha
- (
- float leftadd,
- float rghtadd,
- int ytop,
- int ybottom
- ) {
- //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details
- int ypixel = ytop;
- int lastRowStart = m_texture.length - TEX_WIDTH - 2;
- boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES];
- float screenx = 0; float screeny = 0; float screenz = 0;
- float a = 0; float b = 0; float c = 0;
- int linearInterpPower = TEX_INTERP_POWER;
- int linearInterpLength = 1 << linearInterpPower;
- if (accurateMode){
- if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup
- newax *= linearInterpLength;
- newbx *= linearInterpLength;
- newcx *= linearInterpLength;
- screenz = nearPlaneDepth;
- firstSegment = false;
- } else{
- accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate)
- }
- }
-
- ytop*=SCREEN_WIDTH;
- ybottom*=SCREEN_WIDTH;
- int p = m_index;
-
- float iuf = iuadd;
- float ivf = ivadd;
- float irf = iradd;
- float igf = igadd;
- float ibf = ibadd;
- float iaf = iaadd;
-
- while (ytop < ybottom) {
- int xstart = (int) (xleft + PIXEL_CENTER);
- if (xstart < 0)
- xstart = 0;
-
- int xpixel = xstart;//accurate mode
-
- int xend = (int) (xrght + PIXEL_CENTER);
- if (xend > SCREEN_WIDTH)
- xend = SCREEN_WIDTH;
- float xdiff = (xstart + PIXEL_CENTER) - xleft;
-
- int iu = (int) (iuf * xdiff + uleft);
- int iv = (int) (ivf * xdiff + vleft);
- int ir = (int) (irf * xdiff + rleft);
- int ig = (int) (igf * xdiff + gleft);
- int ib = (int) (ibf * xdiff + bleft);
- int ia = (int) (iaf * xdiff + aleft);
- float iz = izadd * xdiff + zleft;
-
- xstart+=ytop;
- xend+=ytop;
- if (accurateMode){
- screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f));
- screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f));
- a = screenx*ax+screeny*ay+screenz*az;
- b = screenx*bx+screeny*by+screenz*bz;
- c = screenx*cx+screeny*cy+screenz*cz;
- }
- boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true;
- int interpCounter = 0;
- int deltaU = 0; int deltaV = 0;
- float fu = 0; float fv = 0;
- float oldfu = 0; float oldfv = 0;
-
- if (accurateMode&&goingIn){
- int rightOffset = (xend-xstart-1)%linearInterpLength;
- int leftOffset = linearInterpLength-rightOffset;
- float rightOffset2 = rightOffset / ((float)linearInterpLength);
- float leftOffset2 = leftOffset / ((float)linearInterpLength);
- interpCounter = leftOffset;
- float ao = a-leftOffset2*newax;
- float bo = b-leftOffset2*newbx;
- float co = c-leftOffset2*newcx;
- float oneoverc = 65536.0f/co;
- oldfu = (ao*oneoverc); oldfv = (bo*oneoverc);
- a += rightOffset2*newax;
- b += rightOffset2*newbx;
- c += rightOffset2*newcx;
- oneoverc = 65536.0f/c;
- fu = a*oneoverc; fv = b*oneoverc;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack
- } else{
- float preoneoverc = 65536.0f/c;
- fu = (a*preoneoverc);
- fv = (b*preoneoverc);
- }
-
- for ( ;xstart < xend; xstart++ ) {
- if(accurateMode){
- if (interpCounter == linearInterpLength) interpCounter = 0;
- if (interpCounter == 0){
- a += newax;
- b += newbx;
- c += newcx;
- float oneoverc = 65536.0f/c;
- oldfu = fu; oldfv = fv;
- fu = (a*oneoverc); fv = (b*oneoverc);
- iu = (int)oldfu; iv = (int)oldfv;
- deltaU = ((int)(fu - oldfu)) >> linearInterpPower;
- deltaV = ((int)(fv - oldfv)) >> linearInterpPower;
- } else{
- iu += deltaU;
- iv += deltaV;
- }
- interpCounter++;
- }
-
- // get texture pixel color
- try
- {
- //if (iz < m_zbuffer[xstart]) {
- if (noDepthTest || (iz <= m_zbuffer[xstart])) { // [fry 041114]
- //m_zbuffer[xstart] = iz;
-
- // blend
- int al = ia >> 16;
-
- int red;
- int grn;
- int blu;
-
- if (m_bilinear) {
- int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16);
- int iui = (iu & 0xFFFF) >> 9;
- int ivi = (iv & 0xFFFF) >> 9;
-
- // get texture pixels
- int pix0 = m_texture[ofs];
- int pix1 = m_texture[ofs + 1];
- if (ofs < lastRowStart) ofs+=TEX_WIDTH;
- int pix2 = m_texture[ofs];
- int pix3 = m_texture[ofs + 1];
-
- // red
- int red0 = (pix0 & 0xFF0000);
- int red2 = (pix2 & 0xFF0000);
- int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7);
- int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7);
- red = (up + (((dn-up) * ivi) >> 7)) >> 16;
-
- // grn
- red0 = (pix0 & 0xFF00);
- red2 = (pix2 & 0xFF00);
- up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7);
- grn = (up + (((dn-up) * ivi) >> 7)) >> 8;
-
- // blu
- red0 = (pix0 & 0xFF);
- red2 = (pix2 & 0xFF);
- up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7);
- dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7);
- blu = up + (((dn-up) * ivi) >> 7);
-
- // alpha
- pix0>>>=24;
- pix2>>>=24;
- up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7);
- dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7);
- al = al * (up + (((dn-up) * ivi) >> 7)) >> 8;
- } else {
- blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)];
- al = al * (blu >>> 24) >> 8;
- red = (blu & 0xFF0000) >> 16; // 0 - 255
- grn = (blu & 0xFF00) >> 8; // 0 - 255
- blu = (blu & 0xFF); // 0 - 255
- }
-
- // multiply with gouraud color
- red = (red * ir) >>> 8; // 0x00FF????
- grn = (grn * ig) >>> 16; // 0x0000FF??
- blu = (blu * ib) >>> 24; // 0x000000FF
-
- // get buffer pixels
- int bb = m_pixels[xstart];
- int br = (bb & 0xFF0000); // 0x00FF0000
- int bg = (bb & 0xFF00); // 0x0000FF00
- bb = (bb & 0xFF); // 0x000000FF
-
- //
- m_pixels[xstart] = ((br + (((red - br) * al) >> 8)) & 0xFF0000) |((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | ((bb + (((blu - bb) * al) >> 8)) & 0xFF);
- m_stencil[xstart] = p;
- }
- }
- catch (Exception e) {
- }
-
- //
- xpixel++;//accurate mode
- if (!accurateMode){
- iu+=iuadd;
- iv+=ivadd;
- }
- ir+=iradd;
- ig+=igadd;
- ib+=ibadd;
- ia+=iaadd;
- iz+=izadd;
- }
- ypixel++;//accurate mode
- ytop+=SCREEN_WIDTH;
- xleft+=leftadd;
- xrght+=rghtadd;
- uleft+=uleftadd;
- vleft+=vleftadd;
- rleft+=rleftadd;
- gleft+=gleftadd;
- bleft+=bleftadd;
- aleft+=aleftadd;
- zleft+=zleftadd;
- }
- }
-}
diff --git a/core/api.txt b/core/api.txt
new file mode 100644
index 000000000..4b2746f8b
--- /dev/null
+++ b/core/api.txt
@@ -0,0 +1,413 @@
+
+ public void setParent(PApplet parent)
+ public void setPrimary(boolean primary)
+ public void setPath(String path)
+ public void setSize(int iwidth, int iheight)
+ protected void allocate()
+ public void dispose()
+
+ public boolean canDraw()
+ public void beginDraw()
+ public void endDraw()
+
+ protected void checkSettings()
+ protected void defaultSettings()
+ protected void reapplySettings()
+
+ public void hint(int which)
+
+ public void beginShape()
+ public void beginShape(int kind)
+ public void edge(boolean e)
+ public void normal(float nx, float ny, float nz)
+ public void textureMode(int mode)
+ public void texture(PImage image)
+ public void vertex(float x, float y)
+ public void vertex(float x, float y, float z)
+ public void vertex(float x, float y, float u, float v)
+ public void vertex(float x, float y, float z, float u, float v)
+ protected void vertexTexture(float u, float v);
+ public void breakShape()
+ public void endShape()
+ public void endShape(int mode)
+
+ protected void bezierVertexCheck();
+ public void bezierVertex(float x2, float y2,
+ float x3, float y3,
+ float x4, float y4)
+ public void bezierVertex(float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4)
+
+ protected void curveVertexCheck();
+ public void curveVertex(float x, float y)
+ public void curveVertex(float x, float y, float z)
+ protected void curveVertexSegment(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3,
+ float x4, float y4)
+ protected void curveVertexSegment(float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4)
+
+ protected void renderPoints(int start, int stop) // P3D
+ protected void rawPoints(int start, int stop) // P3D
+
+ protected void renderLines(int start, int stop) // P3D
+ protected void rawLines(int start, int stop) // P3D
+
+ protected void renderTriangles(int start, int stop) // P3D
+ protected void rawTriangles(int start, int stop) // P3D
+
+ public void flush()
+ protected void render()
+ proected void sort()
+
+ public void point(float x, float y)
+ public void point(float x, float y, float z)
+ public void line(float x1, float y1, float x2, float y2)
+ public void line(float x1, float y1, float z1,
+ float x2, float y2, float z2)
+ public void triangle(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3)
+ public void quad(float x1, float y1, float x2, float y2,
+ float x3, float y3, float x4, float y4)
+
+ public void rectMode(int mode)
+ public void rect(float a, float b, float c, float d)
+ protected void rectImpl(float x1, float y1, float x2, float y2)
+
+ public void ellipseMode(int mode)
+ public void ellipse(float a, float b, float c, float d)
+ protected void ellipseImpl(float x, float y, float w, float h)
+
+ public void arc(float a, float b, float c, float d,
+ float start, float stop)
+ protected void arcImpl(float x, float y, float w, float h,
+ float start, float stop)
+
+ public void box(float size)
+ public void box(float w, float h, float d)
+
+ public void sphereDetail(int res)
+ public void sphereDetail(int ures, int vres)
+ public void sphere(float r)
+
+ public float bezierPoint(float a, float b, float c, float d, float t)
+ public float bezierTangent(float a, float b, float c, float d, float t)
+ protected void bezierInitCheck()
+ protected void bezierInit()
+ public void bezierDetail(int detail)
+ public void bezier(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3,
+ float x4, float y4)
+ public void bezier(float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4)
+
+ public float curvePoint(float a, float b, float c, float d, float t)
+ public float curveTangent(float a, float b, float c, float d, float t)
+ public void curveDetail(int detail)
+ public void curveTightness(float tightness)
+ protected void curveInitCheck()
+ protected void curveInit()
+ public void curve(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3,
+ float x4, float y4)
+ public void curve(float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4)
+
+ protected void splineForward(int segments, PMatrix3D matrix)
+
+ public void smooth()
+ public void noSmooth()
+
+ public void imageMode(int mode)
+ public void image(PImage image, float x, float y)
+ public void image(PImage image, float x, float y, float c, float d)
+ public void image(PImage image,
+ float a, float b, float c, float d,
+ int u1, int v1, int u2, int v2)
+ protected void imageImpl(PImage image,
+ float x1, float y1, float x2, float y2,
+ int u1, int v1, int u2, int v2)
+
+ public void shapeMode(int mode)
+ public void shape(PShape shape)
+ public void shape(PShape shape, float x, float y)
+ public void shape(PShape shape, float x, float y, float c, float d)
+
+ public void textAlign(int align)
+ public void textAlign(int alignX, int alignY)
+ public float textAscent()
+ public float textDescent()
+ public void textFont(PFont which)
+ public void textFont(PFont which, float size)
+ public void textLeading(float leading)
+ public void textMode(int mode)
+ protected boolean textModeCheck(int mode)
+ public void textSize(float size)
+ public float textWidth(char c)
+ public float textWidth(String str)
+ protected float textWidthImpl(char buffer[], int start, int stop)
+
+ public void text(char c)
+ public void text(char c, float x, float y)
+ public void text(char c, float x, float y, float z)
+ public void text(String str)
+ public void text(String str, float x, float y)
+ public void text(String str, float x, float y, float z)
+ public void text(String str, float x1, float y1, float x2, float y2)
+ public void text(String s, float x1, float y1, float x2, float y2, float z)
+ public void text(int num, float x, float y)
+ public void text(int num, float x, float y, float z)
+ public void text(float num, float x, float y)
+ public void text(float num, float x, float y, float z)
+
+ protected void textLineAlignImpl(char buffer[], int start, int stop,
+ float x, float y)
+ protected void textLineImpl(char buffer[], int start, int stop,
+ float x, float y)
+ protected void textCharImpl(char ch, float x, float y)
+ protected void textCharModelImpl(PImage glyph,
+ float x1, float y1, //float z1,
+ float x2, float y2, //float z2,
+ int u2, int v2)
+ protected void textCharScreenImpl(PImage glyph,
+ int xx, int yy,
+ int w0, int h0)
+
+ public void pushMatrix()
+ public void popMatrix()
+
+ public void translate(float tx, float ty)
+ public void translate(float tx, float ty, float tz)
+ public void rotate(float angle)
+ public void rotateX(float angle)
+ public void rotateY(float angle)
+ public void rotateZ(float angle)
+ public void rotate(float angle, float vx, float vy, float vz)
+ public void scale(float s)
+ public void scale(float sx, float sy)
+ public void scale(float x, float y, float z)
+
+ public void resetMatrix()
+ public void applyMatrix(PMatrix2D source)
+ public void applyMatrix(float n00, float n01, float n02,
+ float n10, float n11, float n12)
+ public void applyMatrix(PMatrix3D source)
+ public void applyMatrix(float n00, float n01, float n02, float n03,
+ float n10, float n11, float n12, float n13,
+ float n20, float n21, float n22, float n23,
+ float n30, float n31, float n32, float n33)
+
+ public getMatrix(PMatrix2D target)
+ public getMatrix(PMatrix3D target)
+ public void setMatrix(PMatrix2D source)
+ public void setMatrix(PMatrix3D source)
+ public void printMatrix()
+
+ public void beginCamera()
+ public void endCamera()
+ public void camera()
+ public void camera(float eyeX, float eyeY, float eyeZ,
+ float centerX, float centerY, float centerZ,
+ float upX, float upY, float upZ)
+ public void printCamera()
+
+ public void ortho()
+ public void ortho(float left, float right,
+ float bottom, float top,
+ float near, float far)
+ public void perspective()
+ public void perspective(float fov, float aspect, float near, float far)
+ public void frustum(float left, float right,
+ float bottom, float top,
+ float near, float far)
+ public void printProjection()
+
+ public float screenX(float x, float y)
+ public float screenY(float x, float y)
+ public float screenX(float x, float y, float z)
+ public float screenY(float x, float y, float z)
+ public float screenZ(float x, float y, float z)
+ public float modelX(float x, float y, float z)
+ public float modelY(float x, float y, float z)
+ public float modelZ(float x, float y, float z)
+
+ public void pushStyle()
+ public void popStyle()
+ public void style(PStyle)
+ public PStyle getStyle()
+ public void getStyle(PStyle)
+
+ public void strokeCap(int cap)
+ public void strokeJoin(int join)
+ public void strokeWeight(float weight)
+
+ public void noStroke()
+ public void stroke(int rgb)
+ public void stroke(int rgb, float alpha)
+ public void stroke(float gray)
+ public void stroke(float gray, float alpha)
+ public void stroke(float x, float y, float z)
+ public void stroke(float x, float y, float z, float a)
+ protected void strokeFromCalc()
+
+ public void noTint()
+ public void tint(int rgb)
+ public void tint(int rgb, float alpha)
+ public void tint(float gray)
+ public void tint(float gray, float alpha)
+ public void tint(float x, float y, float z)
+ public void tint(float x, float y, float z, float a)
+ protected void tintFromCalc()
+
+ public void noFill()
+ public void fill(int rgb)
+ public void fill(int rgb, float alpha)
+ public void fill(float gray)
+ public void fill(float gray, float alpha)
+ public void fill(float x, float y, float z)
+ public void fill(float x, float y, float z, float a)
+ protected void fillFromCalc()
+
+ public void ambient(int rgb)
+ public void ambient(float gray)
+ public void ambient(float x, float y, float z)
+ protected void ambientFromCalc()
+ public void specular(int rgb)
+ public void specular(float gray)
+ public void specular(float x, float y, float z)
+ protected void specularFromCalc()
+ public void shininess(float shine)
+ public void emissive(int rgb)
+ public void emissive(float gray)
+ public void emissive(float x, float y, float z )
+ protected void emissiveFromCalc()
+
+ public void lights()
+ public void noLights()
+ public void ambientLight(float red, float green, float blue)
+ public void ambientLight(float red, float green, float blue,
+ float x, float y, float z)
+ public void directionalLight(float red, float green, float blue,
+ float nx, float ny, float nz)
+ public void pointLight(float red, float green, float blue,
+ float x, float y, float z)
+ public void spotLight(float red, float green, float blue,
+ float x, float y, float z,
+ float nx, float ny, float nz,
+ float angle, float concentration)
+ public void lightFalloff(float constant, float linear, float quadratic)
+ public void lightSpecular(float x, float y, float z)
+ protected void lightPosition(int num, float x, float y, float z)
+ protected void lightDirection(int num, float x, float y, float z)
+
+ public void background(int rgb)
+ public void background(int rgb, float alpha)
+ public void background(float gray)
+ public void background(float gray, float alpha)
+ public void background(float x, float y, float z)
+ public void background(float x, float y, float z, float a)
+ public void background(PImage image)
+ protected void backgroundFromCalc()
+ protected void backgroundImpl(PImage image)
+ protected void backgroundImpl()
+
+ public void colorMode(int mode)
+ public void colorMode(int mode, float max)
+ public void colorMode(int mode, float maxX, float maxY, float maxZ)
+ public void colorMode(int mode, float maxX, float maxY, float maxZ, float maxA)
+
+ protected void colorCalc(int rgb)
+ protected void colorCalc(int rgb, float alpha)
+ protected void colorCalc(float gray)
+ protected void colorCalc(float gray, float alpha)
+ protected void colorCalc(float x, float y, float z)
+ protected void colorCalc(float x, float y, float z, float a)
+ protected void colorCalcARGB(int argb, float alpha)
+
+ public final int color(int gray)
+ public final int color(int gray, int alpha)
+ public final int color(int rgb, float alpha)
+ public final int color(int x, int y, int z)
+
+ public final float alpha(int what)
+ public final float red(int what)
+ public final float green(int what)
+ public final float blue(int what)
+ public final float hue(int what)
+ public final float saturation(int what)
+ public final float brightness(int what)
+
+ public int lerpColor(int c1, int c2, float amt)
+ static public int lerpColor(int c1, int c2, float amt, int mode)
+
+ public void beginRaw(PGraphics rawGraphics)
+ public void endRaw()
+
+ static public void showWarning(String msg)
+ static public void showException(String msg)
+
+ public boolean displayable()
+ public boolean is2D()
+ public boolean is3D()
+
+//
+
+These are the methods found in PImage, which are inherited by PGraphics.
+
+ public PImage(Image)
+ public Image getImage()
+
+ public void setCache(Object parent, Object storage)
+ public void getCache(Object parent)
+ public void removeCache(Object parent)
+
+ public boolean isModified();
+ public void setModified();
+ public void setModified(boolean state);
+
+ public void loadPixels()
+ public void updatePixels()
+ public void updatePixels(int x, int y, int w, int h)
+
+ public void resize(int wide, int high)
+
+ public int get(int x, int y)
+ public PImage get(int x, int y, int w, int h)
+ protected PImage getImpl(int x, int y, int w, int h)
+ public PImage get()
+ public void set(int x, int y, int c)
+ public void set(int x, int y, PImage src)
+ protected void setImpl(int dx, int dy, int sx, int sy, int sw, int sh,
+ PImage src)
+
+ public void mask(int alpha[])
+ public void mask(PImage alpha)
+
+ public void filter(int kind)
+ public void filter(int kind, float param)
+
+ public void copy(int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh)
+ public void copy(PImage src,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh)
+
+ static public int blendColor(int c1, int c2, int mode)
+ public void blend(int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh, int mode)
+ public void blend(PImage src,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh, int mode)
+
+ public void save(String path)
diff --git a/core/done.txt b/core/done.txt
new file mode 100644
index 000000000..e2eb2ec90
--- /dev/null
+++ b/core/done.txt
@@ -0,0 +1,2878 @@
+0164 core (1.0.2)
+X requestImage() causing problems with JAVA2D
+X fix minor strokeWeight bug with OpenGL
+X text() with char array
+o add documentation
+o add this for text in a rectangle?
+X minor bug fix to svg files that weren't being resized properly
+X OpenGL is rendering darker in 0149+
+X http://dev.processing.org/bugs/show_bug.cgi?id=958
+X the fix has been found, just incorporate it
+X thanks to dave bollinger
+X OutOfMemoryError with ellipse() in P3D and OPENGL
+X http://dev.processing.org/bugs/show_bug.cgi?id=1086
+X should also fix problem with AIOOBE
+X http://dev.processing.org/bugs/show_bug.cgi?id=1117
+X point(x,y) ignores noStroke() (in some renderers)
+X http://dev.processing.org/bugs/show_bug.cgi?id=1090
+X fix startup problem when scheme coloring was odd
+X http://dev.processing.org/bugs/show_bug.cgi?id=1109
+X fix several point() problems with P3D
+X http://dev.processing.org/bugs/show_bug.cgi?id=1110
+X nextPage() not working properly with PDF as the renderer
+X http://dev.processing.org/bugs/show_bug.cgi?id=1131
+X save styles when nextPage() is called
+X beginRaw() broken (no DXF, etc working)
+X http://dev.processing.org/bugs/show_bug.cgi?id=1099
+X http://dev.processing.org/bugs/show_bug.cgi?id=1144
+X Fix algorithm for quadratic to cubic curve conversion
+X wrong algorithm in PGraphicsOpenGL and PShapeSVG
+X (thanks to user 'shambles')
+X http://dev.processing.org/bugs/show_bug.cgi?id=1122
+X tint() not working in P2D
+X http://dev.processing.org/bugs/show_bug.cgi?id=1132
+X blend() y coordinates inverted when using OpenGL
+X http://dev.processing.org/bugs/show_bug.cgi?id=1137
+
+invalid/wontfix/dupe
+X Processing will not start with non-standard disk partitioning on OS X
+X http://dev.processing.org/bugs/show_bug.cgi?id=1127
+X Got NoClassDefFoundError exception when accessing quicktime API
+X http://dev.processing.org/bugs/show_bug.cgi?id=1128
+X http://dev.processing.org/bugs/show_bug.cgi?id=1129
+X http://dev.processing.org/bugs/show_bug.cgi?id=1130
+X not using present mode correctly
+X http://dev.processing.org/bugs/show_bug.cgi?id=1138
+X apparent graphics driver conflict on vista
+X http://dev.processing.org/bugs/show_bug.cgi?id=1140
+X PImage.save() does not create parent directories
+X http://dev.processing.org/bugs/show_bug.cgi?id=1124
+X sketch turning blue and not working on osx
+X http://dev.processing.org/bugs/show_bug.cgi?id=1164
+X dupe: blend() inaccurary
+X http://dev.processing.org/bugs/show_bug.cgi?id=1008
+X glPushAttrib style function
+X http://dev.processing.org/bugs/show_bug.cgi?id=1150
+X calling saveFrame() in noLoop() (update reference)
+X http://dev.processing.org/bugs/show_bug.cgi?id=1155
+
+xml
+X fix for xml elements that have null names
+X added listChildren() method
+X added optional toString(boolean) parameter to enable/disable indents
+
+
+0163 core (1.0.1)
+X do not parse split() with regexp
+X http://dev.processing.org/bugs/show_bug.cgi?id=1060
+X ArrayIndexOutOfBoundsException in ellipseImpl() with 1.0
+X http://dev.processing.org/bugs/show_bug.cgi?id=1068
+
+
+0162 core (1.0)
+X no additional changes for 1.0
+
+
+0161 core
+X present on macosx causing strange flicker/jump while window opens
+X using validate() for present mode, pack() otherwise
+X http://dev.processing.org/bugs/show_bug.cgi?id=1051
+
+
+0160 core
+X stroked lines drawing on top of everything else in P3D
+X http://dev.processing.org/bugs/show_bug.cgi?id=1032
+X 100x100 sketches not working
+
+
+0159 core
+o disable present mode? (weirdness with placements on mac)
+X deal with some present mode issues
+X use FSE on mac within the PDE
+X when exporting, never use FSE
+_ document changes re: can specify --exclusive on command line
+X do we need to do glEnable for multisample with gl?
+o just need to test this on a few platforms
+X doesn't seem to be the case
+X Present mode and OPENGL not working in 0156 with Windows Vista
+X http://dev.processing.org/bugs/show_bug.cgi?id=1009
+X Seems to be limited to Java 6u10 (but verify)
+o -Dsun.java2d.d3d=false seems to fix the problem
+o can probably add that to PApplet.main()
+X does not work
+
+
+0158 core
+X beginShape(TRIANGLE_FAN), and therefore arc(), broken in P2D
+X also a typo in the ColorWheel example
+X http://dev.processing.org/bugs/show_bug.cgi?id=1019
+X P2D - null pointer exception drawing line with alpha stroke
+X http://dev.processing.org/bugs/show_bug.cgi?id=1023
+X P2D endShape() is working like endShape(CLOSE)
+X http://dev.processing.org/bugs/show_bug.cgi?id=1021
+X http://dev.processing.org/bugs/show_bug.cgi?id=1028 (mark as dupe)
+X arc() center transparent
+X http://dev.processing.org/bugs/show_bug.cgi?id=1027
+X mark as dupe of bug #200
+X but fixed for the P2D case, still afflicts P2D
+X P2D - alpha stroke rendered at full opacity
+X http://dev.processing.org/bugs/show_bug.cgi?id=1024
+X smooth() on single line ellipses not coming out smooth
+X sort of works, just not great
+X improve (slightly) the quality of ellipse() and arc() with P2D
+X don't use TRIANGLE_FAN on ellipseImpl() and arcImpl() with P2D
+X split out ellipseImpl and arcImpl from PGraphics into P2D and P3D
+X figure out better model for adaptive sizing of circles
+X also goes for arcs, though will be weighted based on arc size
+X Bring back CENTER_RADIUS but deprecate it
+X http://dev.processing.org/bugs/show_bug.cgi?id=1035
+X enable smoothing by default in opengl
+X change hints to instead only be able to DISABLE 2X or 4X
+X bring back .width and .height fields for PShape
+o need to update the examples to reflect
+X no examples to update
+X change reference re: smoothing in opengl
+X hint(), smooth(), and size()
+X rev the version number
+
+
+0157 core
+X SVG polygon shapes not drawing since loadShape() and PShape changes
+X http://dev.processing.org/bugs/show_bug.cgi?id=1005
+X image(a, x, y) not honoring imageMode(CENTER)
+X need to just pass image(a, x, y) to image(a, x, y, a.width, a.height)
+X rather than passing it directly to imageImpl()
+X http://dev.processing.org/bugs/show_bug.cgi?id=1013
+o disable P2D before releasing (unless implementation is finished)
+
+
+0156 core
+X clarify the "no variables in size() command" rule
+X http://dev.processing.org/bugs/show_bug.cgi?id=992
+X present mode broken in general?
+X placement of elements in present mode is messed up
+X "stop" button hops around, window not centered on screen
+X http://dev.processing.org/bugs/show_bug.cgi?id=923
+X disable P2D for size() and createGraphics() before releasing
+X already was disabled, just a bug in detecting it
+
+
+0155 core
+X hint(DISABLE_DEPTH_TEST) throws null pointer exception with OpenGL
+X http://dev.processing.org/bugs/show_bug.cgi?id=984
+
+
+0154 core
+X only set apple.awt.graphics.UseQuartz on osx, otherwise security error
+X http://dev.processing.org/bugs/show_bug.cgi?id=976
+X add skewX() and skewY() to PMatrix
+X Add support style attribute for path tag to Candy SVG (ricard)
+X http://dev.processing.org/bugs/show_bug.cgi?id=771
+X remove setX/Y/Z from PVector, copy() (use get() instead), add mult/div
+X remove copy() from PVector?
+X add mult() and div() with vector inputs?
+
+
+0153 core
+X make PImage.init() public again
+
+
+0152 core
+X no changes to 0152 core
+
+
+0151 core
+X NullPointerException on curveVertex() when using more than 128 vertices
+X http://dev.processing.org/bugs/show_bug.cgi?id=952
+X Text not bounding correctly with x, y, w, h
+X http://dev.processing.org/bugs/show_bug.cgi?id=954
+o dataFolder() might be flawed b/c it's referring to contents of jar file
+o for input, better to use openStream
+X clear up the javadoc on this
+X odd-size height will make blue line across image in saveFrame()
+X http://dev.processing.org/bugs/show_bug.cgi?id=944
+X probably the pixel flipping code (and endian sorting) not happening
+X because the blue comes from the byte order flip
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=post;num=1219196429
+X ArrayIndexOutOfBoundsException in PLine
+X http://dev.processing.org/bugs/show_bug.cgi?id=246
+X http://dev.processing.org/bugs/show_bug.cgi?id=462
+X random AIOOBE with P3D and points
+X http://dev.processing.org/bugs/show_bug.cgi?id=937
+
+cleanup
+X alter bezier and curve matrices to use PMatrix
+X float array stuff is redundant with code that's in PMatrix
+X and PMatrix has to be included even w/o P3D so...
+X add texture support to begin/endRaw
+X should we do joins when alpha is turned off?
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=display;num=1210007450
+X no, because it's too processor intensive to draw a lotta ellipses
+X but added a note about it to the reference for 0151
+X strokeWeight() doesn't work in opengl or p3d
+o gl smoothing.. how to disable polygon but keep line enabled
+o or at least make a note of this?
+o leave smooth off, get the gl object, then enable line smooth
+X don't bother, this is a workaround for another bug
+o PPolygon no longer in use and PLine is a mess
+o make a version of PGraphics3 that uses it for more accurate rendering?
+
+
+0150 core
+X no changes to processing.core in 0150
+
+
+0149 core
+X remove MACOS9 constant from processing.core.*
+X because code no longer runs on os9 since dropping 1.1 support
+X specular() with alpha has been removed
+X GLDrawableFactory.chooseGraphicsConfiguration() error with OpenGL
+X http://dev.processing.org/bugs/show_bug.cgi?id=891
+X http://dev.processing.org/bugs/show_bug.cgi?id=908
+X fix problem with unregisterXxxx()
+X http://dev.processing.org/bugs/show_bug.cgi?id=910
+X make parseFloat() with String[] array return NaN for missing values
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1220880375
+X fix problems with text in a rectangle
+X http://dev.processing.org/bugs/show_bug.cgi?id=893
+X http://dev.processing.org/bugs/show_bug.cgi?id=899
+X finish getImage() method inside PImage
+X delay() is broken
+X http://dev.processing.org/bugs/show_bug.cgi?id=894
+X remove extra ~ files from core.jar
+X also fix for other libraries in the make scripts across platforms
+X fix problems in PApplet regarding signed code
+X createInput() wasn't bothering to check files when not online
+X unhint() has been removed, see the reference for hint() for changes
+o enable() and disable() instead of hint()/unhint()
+o should these use text strings? how will that be compiled?
+X remove unhint(), add opposite hints for those that need to be disabled
+o maybe update hint() ref to be more clear about screen not accumulating
+X no, it's explicitly stated as such
+X make decisions about whether PGraphics is an abstract class or not
+X method signature is a real problem
+X figure out how to handle constructor mess
+X clean up setMainDrawingSurface()
+X should instead be inside size(), and init(), no?
+X add to hint(DISABLE_DEPTH_TEST)
+X gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
+X or clearing the zbuffer for P3D
+X also add a note to the hint() reference
+X DISABLE_DEPTH_TEST bad results
+X have to clear the zbuffer to make it work
+X this may be specific to lines
+X http://dev.processing.org/bugs/show_bug.cgi?id=827
+X though it also seems to be a problem with opengl
+X also make a note of disabling as a way to help font appearance
+o Font width calculation fails when using vectorfonts and PDF
+o http://dev.processing.org/bugs/show_bug.cgi?id=920
+X um, this is gross: getMatrix((PMatrix2D) null)
+X no changing point sizes when using beginShape(POINTS)
+X this is an opengl restriction, should we stick with it elsewhere?
+X and changing stroke weight in general (with lines/shapes)
+o no renderer does this, we should probably disable it
+X added a note to the reference about it
+X may need to add to PApplet.main() for OS X 10.5
+X System.setProperty("apple.awt.graphics.UseQuartz", "true");
+X deprecate arraycopy(), change to arrayCopy()
+
+cleaning
+o chooseFile() and chooseFolder() with named fxn callbacks
+o the function must take a File object as a parameter
+o add better error messages for all built-in renderers
+o i.e. "import library -> pdf" when pdf is missing
+o cameraXYZ doesn't seem to actually be used for anything
+o since camera functions don't even look at it or set it
+o registerSize() in arcball is causing trouble
+o some sort of infinite loop issue
+o textMode(SCREEN) is broken for opengl
+o http://dev.processing.org/bugs/show_bug.cgi?id=426
+o textSpace(SCREEN) for opengl and java2d
+o don't use loadPixels for either
+o use font code to set the cached color of the font, then call set()
+o although set() with alpha is a little different..
+o resizing opengl applet likely to cause big trouble
+o componentlistener should prolly only do size() command outside of draw
+o fjen says blend() doens't work in JAVA2D
+o the functions are fairly well separated now in PMethods
+o just go through all the stuff to make sure it's setting properly
+
+point()
+X java2d - if strokeWeight is 1, do screenX/Y and set()
+X if strokeWeight larger, should work ok with line()
+X no, use an ellipse if strokeWeight is larger
+X gl points not working again
+X need to implement point() as actual gl points
+X this means adding points to the pipeline
+X point() doesn't work with some graphics card setups
+X particularly with opengl and java2d
+X http://dev.processing.org/bugs/show_bug.cgi?id=121
+X point() issues
+o point() being funneled through beginShape is terribly slow
+X go the other way 'round
+X sometimes broken, could be a problem with java 1.5? (was using win2k)
+
+font
+X fix getFontMetrics() warning
+X need to have a getGraphics() to get the actual Graphics object
+X where drawing is happening. parent.getGraphics() works except for OpenGL
+X Java2D textLinePlacedImpl should check for ENABLE_NATIVE_FONTS hint
+X http://dev.processing.org/bugs/show_bug.cgi?id=633
+X also try to check native font on textFont() commands
+X in case the hint() has been enabled in the meantime
+X or rather, always load native font, even w/o the hint() being set
+
+PGraphics API changes
+X setMainDrawingSurface() -> setPrimarySurface()
+X mainDrawingSurface = primarySurface;
+X resize() -> setSize() (roughly)
+X endShape() with no params is no longer 'final'
+X X/Y/Z -> TX/TY/TZ
+X MX/MY/MZ -> X/Y/Z (for sake of PShape)
+X render_triangles -> renderTriangles()
+X depth_sort_triangles -> sortTriangles()
+X render_lines -> renderLines()
+X depth_sort_lines -> sortLines()
+X no longer any abstract methods in PGraphics itself
+X removed support for specular alpha (and its 'SPA' constant)
+X clear() -> backgroundImpl()
+X add DIAMETER as synonym for CENTER for ellipseMode and friends
+X textFontNative and textFontNativeMetrics have been removed
+X they've been re-implemented per-PGraphics in a less hacky way
+X hint(ENABLE_NATIVE_FONTS) goes away
+X need to mention in createFont() reference
+X also maybe cover in the loadFont() reference? (maybe problem...)
+X image.cache has been removed, replaced with get/set/removeCache()
+X this allows per-renderer image cache data to be stored
+X imageMode has been removed from PImage, too awkward
+X this also means that imageMode ignored for get(), set(), blend() and copy()
+X smooth is now part of PGraphics, moved out of PImage
+X raw must handle points, lines, triangles, and textures
+X light position and normal are now PVector object
+X changed NORMALIZED to NORMAL for textureMode()
+
+shapes
+X maybe finish off the svg crap for this release
+X working on pshape
+X add shape() methods to PGraphics/PApplet
+X test and fix svg examples
+X revisions.txt for x/y/z/ tx/ty/tz.. other changes in api.txt
+X bring svg into main lib
+X need to straighten out 'table' object for quick object lookup
+X maybe add to all parent tables? (no, this gets enormous quickly)
+X fix svg caps/joins for opengl with svg library
+X http://dev.processing.org/bugs/show_bug.cgi?id=628
+X save/restore more of the p5 graphics drawing state
+X not setting colorMode(), strokeCap, etc.
+X ignoreStyles is broken - how to handle
+X need a whole "styles" handler
+X handle cap/join stuff by
+X if it's setting the default, no error message
+X if it's not the default, then show an error msg once
+X have a list Strings for errors called, rather than constants for all
+X that way, no need to have an error message for every friggin function
+X PMatrix now PMatrix3D (maybe not yet?)
+X change svg library reference
+
+hint/unhint/enable/disable
+X option to have renderer errors show up
+X 1) as text warnings 2) as runtime exceptions 3) never
+X add warning system for pgraphics, rather than runtime exceptions
+X keep array of warning strings, and booleans for whether they've called
+X ENABLE_DEPTH_SORT not really working for GL
+X because the zbuffer is still there, it's still calculating
+X actually, this is probably because it happens after the frame
+X so really, flush is required whenever the depth sort is called
+X need to check this--isn't this referring to DISABLE_DEPTH_TEST?
+X ENABLE_DEPTH_SORT causing trouble with MovieMaker
+X need to make the flush() api accessible
+X http://dev.processing.org/bugs/show_bug.cgi?id=692
+X image smoothing
+X straighten out default vs. ACCURATE vs. whatever
+X Java2D and P3D and OpenGL are all inconsistent
+o need to be able to do hint() to do nearest neighbor filtering
+X http://dev.processing.org/bugs/show_bug.cgi?id=685
+o imageDetail(), textDetail(), etc?
+o decisions on image smoothing vs. text smoothing vs. all
+
+
+0148 core
+X tweaks to PGraphicsOpenGL to support GLGraphics
+
+
+0147 core
+X processing sketches not restarting after switching pages in safari
+X http://dev.processing.org/bugs/show_bug.cgi?id=581
+
+cleaning
+X misshapen fonts on osx (apple fixed their bug)
+X http://dev.processing.org/bugs/show_bug.cgi?id=404
+
+
+0146 core
+X fix the internal file chooser so that people don't need to make their own
+X threading is a problem with inputFile() and inputFolder()
+X dynamically load swingworker?
+o remove saveFile() methods?
+o write up examples for these instead?
+o start an integration section?
+X get() in java2d not honoring imageMode or rectMode
+X add imageMode(CENTER) implementation
+X add a bunch of changes to the reference to support this
+X Duplicate 3d faces in beginRaw() export
+X this was actually doubling geometry, potentially a bit of a disaster
+X http://dev.processing.org/bugs/show_bug.cgi?id=737
+o bezierVertex YZ Plane fill problem
+X http://dev.processing.org/bugs/show_bug.cgi?id=752
+X weird coplanar stuff, shouldn't be doing 3D anyway
+
+cleanup
+X switch to requestImage() (done in 0145)
+o can bug 77 be fixed with a finalizer? (no, it cannot)
+X make sure that images with alpha still have alpha in current code
+X text in rectangle is drawing outside the box
+X http://dev.processing.org/bugs/show_bug.cgi?id=844
+X points missing in part of screen
+X http://dev.processing.org/bugs/show_bug.cgi?id=269
+
+
+0145 core
+X separate x/y axis on sphereDetail() params
+X http://dev.processing.org/bugs/show_bug.cgi?id=856
+X make sure docs for PImage use createImage
+X add notes about JOGLAppletLauncher
+X http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/JOGLAppletLauncher.html
+X added to javadoc
+o need a halt() method which will kill but not quit app (sets finished?)
+o exit() will actually leave the application
+o this may in fact only be internal
+X this is just the stop() method, though maybe we need to document it
+X text(String, float, float, float, float) draws text outside box
+X http://dev.processing.org/bugs/show_bug.cgi?id=844
+X implement textAlign() for y coords in text rect
+X need to add reference for this
+X textAlign() bottom now takes textDescent() into account
+X remove gzip-related hint()
+
+threading
+X major threading overhaul before 1.0 (compendium)
+X http://dev.processing.org/bugs/show_bug.cgi?id=511
+X ewjordan has added a good trace of the badness
+X need to move off anim off the main event thread
+X move away from using method like display
+X look into opengl stuff for dealing with this
+X move addListeners() calls back out of PGraphics
+X resize window will nuke font setting
+X textFont() used in setup() is null once draw() arrives
+X http://dev.processing.org/bugs/show_bug.cgi?id=726
+X colorMode() set inside setup() sometimes not set once draw() arrives
+X http://dev.processing.org/bugs/show_bug.cgi?id=767
+X applet sizing issues with external vm
+X could this possibly be related to the linux bug?
+X http://dev.processing.org/bugs/show_bug.cgi?id=430
+X alloc() stuff not fixed because of thread halting
+X problem where alloc happens inside setup(), so, uh..
+X http://dev.processing.org/bugs/show_bug.cgi?id=369
+X should instead create new buffer, and swap it in next time through
+X sonia (and anything awt) is locking up on load in rev 91
+X prolly something w/ the threading issues
+X paint is synchronized in 0091
+X however this is a necessity, otherwise nasty flickering ensues
+X and using a "glock" object seems to completely deadlock
+X http://dev.processing.org/bugs/show_bug.cgi?id=46
+o claim that things are much slower in 107 vs 92
+o http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Suggestions;action=display;num=1141763531
+X hopefully this is cleaned up by removing some of the synchronization
+X sketches lock up when system time is changed
+X http://dev.processing.org/bugs/show_bug.cgi?id=639
+X can draw() not be run on awt event thread?
+X look into opengl stuff for dealing with this
+o "is there a better way to do this" thread in lists folder
+X framerate that's reported is out of joint with actual
+X http://dev.processing.org/bugs/show_bug.cgi?id=512
+X accuracy of frame timer is incorrect
+X seems to be aliasing effect of low resolution on millis()
+X so rates coming out double or half of their actual
+X probably need to integrate over a rolling array of 10 frames or so
+X frameRate() speeds up temporarily if CPU load drops dramatically
+X http://dev.processing.org/bugs/show_bug.cgi?id=297
+o perhaps add a hint(DISABLE_FRAMERATE_DAMPER)
+X fix the flicker in java2d mode
+X http://dev.processing.org/bugs/show_bug.cgi?id=122
+X framerate(30) is still flickery and jumpy..
+X not clear what's happening here
+X appears to be much worse (unfinished drawing) on macosx
+X try turning off hw accel on the mac to see if that's the problem
+
+
+0144 core
+X if loading an image in p5 and the image is bad, no error msg shown
+X that is, if a loadImage() turns up an access denied page
+X added an error message for this, and the image width and height will be -1
+X added loadImageAsync() for threaded image loading
+
+opengl fixes
+X incorporate changes from andres colubri into PGraphicsOpenGL
+X most of the changes incorporated, something weird with constructors
+X use gluErrorString() for glError() stuff
+X PGraphicsOpenGL.java:
+X directionalLight() and .pointLight() are both calling
+X glLightNoAmbient() which then creates a new FloatBuffer
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1199376364
+
+
+0143 core
+X some fonts broken in java 1.5 on osx have changed again
+X http://dev.processing.org/bugs/show_bug.cgi?id=407
+X filed as bug #4769141 with apple http://bugreport.apple.com/
+X appears that asking for the postscript name no longer works
+o fix "create font" and associated font stuff to straighten it out
+X was grabbing the wrong native font with ico sketch
+X seems that the psname is no longer a good way to grab the font? related?
+X available font issues
+X is getFontList returning a different set of fonts from device2d?
+X try it out on java 1.3 versus 1.4
+X getAllFonts() not quite working for many fonts
+X i.e. Orator Std on windows.. macosx seems to be ok
+X is getFamilyNames() any different/better?
+X when did this break? 1.4.1? 1.4.x vs 1.3?
+X may be that cff fonts won't work?
+X or is it only those with ps names?
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1117445969
+o leading looks too big, at least in PGraphics2 with news gothic
+X though prolly the converted version of the .ttf?
+X add a fix so that negative angle values won't hork up arc() command
+X add resize() method to PImage
+
+
+0142 core
+X update iText in PDF library to 2.1.2u
+X loadStrings(".") should not list directory contents
+X http://dev.processing.org/bugs/show_bug.cgi?id=716
+
+
+0141 core
+X no changes to core in 0141
+
+
+0140 core
+X add static version of loadBytes() that reads from a File object
+X slightly clearer error messages when OpenGL stuff is missing
+
+
+0139 core
+X no changes to core in 0139
+
+
+0138 core
+X improve tessellation accuracy by using doubles internally
+X http://dev.processing.org/bugs/show_bug.cgi?id=774
+
+
+0137 core
+X add gz handling for createOutput()
+X change openStream() to createInput() (done in 0136)
+X add createOutput()
+X deprecate openStream() naming
+
+
+0136 core
+X add static version of saveStream() (uses a File and InputStream object)
+X A "noLoop()" sketch may be unresponsive to exit request
+X http://dev.processing.org/bugs/show_bug.cgi?id=694
+X Fixed bug with subset() when no length parameter was specified
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1196366408
+X http://dev.processing.org/bugs/show_bug.cgi?id=707
+X figure out why tiff images won't open with after effects
+X http://dev.processing.org/bugs/show_bug.cgi?id=153
+X open with photoshop, resave, see which tags change
+X specifically, which tags that were in the original image file
+X perhaps something gets corrected?
+X had a fix, but decided not to re-implement the loadTIFF stuff too
+X fix for bezierTangent() problem from dave bollinger
+X http://dev.processing.org/bugs/show_bug.cgi?id=710
+X implement curveTangent (thanks to davbol)
+X http://dev.processing.org/bugs/show_bug.cgi?id=715
+X fix problem with get() when imageMode(CORNERS) was in use
+X fix bug with splice() and arrays
+X http://dev.processing.org/bugs/show_bug.cgi?id=734
+X 'screen' is now static
+X undo this--may need to be better about specifying screen and all
+X PImage mask doesn't work after first call
+X http://dev.processing.org/bugs/show_bug.cgi?id=744
+X load and save tga results in upside down tga
+X http://dev.processing.org/bugs/show_bug.cgi?id=742
+X fix problem with g.smooth always returning false in JAVA2D
+X http://dev.processing.org/bugs/show_bug.cgi?id=762
+X add XMLElement (not filename) constructor to SVG lib
+X http://dev.processing.org/bugs/show_bug.cgi?id=773
+
+
+0135 core
+X modelX/Y/Z still having trouble
+X http://dev.processing.org/bugs/show_bug.cgi?id=486
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Suggestions;action=display;num=1186614415
+X add docs for model/screen/Y/Z
+X added for model, along with example.
+X screen was already complete
+X bring back opengl mipmaps (create them myself? try w/ newer jogl?)
+X opengl mipmaps are leaking (regression in spite of #150 fix)
+X http://dev.processing.org/bugs/show_bug.cgi?id=610
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=display;num=1193967684
+X seems to not actually be a problem on mbp, try desktop?
+X copy() was needing updatePixels() when used with OPENGL or JAVA2D
+X http://dev.processing.org/bugs/show_bug.cgi?id=681
+X check on the bug report for this one as well
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1173394373
+
+earlier
+o add notes about fixing serial on the mac to the faq (and link to bug)
+X not necessary, hopefuly things working better now
+X utf8 and encodings
+X createWriter() and createReader() that take encodings
+X xml files seem to be a lot of UTF-8
+X xml stuff
+X getItem("name");
+X getItems("name"); (same, but looks for multiple matches
+X getItem("path/to/item");
+o or could use getItem and getItemList? getItemArray()?
+o read more about xpath
+X parse xml from a string object
+X not have to just use Reader
+X add mention of this to the board
+o update to new version of jogl
+X fix mini p5 bugs for eugene
+
+
+0134 core
+X add noLights() method
+X http://dev.processing.org/bugs/show_bug.cgi?id=666
+X redraw the screen after resize events (even with noLoop)
+X http://dev.processing.org/bugs/show_bug.cgi?id=664
+o problem with transparency in mask()
+o http://dev.processing.org/bugs/show_bug.cgi?id=674
+X mark bug as invalid, using fill() instead of tint()
+X move to UTF-8 as native format for core file i/o operations
+X update reference to document the change
+o jogl glibc 2.4 problem on linux
+o move back to previous jogl until 1.1.1 is released
+X http://dev.processing.org/bugs/show_bug.cgi?id=675
+o deal with opengl applet export changes
+o what is deployment suggestion for all the different platforms?
+o can the jar files actually provide the DLLs properly?
+X revert back to jogl 1.0
+
+
+0133 core
+X fix problem with "export to application" and opengl
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=display;num=1193142573
+X add focus requests so that better chance of keys etc working
+X http://dev.processing.org/bugs/show_bug.cgi?id=645
+X argh, these make things worse (P3D run internal)
+X add stuff about classversionerrors to the reference
+X also update the libraries page
+X fix background() with P3D and beginRaw()
+X endRaw() has a problem with hint(ENABLE_DEPTH_SORT)
+X because the triangles won't be rendered by the time endRaw() is called
+X force depth sorted triangles to flush
+X is mousePressed broken with noLoop() or redraw()?
+X sort of but not really, add notes to reference about it
+
+cleaning
+o calling graphics.smooth(), graphics.colorMode() outside begin/endDraw
+o this causes everything to be reset once the draw occurs
+o kinda seems problematic and prone to errors?
+X nope, just need to say to do all commands inside begin/endDraw
+o finish implementation so 1.1 support can return
+X http://dev.processing.org/bugs/show_bug.cgi?id=125
+o check into ricard's problems with beginRecord()
+X i believe these were caused by linux java2d issues
+X beginFrame()/beginDraw() and defaults()
+X when should these be called, when not?
+X seems as though the begin/end should happen inside beginRaw/Record
+X defaults() gets called by the size() command in PApplet
+o would be cool if could sort w/o the sort class..
+o meaning use reflection to sort objects, just by implementing a few methods
+o would be much simpler and less confusing than new Sort() etc
+o or would it be ridiculously slow?
+X just using Comparator instead, since moving to Java 1.4
+X make a PException that extends RuntimeException but packages an ex?
+X http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
+X no, not necessary, and exceptions suck
+o need to write an error if people try to use opengl with 1.3 (i.e. on export)
+o don't let users with java < 1.4 load OPENGL
+o http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Contribution_3DOpenGL;action=display;num=1114368123;start=3
+o catch security exceptions around applet i/o calls
+o not just for saving files, but provide better error msgs when
+o attempting to download from another server
+X nope, just cover this in the reference
+o files not in the data folder (works in env, not in sketch)
+X mentioned repeatedly in the docs
+o fix link() to handle relative URLs
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1081710684
+X more trouble (and bug-worthy) than it's worth
+o put SecurityException things around file i/o for applets
+o rather than checking online(), since applets might be signed
+X no, better to let errors come through
+o slow on java2d, fast on p3d
+o http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115276250;start=3
+
+ancient
+o strokeWeight is still broken
+o setting stroke width on circle makes odd patterns
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1077013848
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1080347160
+o more weirdness with stroke on rect, prolly not alpha
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1085799526
+o rect is not getting it's stroke color set
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1073582391;start=0
+o weird problem with drawing/filling squares
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1077226984
+o alpha of zero still draws boogers on screen
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1073329613;start=0
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1080342288;start=0
+o break apart functions into local (placement) and override (blitting)
+o just have a "thin_flat_line" option in opengl code
+o is quad strip broken or not behaving as expected?
+X may be correct, it worked for nik
+X inside draw() mode, delay() does nothing
+X delay might be a good way to signal drawing to the screen/updating
+X set(x, y, image) x, y not setting with processing
+
+fixed earlier
+X is the texture[] array in PGraphics3D causing the problems with memory?
+X actually it's a PGraphicsGL problem..
+X maybe the image binding not getting unbound?
+o should image i/o be moved into PImage?
+o still needs applet object, so it's not like this is very useful
+o external PImage methods could take stream, i suppose..
+X relevant parts were moved in, others not
+o loadImage() using spaces in the name
+o if loadImage() with spaces when online(), throw an error
+o get tiff exporter for p5 to support argb and gray
+X would also need to modify the tiff loading code,
+X because the header would be different
+X http://dev.processing.org/bugs/show_bug.cgi?id=343
+X map() is not colored, neither is norm
+X image outofmemoryerror for casey's students
+X http://dev.processing.org/bugs/show_bug.cgi?id=355
+X this may be related to a ton of other memory bugs
+X 1.5.0_07 and 1.4.2_12 contain the -XX:+HeapDumpOnOutOfMemoryError switch
+X invaluable for tracking down memory leaks
+X can't replicate anymore
+X texture mapping
+X very odd, "doom era" stuff
+X would it be possible to have a 'slow but accurate' mode?
+X http://dev.processing.org/bugs/show_bug.cgi?id=103
+X fixed in release 0125
+X add hint() and unhint()
+X also add unhint() to the keywords file
+X and maybe remove hint() from keywords_base?
+o present mode is flakey.. applet doesn't always come up
+o seems like hitting stop helps shut it down?
+o is full screen window not being taken down properly?
+o has this fixed itself, or is it an issue with launching externally?
+X seems to be fixed in later java versions
+X rewrite getImpl/setImpl inside opengl
+X placement of 100x100 items is odd
+X happens with P3D and maybe also P2D?
+X http://dev.processing.org/bugs/show_bug.cgi?id=128
+
+
+0132 core
+X an image marked RGB but with 0s for the alpha won't draw in JAVA2D
+X images with 0x00 in their high bits being drawn transparent
+X also if transparency set but RGB is setting, still honors transparency
+X http://dev.processing.org/bugs/show_bug.cgi?id=351
+X improve memory requirements for drawing images with JAVA2D
+X now using significantly less memory
+
+tint/textures
+X tint() and noTint() switching problem in P2D
+X this should be a quick fix
+X http://dev.processing.org/bugs/show_bug.cgi?id=222
+X related to the fill bugs: when fill is identical, no fill applied
+X actually tint() should take over for fill as per-vertex color
+X when textured images are being used
+X http://dev.processing.org/bugs/show_bug.cgi?id=169
+X tint() should set texture color, fill() is ignored with textures
+X add to the reference
+X fix tint() for PGraphics3 (what could be wrong?)
+X tint() honoring alpha but not colored tint
+X maybe not setting fill color when drawing textures
+X guessing it's an implementation issue in sami's renderer
+X check with the a_Displaying example and tint(255, 0, 0, 100);
+X http://dev.processing.org/bugs/show_bug.cgi?id=90
+
+
+0131 core
+X hint(DISABLE_DEPTH_TEST) not behaving consistently
+X http://dev.processing.org/bugs/show_bug.cgi?id=483
+o make hints static - cannot do that
+X clean up hinting mechanism a bit
+X look into jogl anti-aliasing on osx
+o smoothMode(2) and smoothMode(4), right after size()?
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=display;num=1175552759
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=OpenGL;action=display;num=1164236069
+X look into capabilities stuff from mike creighton
+X also sets the aa mode on the pc so it no longer needs control panel bunk
+X update to JOGL 1.1.0
+X add gluegen-rt back to the applet export
+X http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/JOGLAppletLauncher.html
+X add print() and println() for long and double
+X http://dev.processing.org/bugs/show_bug.cgi?id=652
+X fix minor bug in saveStream() (undocumented)
+X "this file is named" errors don't like subdirectories
+X need to strip off past the file separator or something
+
+
+0130 core
+X fixed problem with size() and the default renderer
+X the renderer was being reset after setup(),
+X so anything that occurred inside setup() was completely ignored.
+X http://dev.processing.org/bugs/show_bug.cgi?id=646
+X http://dev.processing.org/bugs/show_bug.cgi?id=648
+X http://dev.processing.org/bugs/show_bug.cgi?id=649
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1192873557
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1192731014
+
+
+0129 core
+X width and height not always set properly
+X http://dev.processing.org/bugs/show_bug.cgi?id=642
+X bring back background() with alpha
+
+
+0128 core
+X remove PFont reflection stuff
+X remove cursor reflection stuff
+X fix up sorting functions
+X implement sortCompare() and sortSwap()
+X discuss this with casey
+X also could be using Arrays.sort(blah) with Comparable (1.2+)
+X make sorting functions static
+X use methods from Arrays class, cuts down on code significantly
+X implement sortCompare() and sortSwap()
+X discuss this with casey
+o also could be using Arrays.sort(blah) with Comparable (1.2+)
+X make sorting functions static?
+o should loadFont() work with ttf files (instead of createFont?)
+X otherwise loadFont() would work with font names as well, awkward
+X better to use createFont() for both
+o jogl issues with some cards on linux, might be fixed with newer jogl
+X http://dev.processing.org/bugs/show_bug.cgi?id=367
+X remove methods for background() to include an alpha value
+X this is undefined territory because of zbuffer and all
+X if you want that effect, use a rect()
+X saveFrame() produces a black background because bg not set correctly:
+X http://dev.processing.org/bugs/show_bug.cgi?id=421
+X background not being set properly
+X http://dev.processing.org/bugs/show_bug.cgi?id=454
+X having shut off the defaults reset, background not getting called for java2d
+X so this will make that other stuff regress again
+X in particular, when the applet is resized, but renderer not changed
+X why aren't background() / defaults() being called for opengl?
+o http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Contribution_3DOpenGL;action=display;num=1118784331
+o simon reports borders on P3D and OPENGL if background() not called
+X window fixed at 100x100 pixels
+X http://dev.processing.org/bugs/show_bug.cgi?id=197
+X width/height on problem machine prints out as:
+X 100x100 issues are exhibited on bh140c PCs, test and fix!
+X 100,200 and 128,200
+o AIOOBE on PLine 757.. halts renderer
+o fix erik's problems with export (also in bugs db)
+X draw() called twice in vista with java 1.6
+X http://dev.processing.org/bugs/show_bug.cgi?id=587
+
+cleanup from previous releases
+X P3D not doing bilinear interpolation in text and images
+X because smooth() has to be set (and smooth throws an error in P3D)
+X how should this be handled? a hint? allowing smooth()?
+X probably just allow smooth() but don't smooth anything
+o pdf export ignoring transparency on linux
+o check to see if this is the case on other linux machines
+o seems to be working fine on windows
+o http://dev.processing.org/bugs/show_bug.cgi?id=345
+X change how java version is determined on mac
+X http://developer.apple.com/technotes/tn2002/tn2110.html
+X (this tn provides no guidance for macos8/9.. gah)
+o little window showing up on macosx when running
+X never able to confirm, probably just old java bug
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1081284410
+o flicker happening on osx java 1.4, but not 1.3:
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1083184297
+o don't let users on < 1.3 load JAVA2D
+X set upper bound on framerate so as not to completely hose things?
+
+fixed in 0127
+X ARGB problems with createGraphics
+o P3D from createGraphics needs to be marked RGB not ARGB
+X http://dev.processing.org/bugs/show_bug.cgi?id=160
+X http://dev.processing.org/bugs/show_bug.cgi?id=428
+X http://dev.processing.org/bugs/show_bug.cgi?id=482
+X http://dev.processing.org/bugs/show_bug.cgi?id=530
+X http://dev.processing.org/bugs/show_bug.cgi?id=527
+
+reasons to drop 1.1 support (and support 1.3+)
+X remove reflection from createFont() constructor/methods in PFont
+X this would make PFont much smaller
+X array functions could be done through Arrays.xxx class
+X although some of these may be built in
+X sorting could be done through built-in sort() class
+X split() function could echo the built in split/regexp setup
+X and add features for regexp
+X could introduce use of Timer class in examples
+X also use SwingWorker to launch things on other threads
+X weirdness of two modes of handling font metrics
+X textFontNativeMetrics gives deprecation error
+X getFontList stuff in PFont causes problems
+
+
+0127 core
+X pixel operations are broken in opengl
+X get(), set(), copy(), blend(), loadPixels, updatePixels()
+X set(x, y, image) y reversed in openGL
+X background(image) also broken
+X also textMode(SCREEN)
+X http://dev.processing.org/bugs/show_bug.cgi?id=91
+o replaceAll() not supported by 1.1
+o http://dev.processing.org/bugs/show_bug.cgi?id=561
+o make version of loadBytes that checks length of the stream first
+o this might not be worth it
+o the number of cases where this works is small (half of url streams)
+o and who knows if the value returned will be correct
+o (i.e. will it be the uncompressed or compressed size of the data?)
+
+createGraphics() issues
+X offscreen buffers fail with texture mapping
+X pixels not being set opaque (only with textures?)
+X http://dev.processing.org/bugs/show_bug.cgi?id=594
+X add note to createGraphics() docs that opacity at edges is binary
+X PGraphics problem with fillColor
+X http://dev.processing.org/bugs/show_bug.cgi?id=468
+
+fixed earlier
+X add to open() reference problems with mac
+X need to use the 'open' command on osx
+X or need to do this by hand
+X prolly better to do it by default, since on windows we use cmd?
+X check to see if the user has 'open' in there already
+X they can call Runtime.getRuntime().exec() if they want more control
+
+fixed earlier (in 0125) by ewjordan
+X accuracy in P3D is very low
+X http://dev.processing.org/bugs/show_bug.cgi?id=95
+X textured polys throwing a lot of exceptions (ouch)
+X http://dev.processing.org/bugs/show_bug.cgi?id=546
+X polygons in z axis with nonzero x or y not filling properly
+X http://dev.processing.org/bugs/show_bug.cgi?id=547
+
+
+0126 core
+o rect() after strokeWeight(1) gives wrong coords
+X http://dev.processing.org/bugs/show_bug.cgi?id=535
+X bug in osx java 1.4 vs 1.5
+X fix bug in str() methods that take arrays
+X method was not working properly, was using the object reference
+X new version of saveStream()
+X implement auto-gzip and gunzip
+X fix bug where sort() on 0 length array would return null
+X instead, returns an array
+X unregisterXxxx() calls to remove methods from libs
+X http://dev.processing.org/bugs/show_bug.cgi?id=312
+X implemented by ewjordan
+X sort() on strings ignores case
+X mention the change in the reference
+X added MIN_FLOAT, MAX_FLOAT, MIN_INT, MAX_INT to PConstants
+X throw AIOOBE when min() or max() called on zero length array
+o fix lerpColor() to take the shortest route around the HSB scale
+o loadBytes() doesn't do auto gunzip? but loadStrings and createReader do?
+X this might be a good solution for dealing with the differences
+o with loadBytes(), they can use gzipInput (or loadBytesGZ?)
+o although what does openStream do? (doesn't do auto?)
+X auto-gunzip on createReader()
+o add auto-gunzip to loadStrings()
+X others for auto-gunzip?
+X do the same for createWriter() et al
+X disable mipmaps in 0126
+X http://dev.processing.org/bugs/show_bug.cgi?id=610
+X add match() method that returns an array of matched items
+
+
+0125 core
+X more blend() modes (the five listed on the thread below?)
+X http://dev.processing.org/bugs/show_bug.cgi?id=132
+X figure out what the modes should actually be:
+X photoshop: normal, dissolve; darken, multiply, color burn,
+X linear burn; lighten, screen, color dodge, linear
+X dodge; overlay, soft light, hard light, vivid light,
+X linear light, pin light, hard mix; difference,
+X exclusion; hue, saturation, color, luminosity
+X illustrator: normal; darken, multiply, color burn; lighten,
+X screen, color dodge; overlay, soft light, hard light;
+X difference, exclusion; hue, sat, color, luminosity
+X director: Copy, Transparent, Reverse, Ghost, Not copy,
+X Not transparent, Not reverse, Not ghost, Matte, Mask;
+X (below seems more useful:
+X Blend, Add pin, Add, Subtract pin, Background transparent,
+X Lightest, Subtract, Darkest, Lighten, Darken
+X flash:
+X DIFFERENCE: C = abs(A-B);
+X MULTIPLY: C = (A * B ) / 255
+X SCREEN: C= 255 - ( (255-A) * (255-B) / 255 )
+X OVERLAY: C = B < 128 ? (2*A*B/255) : 255-2*(255-A)*(255-B)/255
+X HARD_LIGHT: C = A < 128 ? (2*A*B/255) : 255-2*(255-A)*(255-B)/255
+X SOFT_LIGHT: C = B < 128 ? 2*((A>>1)+64)*B/255 : 255-(2*(255-((A>>1)+64))*(255-B)/255)
+X jre 1.5.0_10 is still default at java.com.. blech
+X http://dev.processing.org/bugs/show_bug.cgi?id=513
+X constant CENTER_RADIUS will be changed to just RADIUS
+X CENTER_RADIUS is being deprecated, not removed
+X remove CENTER_RADIUS from any p5 code (i.e. examples)
+X split() inconsistency (emailed casey, will discuss later)
+X make split(String, String) behave like String.split(String)
+X and make current split(String) into splitTokens(String)
+X that means split(String) no longer exists
+o add splitTokens() documentation
+o document new version of split() and regexp
+o should we mention String.split?
+X ironed out more of the preproc parseXxxx() functions
+X deal with targa upside-down and non-rle encoding for tga images
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1171576234
+X change println(array) to be useful
+o document using join() for old method
+X remove print(array) since it's silly?
+X make sure it's not in the reference
+X [0] "potato", [1] "tomato", [2] "apple"
+X fix filter(GRAY) on an ALPHA image to produce a good RGB image
+
+0125p2
+X updatePixels ref is wrong
+X has x/y/w/h version
+X the reference is also cut off
+X make ENTER, TAB, etc all into char values (instead of int)
+X some way to vertically center text
+X either by setting its middle vertical point
+X or by setting a top/bottom for the rectangle in which it should be placed
+o maybe textAlign(CENTER | VERTICAL_CENTER);
+X or TOP, MIDDLE, and BOTTOM
+o textAlign(CENTER | TOP);
+o could even have textAlign(CENTER) and textAlign(TOP) not replace each other
+X or textAlign(LEFT, MIDDLE); -> this one seems best
+X add reference for new param, and update keywords.txt
+X given to andy
+
+0125p3
+X PImage.save() method is not working with get()
+X http://dev.processing.org/bugs/show_bug.cgi?id=558
+X NullPointerException in Create Font with "All Characters" enabled
+X http://dev.processing.org/bugs/show_bug.cgi?id=564
+X added min() and max() for float and int arrays
+X need to update reference
+X moved around min/max functions
+X opengl image memory leaking
+X when creating a new PImage on every frame, slurps a ton of memory
+X workaround is to write the code properly, but suggests something bad
+X http://dev.processing.org/bugs/show_bug.cgi?id=150
+X opengl keeping memory around..
+X could this be in vertices that have an image associated
+X or the image buffer used for textures
+X that never gets cleared fully?
+X registerSize() was registering as pre() instead
+X http://dev.processing.org/bugs/show_bug.cgi?id=582
+X set() doesn't bounds check
+X this shouldn't actually be the case
+X http://dev.processing.org/bugs/show_bug.cgi?id=522
+X get()/set() in PGraphicsJava2D don't bounds check
+X was actually a dumb error in setDataElements()
+X set modified to true on endDraw() so that image updates properly
+X http://dev.processing.org/bugs/show_bug.cgi?id=526
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1171574044
+
+0125p4 (in progress)
+X significant improvement to text and images in opengl
+X now using mipmaps to interpolate large and small images
+X fix bug with mipmapping on radeon 9700
+X things not showing up in linux
+X this may be fixed along with bug #341
+X probably threading issue, 98 doesn't have any trouble
+X signs point to Runner or PApplet changes between 98 and 99
+X commenting out applet.setupFrameResizeListener()
+X in line 307 from Runner.java solved the problem
+X http://dev.processing.org/bugs/show_bug.cgi?id=282
+X size of sketch different in setup() and draw() on linux
+X make sure that the sketch isn't being sized based on bad insets
+X problem with resizing the component when the frame wasn't resizable
+X http://dev.processing.org/bugs/show_bug.cgi?id=341
+X major rework of the open() command
+X add gnome-open/kde-open for with PApplet.open()
+X add open (-a?) on osx to the open() command
+X make changes in the javadoc and reference
+X opengl crashes when depth sorting more than two textured shapes
+X http://dev.processing.org/bugs/show_bug.cgi?id=560
+
+ewjordan stuff (changes checked in)
+X rect() changes size as it changes position
+X http://dev.processing.org/bugs/show_bug.cgi?id=95
+X strange texture warping in P3D
+X hint(ENABLE_ACCURATE_TEXTURES)
+X http://dev.processing.org/bugs/show_bug.cgi?id=103
+X lines skip on 200x200 surface because of fixed point rounding error
+X http://dev.processing.org/bugs/show_bug.cgi?id=267
+X this may be same as 95
+X Polygons parallel to z-axis not always filling with nonzero x or y
+X http://dev.processing.org/bugs/show_bug.cgi?id=547
+
+
+0124 core
+X with smooth() turned off, shouldn't be smoothing image on resize
+X but on osx, apple defaults the image smoothing to true
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Programs;action=display;num=1164753510
+X http://developer.apple.com/documentation/Java/Conceptual/JavaPropVMInfoRef/Articles/JavaSystemProperties.html#//apple_ref/doc/uid/TP40001975-DontLinkElementID_6
+X background(0, 0, 0, 0) was resetting stroke, smooth, etc.
+X make imageImpl() use WritableRaster in an attempt to speed things up
+X fix weird situation where fonts used in more than one renderer wouldn't show
+X opengl doesn't draw a background for the raw recorder
+X change P3D to smooth images nicely (bilinear was disabled)
+X ambientLight(r,g,b) was still ambientLight(r,g,r)
+X http://dev.processing.org/bugs/show_bug.cgi?id=465
+X fix from dave bollinger for the POSTERIZE filter
+X http://dev.processing.org/bugs/show_bug.cgi?id=399
+X fix PImage regression in 0124 and the cache crap
+X added a version of trim() that handles an entire array
+X removed contract(), one can use expand() and subset() instead
+X backgroundColor to cccccc instead of c0c0c0
+X loadImage() requires an extension, maybe add a second version?
+X loadImage("blah", "jpg");
+X otherwise people have to use strange hacks to get around it
+X also chop off ? from url detritus
+X also just pass off to default createImage() if no extension available
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1165174666
+X http://dev.processing.org/bugs/show_bug.cgi?id=500
+X java 1.5.0_10 breaks jogl
+X add error message to p5 about it
+X http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6504460
+X http://www.javagaming.org/forums/index.php?topic=15439.0
+X upgrade to 1.5.0_11 or later:
+X http://java.sun.com/javase/downloads/index_jdk5.jsp
+X or downgrade to 1.5.0_09
+X http://java.sun.com/products/archive/j2se/5.0_09/index.html
+X no disk in drive error
+X was this something that changed with the java updates? (1.5_10)
+X doesn't seem to be, still not sure
+X problem was the floppy drive.. gak
+X http://dev.processing.org/bugs/show_bug.cgi?id=478
+X copy() sort of broken in JAVA2D
+X example sketch posted with bug report
+X http://dev.processing.org/bugs/show_bug.cgi?id=372
+o saveStrings(filename, strings, count)
+o otherwise the save is kinda wonky
+o or maybe that should just be done with the array fxns
+
+fixed earlier
+o sketches often freeze when stop is hit on an HT machine
+o need to test the examples cited on pardis' machine
+o http://dev.processing.org/bugs/show_bug.cgi?id=232
+X debug NumberFormat InterruptedException on dual proc machine
+X use notify() instead of interrupt()?
+X or Thread.currentThread() should be checked first?
+o svg loader is on the list for 1.0
+o maybe include as part of PApplet (casey thinks so)
+X using gl, lines don't show up in pdf with record (they're ok with p3d)
+X http://dev.processing.org/bugs/show_bug.cgi?id=325
+o with network connection
+o download a copy of the source for 0069, get the renderer
+o svn mv PGraphics2 PGraphicsJava
+o version of BApplet that replaces g. with ai. or pdf.
+
+
+0123 core
+X setup() and basic mode apps not working
+X http://dev.processing.org/bugs/show_bug.cgi?id=463
+
+
+0122 core
+X noiseSeed() only works once, before the arrays are created
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1162856262
+X make lerpColor honor the current color mode
+X lerpColor(c1, c2, amt, RGB/HSB/???)
+o test this out for a bit
+o though that's awkward b/c colors always RGB
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Suggestions;action=display;num=1160096087
+X regression in P3D that prevents point() from drawing
+X problem is with setup_vertex() not adding similar points
+X http://dev.processing.org/bugs/show_bug.cgi?id=444
+X if doing openstream on url, says that "the file" is missing or invalid
+X add notes about it being a url
+
+fixed earlier, bug cleaning
+X gray background in pdf (using both gl and p3d)
+X http://dev.processing.org/bugs/show_bug.cgi?id=324
+X verified as fixed in 0122
+
+
+0121 core
+X need to document changes to int() (no longer accepts boolean)
+X background(0, 0, 0, 0) is the way to really clear everything with zeroes
+X or background(0, 0), but the former is prolly better conceptually
+X how to clear the screen with alpha? background(0, 0, 0, 0)?
+o background(EMPTY) -> background(0x01000000) or something?
+X size(), beginRecords(), beginRaw(), createGraphics()
+X broken for file-based renderers in 0120
+X http://dev.processing.org/bugs/show_bug.cgi?id=434
+
+
+0120 core
+X fixed error when using hint(ENABLE_NATIVE_FONTS) with JAVA2D
+X java.lang.IllegalArgumentException:
+X null incompatible with Global antialiasing enable key
+X fix issue where ambientLight(r, g, b) was instead ambientLight(r, g, r)
+X http://dev.processing.org/bugs/show_bug.cgi?id=412
+X createFont() should always use native fonts
+X need to warn that fonts may not be installed
+X recommend that people include the ttf if that's the thing
+X or rather, that this is only recommended for offline use
+X fix 3D tessellation problems with curveVertex and bezierVertex
+X actually was z = Float.MAX_VALUE regression
+X http://dev.processing.org/bugs/show_bug.cgi?id=390
+X two examples in sketchbook
+X this has been reported several times
+X concave polygons having trouble if points come back to meet
+X tesselator/triangulator gets confused when points doubled up
+X might need to avoid previous vertex hitting itself
+X http://dev.processing.org/bugs/show_bug.cgi?id=97
+X graphics gems 5 has more about tessellation
+X polygons perpendicular to axis not drawing
+X is this a clipping error?
+X probably a triangulation error, because triangles work ok
+X http://dev.processing.org/bugs/show_bug.cgi?id=111
+X problem is that the area of the polygon isn't taking into account z
+X lookat is now camera(), but not fixed in the docs
+X add notes to the faq about the camera changes on the changes page
+o update run.bat for new quicktime
+o unfortunately this is messy because qtjava sometimes has quotes
+o and qtsystem might be somewhere besides c:\progra~1
+X run.bat has been removed from current releases
+X registering font directories in pdf.. is it necessary?
+X (commented out for 0100)
+X re-added for 0120
+o when re-calling size() with opengl, need to remove the old canvas
+o need to check to see if this is working properly now
+X passing applet into createGraphics.. problems with re-adding listeners
+X since the listeners are added to the PApplet
+X i think the listeners aren't re-added, but need to double check
+X createGraphics() having problems with JAVA2D, and sometimes with P3D
+X http://dev.processing.org/bugs/show_bug.cgi?id=419
+X with default renderer, no default background color?
+X only sometimes.. why is this?
+X only call defaults() when it's part of a PApplet canvas
+X make sure that defaults() is no longer necessary
+X don't want to hose PGraphics for others
+X both for pdf, and making background transparent images
+X PGraphics3D should alloc to all transparent
+X unless it's the main drawing surface (does it know on alloc?)
+X in which case it should be set to opaque
+X have createGraphics() create a completely transparent image
+X and also not require defaults() to be called
+X make a note in the createFont() reference that 1.5 on OS X has problems
+o if calling beginPixels inside another, need to increment a counter
+o otherwise the end will look like it's time to update
+o which may not actually be the case
+o i.e. calling filter() inside begin/end block
+X get creating new PGraphics/2/3 working again
+X http://dev.processing.org/bugs/show_bug.cgi?id=92
+X maybe createGraphics(200, 200) to create same as source
+X createGraphics(200, 200, P2D) to create 2D from 3D
+X also, drawing a PGraphics2 doesn't seem to work
+X new PGraphics2 objects are set as RGB, but on loadPixels/updatePixels
+X they're drawn as transparent and don't have their high bits set
+X problems between modelX between alpha and beta
+X http://dev.processing.org/bugs/show_bug.cgi?id=386
+X y may be flipped in modelX/Y/Z stuff on opengl
+X is this the same bug? assuming that it is
+
+in previous releases
+X when using PGraphics, must call beginFrame() and endFrame()
+X also need to be able to turn off MemoryImageSource on endFrame
+X call defaults() in beginFrame()
+X should PGraphics be a base class with implementations and variables?
+X then PGraphics2D and PGraphics3D that subclass it?
+X (or even just PGraphics2 and PGraphics3)
+X also rename PGraphics2 to PGraphicsJava
+X it's goofy to have the naming so different
+X tweak to only exit from ESC on keyPressed
+o probably should just make this a hint() instead
+X just documented in reference instead
+o metaballs example dies when using box()
+o long string of exceptions, which are also missing their newlines
+X grabbing sun.cpu.endian throws a security exception with gl applets
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Contribution_3DOpenGL;action=display;num=1114368123
+
+
+0119 core
+X add saveStream() method
+X change to handle Java 1.5 f-up where URLs now give FileNotFoundException
+X http://dev.processing.org/bugs/show_bug.cgi?id=403
+X add unlerp() method
+
+
+0118 core
+X replace jogl.jar with a signed version
+X fix the export.txt file for the linux release
+X fix problem with setting the parent and the PDF renderer
+
+
+0117 core
+X no changes, only to the build scripts
+
+
+0116 core
+X make background() ignore transformations in JAVA2D
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1147010374
+o createGraphics to not require defaults()
+X can't do, because an end() function must be called to clear the renderer
+X add "hide stop button" arg for PApplet
+X beginFrame/endFrame -> beginDraw/endDraw
+X add new constant for the DXF renderer
+X array utilities on Object[] are worthless.. fix it with reflection?
+X see if reflection will allow expand for all class types
+X expand, append, contract, subset, splice, concat, reverse
+X typed version of array functions:
+X append(), shorten(), splice, slice, subset, concat, reverse
+X http://dev.processing.org/bugs/show_bug.cgi?id=115
+X fix issue where processing applets would run extremely fast
+X after having been starved of resources where there framerate dropped
+X http://dev.processing.org/bugs/show_bug.cgi?id=336
+X added color/stroke/tint/fill(#FF8800, 30);
+X test imageio with images that have alpha (does it work?)
+X nope, doesn't, didn't finish support
+X http://dev.processing.org/bugs/show_bug.cgi?id=350
+X openStream() fails with java plug-in because non-null stream returned
+X http://dev.processing.org/bugs/show_bug.cgi?id=359
+X update jogl to latest beta 5
+X make framerate into frameRate (to match frameCount)
+X AIOOBE in P3D during defaults/background/clear
+X PGraphics.clear() problem from workbench and malware stuff
+X had to put synchronized onto draw and size()
+X actually it'll work if it's only on size()
+X the sync on the mac hangs an applet running by itself
+X even though it seems to be ok for a component
+X thread sync problem with allocation
+X http://dev.processing.org/bugs/show_bug.cgi?id=369
+X major threading change to use wait()/notifyAll() instead of interrupt/sleep
+X noLoop() at end of setup is prolly b/c of interruptedex
+X need to not call Thread.interrupt()
+X opengl + noLoop() causes InterruptedException
+X check to see noLoop() breakage is fixed in 92 vs 91
+X checked, not fixed
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115330568
+X http://dev.processing.org/bugs/show_bug.cgi?id=164
+X remove image(filename) and textFont(filename) et al.
+X revision 115 may be saving raw files as TIFF format
+X may be a bug specific to java 1.5 (nope)
+X http://dev.processing.org/bugs/show_bug.cgi?id=378
+X saveFrame() not working for casey
+X problem with tiff loading in photoshop etc
+X check http:// stuff to see if it's a url first on openStream()
+X it's the most harmless, since prolly just a MFUEx
+X fix problem where root of exported sketch won't be checked
+X http://dev.processing.org/bugs/show_bug.cgi?id=389
+X createFont not working from applets (only with .ttf?)
+X throws a security exception because of the reflection stuff
+X http://dev.processing.org/bugs/show_bug.cgi?id=101
+X urls with ampersands don't work with link()
+X Runtime.getRuntime().exec("cmd /c start " + url.replaceAll("&","^&"));
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1149974261
+X fix bug where smooth() was shut off after using text
+X (that had the smoothing turned off when used in "Create Font")
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1148362664
+X fix dxf to use begin/endDraw instead of begin/endFrame
+X fixes axel's bug with dxf export
+X set default frameRate cap at 60
+X otherwise really thrashing the cpu when not necessary
+X jpeg loading may be extremely slow (loadBytes?)
+X seems specific to 0115 versus the others
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1158111639
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1154714548
+X http://dev.processing.org/bugs/show_bug.cgi?id=392
+X loadImage() problems with png and jpg
+X actually it's an issue with some types of jpeg files
+X http://dev.processing.org/bugs/show_bug.cgi?id=279
+X java.lang.IllegalArgumentException:
+X Width (-1) and height (-1) cannot be <= 0
+X identical to what happens when the image data is bad
+X for instance, trying to load a tiff image with the jpg loader
+X http://dev.processing.org/bugs/show_bug.cgi?id=305
+o blend() mode param should be moved to the front
+X nah, works better with the other format
+X make sure there's parity with the copy() functions
+X remove single pixel blend functions
+o blend() should prolly have its mode be the first param
+X move blend() to blendColor() when applying it to a color
+X added lerpColor(), though it needs a new name
+X went back to old image i/o (sometimes caused trouble when exported)
+X http://dev.processing.org/bugs/show_bug.cgi?id=376
+X change reader() to createReader() for consistency?
+X though printwriter is odd for output..
+X also createWriter() and the rest
+o add to docs: save() on a PImage needs savePath() added
+X hint(DISABLE_NATIVE_FONTS) to disable the built-in stuff?
+X or maybe this should be hint(ENABLE_NATIVE_FONTS) instead?
+X figure out default behavior for native text fonts
+X make sure insideDrawWait() is in other resize() methods
+X begin/end/alloc waits to PGraphicsJava2D, PGraphicsOpenGL, PGraphics3D
+X fix bug with fill(#ffcc00, 50);
+X toInt() on a float string needs to work
+X need to check for periods to see if float -> int first
+X shape changes
+X remove LINE_STRIP - tell people to use beginShape() with no params
+X remove LINE_LOOP - tell people to use endShape(CLOSE)
+o also remove POLYGON?
+X may as well remove it
+X though something still needed as an internal constant
+X add endShape(CLOSE) or CLOSED
+X when running as an applet, sketchPath won't be set
+X change the error message slightly
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1153150923
+X use parseFloat instead of toFloat()? to be consistent with javascript
+X also clean up some of the casting silliness
+
+more recent
+X only update mouse pos on moved and dragged
+X http://dev.processing.org/bugs/show_bug.cgi?id=170
+X also updates a bug that caused sketches to jump in funny ways
+
+fixed in 0115 / quicktime 7.1
+X color values on camera input flipped on intel macs
+X checked in a change for this recommended on qtjava list
+X http://dev.processing.org/bugs/show_bug.cgi?id=313
+
+really old stuff
+o get loop, noLoop, redraw, and framerate all working in opengl
+o needs custom animator thread..
+o depth() shouldn't be needed for opengl unless actually 3D
+o right now the camera doesn't get set up unless you call depth()
+o box and sphere are broken in gl
+o what should the update image function be called?
+
+
+0115 core
+X remove debug message from loadPixels()
+X remove debug message from PGraphics2.save()
+X fix error message with dxf when used with opengl
+X if file is missing for reader()
+X return null and println an error rather than failing
+X add arraycopy(from, to, count);
+X fix fill/stroke issues in bugs db (bug 339)
+X saveTIFF, saveHeaderTIFF, saveTGA no longer public/static in PImage
+X this was a mistake to expose the api this way
+X more image file i/o in java 1.4
+X add dynamic loading of the jpeg, png, and gif(?) encoder classes
+X http://dev.processing.org/bugs/show_bug.cgi?id=165
+X http://java.sun.com/products/java-media/jai/index.jsp
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Programs;action=display;num=1120174647
+X P5 cannot read files generated by saveFrame()
+X need to update docs re: tga
+X and add support for reading its own uncompressed TIFs
+X http://dev.processing.org/bugs/show_bug.cgi?id=260
+
+
+0114 core
+X added createGraphics(width, height, renderer)
+X no need to use (..., null) anymore
+X fix set() for JAVA2D, also fixes background(PImage) for JAVA2D
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1145108567
+X remove "max texture size" debug message
+X flicker with depth sort enabled
+X implement basic depth sorting for triangles in P3D and OPENGL
+X add option to sort triangles back to front so alpha works
+X http://dev.processing.org/bugs/show_bug.cgi?id=176
+o at least add it to the faq, or this would be a test case w/ the sorting
+
+
+0113 core
+X fix for open() on macosx submitted by chandler
+
+
+0112 core
+X saveFrame() issues with JAVA2D on osx
+X http://dev.processing.org/bugs/show_bug.cgi?id=189
+o implement hint(NO_DEPTH_TEST) for opengl
+X already done hint(DISABLE_DEPTH_TEXT);
+X check min/max texture sizes when binding to avoid problems
+X minimum texture size may be 64x64
+X maximum appears to be 2048, on macs maybe 512
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Contribution_3DOpenGL;action=display;num=1137130317
+X fix non-bound textures from mangling everything else
+X http://dev.processing.org/bugs/show_bug.cgi?id=322
+X fix enable/disable textures for some objects
+X also a big problem for fonts
+X calling updatePixels() on each frame fixes the issue (sorta)
+X images are memory leaking pretty badly
+X texture re-allocated on each frame
+X lighting bug introduced in rev 109
+X spotLight has troubles with an invalid value
+X probably somethign weird about the params (3 vs 4) being sent
+X the first spotLight works fine, it's something with the second
+X (the one that follows the mouse)
+X just something to debug in the example
+X regression from contributed code..
+X was using apply() instead of set() in PMatrix inverse copy
+X filter() is also broken (not rewinding the intbuffer)
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Contribution_3DOpenGL;action=display;num=1144561113
+
+sound has been removed
+o duration as an internal param, not a function
+o When a sound is finished playing,
+o it should return to 0 so it can play again
+o Putting sound.loop() in draw() seemed to spawn multiple sounds threads?
+o After a sound is paused, it will only play from where it was paused
+o to its end and will not loop again
+o The ref in PSound2 says volume accepts vals from 0...1
+o but values larger than one increase the volume.
+o SoundEvent // is sound finished?? Can't access now.
+o make java 1.1 version of PSound work properly
+o merge PSound and PSound2 via reflection?
+o once debugged, merge these back together and use reflection
+o (unless it's a messy disaster)
+o Unsupported control type: Master Gain
+o what's actually causing this error?
+o http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115467831
+o PSound.play() won't play the sound a 2nd time (reopened)
+o http://dev.processing.org/bugs/show_bug.cgi?id=208
+o loadSound apparently broken in java 1.5?
+o http://dev.processing.org/bugs/show_bug.cgi?id=285
+X need to just remove PSound altogether
+
+
+0111 core
+X need to have a better way of getting/figuring out the endian
+X use ByteOrder class in jdk 1.4, since issue is local to JOGL
+X security ex when run as an applet
+X also can no longer assume that macosx is big endian
+X http://dev.processing.org/bugs/show_bug.cgi?id=309
+o making 'run' synchronized caused a freeze on start w/ opengl
+X display() as a function name is problematic
+X causes nothing to show up.. either rename or mark it final
+X http://dev.processing.org/bugs/show_bug.cgi?id=213
+X fix for lights throwing a BufferOverflowException
+
+
+0110 core
+X finish updates for osx and opengl
+X http://developer.apple.com/qa/qa2005/qa1295.html
+X find/build universal version of jogl
+
+
+0109 core
+X loadImage("") produces weird error message
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Programs;action=display;num=1136487954
+X still having strokeCap() problems
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1134011764
+X fixes contributed by willis morse to deal with memory wastefulness
+X should help speed up some types of OPENGL and P3D mode sketches
+
+
+0108 core
+X image(String filename, ...) and textFont(String filename, ...) implemented
+X add notes to faq about video fix
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=VideoCamera;action=display;num=1134871549
+X look into code that fixes crash on camera.settings()
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=VideoCamera;action=display;num=1139376484
+X finish dxf writer that'll work with recordRaw()
+
+
+0107 core
+X no changes, only fixes for "save" bugs
+
+
+0106 core
+X fix bug where more than 512 vertices would cause trouble in P3D and OPENGL
+
+
+0105 core
+X fix some issues with beginRaw and opengl
+
+
+0104 core
+X don't open a window the size of the pdf if in pdf mode
+X need to have some sort of flag in the gfx context that it's visible or not
+o handled inside updateSize()?
+X if it doesn't display to the screen, needs to never show a window
+X basically if the main gfx context isn't viewable, close the window
+X since it may have already been opened at 100x100
+X avoid opening it in the first place?
+X added toolkit getFontMetrics() for shape mode fonts to be able to change size
+X recordRaw() to a PGraphics3 should send 3D data.
+X but recordRaw() to a PGraphics(2) should send only 2D data.
+
+
+0103 core
+X fix stack overflow problem
+X bug in itext implementation on osx (10.4 only?)
+X http://www.mail-archive.com/itext-questions@lists.sourceforge.net/msg20234.html
+
+in previous releases
+X recordFrame() and beginFile()/endFile()
+X how to deal with triangles/lines and triangleCount and lineCount
+X maybe just need a triangleImpl and lineImpl
+X because it's too messy to retain the triangle objects and info
+X calling recordFrame() from mousePressed is important
+X dangerous tho because mouse fxn called just before endFrame
+
+
+0102 core
+X no changes, windows-only release to deal with processing.exe
+
+
+0101 core
+X add dispose() call to the shutdown part of PApplet
+
+
+0100 core
+X user.dir wasn't getting set properly
+X when graphics can be resized, resize rather than creating new context
+X change savePath() et al a great deal, include better docs
+X http://dev.processing.org/bugs/show_bug.cgi?id=199
+X straighten out save() and saveFrame()
+o use File object for when people know what they're doing?
+X same issue occurs with pdf and creating graphics obj
+
+get initial version of pdf working
+X get rid of beginFrame/endFrame echo to recorders?
+X that way begin/end can just be where the recorder starts/stops?
+X recordRaw is really confusing..
+X when to use beginFrame/endFrame
+X is beginRaw/endRaw really needed?
+X seems to be a problem that it's an applet method
+X but then it's called on the g of the applet
+X but then it's the recorderRaw of that g that gets it called..
+X how to flush when the sketch is done
+X inside dispose method? explicit close?
+X call exit() at end of pdf apps? exit calls dispose on gfx?
+X beginRecord() and endRecord() so that record doesn't stop after frame?
+X enable PGraphicsPDF for inclusion
+X write documentation on images (they suck) and fonts (use ttf)
+
+
+0099 core
+X removed playing() method from PSound
+X integrate destroy() method from shiffman as dispose() in PSound2
+X ComponentListener is probably what's needed for resize()
+X make sure that components can be resized properly via size()
+X http://dev.processing.org/bugs/show_bug.cgi?id=209
+X or that it properly responds to a setBounds() call
+X calling size() elsewhere in the app doesn't quite work
+X A second call to size almost works.
+X The buffer apparently gets allocated and saveFrame saves the
+X new size but drawing appears to be disabled.
+X http://dev.processing.org/bugs/show_bug.cgi?id=243
+
+
+0098 core
+X change recordShapes() to just record() and recordRaw()
+X width, height set to zero in static mode
+X http://dev.processing.org/bugs/show_bug.cgi?id=198
+X probably only set when resize() is called, and it's not happening
+X be careful when fixing this, bugs 195/197 were a result:
+X http://dev.processing.org/bugs/show_bug.cgi?id=195
+X http://dev.processing.org/bugs/show_bug.cgi?id=197
+X PSound.play() won't play the sound a 2nd time
+X (have to call stop() first)
+X http://dev.processing.org/bugs/show_bug.cgi?id=208
+
+
+0097 core
+X no changes, only export to application stuff
+
+
+0096 core
+X set applet.path to user.dir if init() is reached and it's not set
+X add DISABLE_DEPTH_TEST to PGraphics3
+X need to document this somewhere
+X also need to add to PGraphicsGL
+X access logs are being spammed because openStream() gets a 404
+X the default should be to check the .jar file
+X openStream() doesn't work with subfolders
+X http://dev.processing.org/bugs/show_bug.cgi?id=218
+X screwed up movie loading paths (quick fix)
+X http://dev.processing.org/bugs/show_bug.cgi?id=216
+X additional cleanup in the Movie class
+X make path thing into getPath() or something?
+X sketchPath(), dataPath(), savePath(), createPath()
+X applet shouldn't be resizing itself
+X opens at correct size, then makes itself small, then large again
+X setup() mode apps often don't open at the correct placement
+X because of their resizing
+X check into bug where applet crashing if image not available
+X probably need to add a hint() to make things not halt
+X loadBytes() and openStream() et al need to return null
+X loadImage() can too, but print an error to the console
+X "not available in P3D" should read "OPENGL" in opengl lib
+X keypressed ref: repeating keys
+X also remove "no drawing inside keypressed"
+X text block wrap problem with manual break character (\n)
+X http://dev.processing.org/bugs/show_bug.cgi?id=188
+
+draw mode issues
+X when run externally without a draw, applets will exit immediately
+X when run internally (no code folder or .java files) will just wait
+X shouldn't quit draw mode apps immediately
+X otherwise something gets drawn then the applet exits
+X should instead use exit() when they need to exit
+X NullPointerException when no draw()
+X http://dev.processing.org/bugs/show_bug.cgi?id=210
+X window closing immediately with library imports
+X http://dev.processing.org/bugs/show_bug.cgi?id=204
+X check into loadImage() with jars bug, very frustrating
+o when using loadImage() on a jar, turn off "no cache" option?
+X image no load halts the program (rather than returning null)
+X note in the reference: png images work with java 1.3+
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=WebsiteBugs;action=display;num=1125968697
+X add bug re: gif image break missing to revisions.txt
+X http://dev.processing.org/bugs/show_bug.cgi?id=217
+
+image pile
+X get loadImage() to work properly with data folder
+X should probably use the code from loadStream
+X and the url stuff should be an alternate method altogether
+o loadImage() seems to be caching everything from the jar
+X http://java.sun.com/developer/technicalArticles/Media/imagestrategies/index.html
+o make a note of how to disable this
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Programs;action=display;num=1078795681
+o bizarre image loading error with c_Rollover.zip
+X couldn't find/replicate this
+o read uncompressed tiff
+X read uncompressed tga files.
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_Software;action=display;num=1081190619
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Tools;action=display;num=1066742994
+o updated png encoder
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1083792994
+
+older stuff, no longer an issue
+o don't cache stuff from loadStrings and others
+o mac java vm won't give up old version of file
+o or use setUseCaches(false)
+o too many push() will silently stop the applet inside a loop
+X allow save(), saveFrame() et al to properly pass in absolute paths
+X (so that it doesn't always save to the applet folder)
+X could require that save() takes an absolute path?
+X loadImage must be used inside or after setup
+X either document this and/or provide a better error message
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Programs;action=display;num=1060879468
+X expose function to write tiff header in PImage (advanced)
+X helps with writing enormous images
+X tag release 93 (francis thinks it's rev 1666)
+
+
+0095 core
+X undo the fix that causes the width/height to be properly set
+
+
+0094 core
+X fix bug that was causing font sizes not to be set on opengl
+X http://dev.processing.org/bugs/show_bug.cgi?id=174
+X apply fix from toxi to make targa files less picky
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1127999630
+X "folder" has been renamed to "path" to match savePath().
+X added "dataPath" to return the full path to something in the data folder
+X savePath should maybe be appletPath or sketchPath
+X because can be used for opening files too
+X (i.e. if needing a File object)
+X width, height set to zero in static mode
+X probably only set when resize() is called, and it's not happening
+X g.smooth is always false in opengl
+X http://dev.processing.org/bugs/show_bug.cgi?id=192
+
+o triangleColors are different because they're per-triangle
+o as opposed to per-vertex, because it's based on the facet of the tri
+X make vertexCount etc properly accessible in PGraphics3
+X so that people can do things like the dxf renderer
+X also have a simple way to hook in triangle leeches to PGraphics3
+X this exists, but needs to be documented, or have accessors
+
+
+0093 core
+X upgrade jogl to a newer rev to fix osx "cannot lock" issues
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1118603714
+X http://192.18.37.44/forums/index.php?topic=1596.msg79680#msg79680
+X faster blur code contributed by toxi
+X filter(ERODE) and filter(DILATE) contributed by toxi
+o textAscent() should probably be g.textAscent instead
+o more like textLeading() etc
+X nope, because it requires grabbing the font metrics and other calculations
+X bezierDetail, curveDetail made public
+X added textMode(SHAPE) for OPENGL
+X error message saying that strokeCap and strokeJoin don't work in P3D
+X textMode(SHAPE) throws ex when drawing and font not installed
+X fix a bug with filename capitalization error throwing
+X add NO_DEPTH_TEST to PGraphics3
+X java 1.4 code snuck into PApplet, causing problems on the mac
+X http://dev.processing.org/bugs/show_bug.cgi?id=146
+X prevent PGraphics.save() from inserting a file prefix
+X so that people can use absolute paths
+X or add a version that takes a file object
+
+nixed or fixed in previous releases
+X textMode(SCREEN) having issues on Mac OS X
+X seem to be problems with updatePixels() on the mac
+X appears to run asynchronously
+X move zbuffer et al into PGraphics so that people don't have to cast to P3
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Contribution_3DOpenGL;action=display;num=1116978834
+o noLoop() is behaving strangely
+o http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1116002432;start=0
+
+
+0092 core
+X rle-compressed tga save() method added by toxi
+X also version that only saves RGB instead of ARGB
+X proper/consistent api to access matrices in PGraphics/PGraphics3
+X first use loadMatrix(), then m00, m01 etc
+X find the post on the board and make a note of this
+X proper api for access to Graphics2D object in PGraphics2
+X just add the current "g2" thing to the faq
+X and make a note of it on the suggestions board
+X vars like cameraX etc need to be in PGraphics
+X otherwise g.xxxx won't work
+X how far should this go? vertices etc?
+X vertices not included because switching to triangleImpl and lineImpl
+X fix for copy() in java2d to make things a little speedier
+X make PApplet.main() for java 1.3 friendly (Color class constants)
+X remove call to background() in PGraphics2
+o change PGraphics to PGraphics2
+o or not, because PGraphics has all the base stuff for 3D
+o change PGraphics2 to PGraphicsJava or PGraphicsJava2D
+o maybe wait until the new shape stuff is done?
+X move font placement stuff back into PGraphics?
+X figure out how to get regular + java fonts working
+X use that do drive how the api is set up
+X optimize fonts by using native fonts in PGraphics2
+X especially textMode(SCREEN) which is disastrously slow
+X in java2d, can quickly blit the image itself
+X this way, can isolate it for gl too, which will use glBitmap
+X danger of this setup is that it may run much nicer for the author
+X i.e. with the font installed, and then super slow for their users
+X add "smooth" as a field inside the font file
+X and when smooth field is set, make sure JAVA2D enables smoothing
+X since otherwise smooth() has to be called for the whole g2
+X rob saunders contributed a fix for a bug in PImage.copy()
+X the wrong boundaries were being copied in the code
+X fix bug where noLoop() was waiting 10 secs to call exit()
+X add ability to draw text from the current text position
+
+
+0091 core
+X change to synchronization to hopefully fix some update issues
+X curveVertex() problem in P2D when > 128 points fixed
+_ http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115856359;start=0
+X for present mode, need to set a default display
+X currently crashes if only --present is specified w/o --display
+o make the 1.4 code in PApplet load via reflection
+X doesn't appear necessary with 1.3 applets
+o or is some of the stuff usable in 1.3 but not all?
+o ie. the device config classes exist but not the set full screen method
+X currently some bugs in the main() because it's not sizing applets
+X if running in present mode it works ok
+X but that also needs its display set.. argh
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115834600;start=0
+X add exit() function to actually explicitly quit
+X scripts will just require that people include exit at the end
+X esc should kill fullscreen mode (actually now it just quits anything)
+X can a key handler be added to the window? not really
+X add an escape listener to the applet tho.. but will it work with gl?
+X how can this be shut off for presentations?
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1114027594;start=0
+X present mode wasn't reading the stop button color
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Suggestions;action=display;num=1116166897;start=0
+X cleaned up the createFont() functions a little
+X java 1.3 required message isn't clickable
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1117552076
+
+
+0090 core
+X added arraycopy() function that calls System.arraycopy()
+X also the useful shortcut fxn
+
+
+0089 core
+X no changes since 88
+
+
+0088 core
+X createFont crashes on verdana (win2k)
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115258282;start=0
+X made ceil(), floor(), and round() return ints instead of floats
+X fix for PSound: Unsupported control type: Master Gain
+X just shuts off the volume control
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1115467831;start=0
+
+cleared out / completed in previous releases
+X typed version of expand() and contract()
+o fishwick bug with text() and shapes
+o ellipses no longer completed when g.dimensions = 2 or 3,
+o or not even drawn.. what a mess.
+X go through and figure out what stuff to make public
+o depth testing of lines vs text is problematic
+o probably need to patch in an older version of the line code
+o use depth()/noDepth() to handle depth test
+X on exceptions, use die to just kill the applet
+X make the file i/o stuff work more cleanly
+X if people want to use their own file i/o they can do that too
+o this could also be contributing to the hanging bug
+X static applets need to be able to resize themselves on 'play'
+X figure out what to do with static apps exported as application
+X needs to just hang there
+o scripts (w/ no graphics) will need to call exit() explicitly
+o actually.. just override the default draw() to say exit()
+X may need a fileOutput() and fileInput() function
+X to take care of exception handling
+o or maybe scripts are just handled with a different method? (yech)
+o or maybe setup() can actually throw and Exception?
+o but that's inserted by the parser, and hidden from the user?
+o implement size(0, 0) -> just doesn't bother doing a frame.show();
+o too abstract, just have draw() call exit by default
+o so if nothing inside draw, just quits
+o make properly exit after things are finished
+o still some weirdness with thread flickering on the mac
+o and frenetic display updates on the pc
+o move really general things out of PConstants (X, Y, Z..) ?
+X add something to PApplet to have constants for the platform
+o needed for error messages (don't talk about winvdig on mac)
+X and also useful for programs
+X bring screen space and font size settings back in to PGraphics
+X causing too much trouble to be stuck down in PFont
+
+
+0087 core
+
+fixed in previous releases
+X The PushPop example in Transformations is not working
+X with lights() callled
+X The transparency of the Rotate3D example in Translformations
+X is not as expected
+X lighting totally sucks (both PGraphics3 and PGraphicsGL)
+X bring in materials for opengl as well?
+X don't include a class, just make it similar to the light functions
+X sphere() and box() should set normals and take textures
+X background color seems to be wrong?
+X check this once lighting actually works
+X printarr() of null array crashes without an error
+X actually, errors from many crashes not coming through on the mac?
+
+
+0086 core
+X java 1.4 getButton() was inside the mouse handler
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1114147314;start=3
+X color() doesn't work properly because g might be null?
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1114518309;start=0
+X textMode(RIGHT) etc causing trouble.. tell ppl to use textAlign()
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1114219121;start=4
+X saveFrame with a filename still causing trouble:
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1114097641;start=0
+X fov should be in radians
+X present mode not working on macosx 10.2?
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1114381302;start=0
+X ex on endshape if no calls to vertex
+X http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1113940972
+X is camera backwards, or staying fixed and moving the scene?
+X camera() is broken, should be ok to call it at beinning of loop
+X end of lookat might be backwards
+X or endCamera might be swapping camera and cameraInv
+X beginCamera also grabs it backwards
+
+
+0085 core
+X camera() was missing from PGraphics
+X some tweaks to openStream() for loading images and less errors
+X basic clipping in P3D from simon
+
+
+0084 core
+X fixed create font / incremented font file version number
+X simon lighting fixes
+X added simon's lighting docs to lights() fxn in javadoc
+X set default stroke cap as ROUND
+X otherwise smooth() makes points disappear
+X hack for text with a z coordinate
+
+
+0083 core
+X fix double key events
+X fix mrj.version security error on the pc
+X set() fixes for PGraphics2 and setImpl inside PGraphics
+X remove angleMode (also from PMatrix classes)
+X remove/rename postSetup() stuff from PGraphics/PApplet
+X camera(), perspective(), ortho()
+X matrix set by the camera on each beginFrame
+X push/pop are now pushMatrix/popMatrix
+o get PGraphics.java engine working again
+
+lighting stuff
+X make fill() cover ambient and diffuse
+X provide separate call for ambient to shut it off
+o why does diffuse just mirror fill()?
+o seems to cover just diffuse, not ambient_and_diffuse like fill
+o maybe fill() should set diffuse, and sep call to ambient() sets ambient?
+X removed it
+X move dot() to the bottom w/ the other math
+
+already done
+X remove PMethods as actual class, use recordFrame(PGraphics)
+X size(200, 200, "processing.illustrator.PGraphicsAI");
+
+api questions
+o image(String name) and textFont(String name)
+o do we change to font(arial, 12) ?
+X remove angleMode() ?
+X be consistent about getXxx() methods
+X just use the variable names.. don't do overkill on fillR et al
+X or just what functions are actually made public
+X is fillRi needed? it's pretty goofy..
+X how to handle full screen (opengl especially) or no screen (for scripts)
+
+tweaking up simong light code
+o what's up with resetLights?
+o add PLight object to avoid method overflow
+o preApplyMatrix, invApplyMatrix?
+o applyMatrixPre and applyMatrixIn
+o rotateXInv is ugly..
+o irotateX?, papplyMatrix?
+
+wednesday evening
+X expose api to launch files, folders, URLs
+X use with/in place of link()
+X call it open()
+X what to call firstMouse
+X implement rightMouse?
+X yes, mouseButton = LEFT, CENTER, or RIGHT
+X error when running on 1.1...
+X You need to install Java 1.3 or later to view this content.
+X Click here to visit java.com and install.
+X make inverseCamera into cameraInv
+X fix messages referring to depth()
+X route all of them through a single function rather than current waste
+X fix bezierVertex() in P3D for newer api
+
+wednesday late
+X track loadImage() with filenames that are inconsistent
+X really a problem with the ves61r kids
+X i.e. mixed case filename in sketch is different in windows
+X but when uploaded to a unix server causes a serious problem
+X use canonicalPath to flag possible problems
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1096508877;start=5
+o fix shapes in P3D (line loop, polygons, etc)
+o should we include a from and to for the directional light?
+X no, cuz it doesn't do much really..
+X fromX-toX etc is all that's different
+
+thursday day
+X set modelview to camera on endCamera
+X add ortho() and perspective() to PGraphics.java
+
+thursday evening
+o textMode(ALIGN_LEFT) etc, should make sure that left/center/right not used
+X though since have to change to LEFT, should be easy to switch
+
+friday night
+o should toInt('5') return the ascii or the char?
+X since (int) '5' returns the ascii, that's what it does
+X made a note in the PApplet reference
+
+text api
+X textMode ALIGN_CENTER _LEFT _RIGHT -> CENTER, LEFT, RIGHT ?
+X use built-in font if available? yes
+o text() with \n is semi-broken
+X does the font or PApplet control the size? (the font, ala java)
+X without setting the font, SCREEN_SPACE comes out weird
+o move SCREEN_SPACE into ScreenFont() class?
+o probably not, casey thinks screen space text is prolly more useful
+o that way can clear up some of the general confusion in the code
+X textFont with a named font can use the renderer/os font
+X illustrator api can get the ps name from the java font name
+X since it's associated with the font file.. wee!
+X for postscript, can grab the real font
+o altho problem here is that really the fonts just need a name
+o since needs to render to screen as well
+o font has to be installed to get psname
+X fine because why would you embed a ps font that you don't have?
+o need to resolve SCREEN_SPACE vs OBJECT_SPACE
+o can this be auto-detected with noDepth()?
+o how does rotated text work?
+o PFont.rotate(180) rotate(PI)
+o or can this be detected from the matrix?
+X don't use pixels to do screen space text inside PFont
+X add a function in PGraphics for direct pixel image impl
+X store the font name in the vlw font file (at the end)
+o could include multiple names for multi platforms
+X get text impl stuff working properly
+o look into fixing the texture mapping to not squash fonts
+o NEW_GRAPHICS totally smashes everything
+
+friday postgame
+X implement createFont()
+X with a .ttf does a create font internally (1.3+ only)
+X although the images aren't populated
+X until a P2D/P3D/OPENGL tries to draw them, which triggers it
+X but if PGraphics2, just uses the built-in font
+X also works for font names and just creating them
+X if font name doesn't end with otf or ttf, then tries to create it
+X change objectX/Y/Z to modelX/Y/Z
+X PFont.list() to return string list of all the available fonts
+X probably not a mode of use that we really want to encourage
+X actually important because the whole graphicsdevice crap is silly
+X and we need a 1.1 versus 1.3/1.4 version
+X implement printarr() as println() ?
+X actually deal with all the array types.. oy
+X should nf() handle commas as well?
+X just add a basic nfc() version for ints and floats
+o yes, and add nf(int what) so that non-padded version works
+o but don't put commas into the zero-padded version
+o make nf/nfs/nfp not so weird
+o nf(PLUS, ...) nf(PAD, ...) nfc(PLUS, ...)
+X unhex was broken for numbers bigger than 2^31
+
+saturday late afternoon
+X fix bug with openStream() and upper/lowercase stuff
+X do a better job of handling any kind of URLs in openStream()
+
+sunday morning
+X incorporate simon's new lighting code
+
+
+0082 core
+X make jdkVersion, jdkVersionName, platform, platformName variables
+X additional note about screen sizes and displays
+X sto instead of stop in present mode
+X appears that opengl libraries weren't correctly added in 81?
+X requestFocus() now called on gl canvas
+X basic lights now work by default
+
+
+0081 core
+X background(PImage) now works in opengl
+X when running externally, applets don't always get placed properly
+X if size is never set, then doesn't always layout
+X problem is in gl and in core, and is inconsistent
+X move more logic for layout into PApplet.. maybe a static method?
+X this way can avoid duplicating / breaking things
+o what is the stroked version of a sphere? a circle?
+X write list of params that can be passed to PApplet
+o document in the code a note about how size() et al place themselves
+X saveFrame was double-adding the save path because of save() changes
+
+size(200, 200, P3D) - createGraphics and placement issues
+X make pappletgl work back inside papplet
+X and then size(300, 300, DEPTH) etc
+X get rid of opengl renderer menu
+o otherwise hint() to use the p5 renderer instead of java2d
+X applet placement is screwy
+X how to force PGraphics() instead of PGraphics2()
+X size(300, 200, P2D);
+X size() doing a setBounds() is really bad
+X because it means things can't be embedded properly
+o applets on osx (and windows) sometimes show up 20 pixels off the top
+X how to shut off rendering to screen when illustrator in use?
+X need size(30000, 20000) for illustrator, problem in papplet
+X size(30000, 20000, ILLUSTRATOR)
+X make Graphics2 et al load dynamically using reflection
+X can this be done with g2 and if exception just falls back to g1?
+X this way people can remove g1 by hand
+o size() that changes renderer will throw nasty exception in draw()
+X or maybe that's ok? document that no changing renderers?
+X take a look to see what needs to happen to get PAppletGL merged in
+X i.e. can i just extend GLCanvas?
+
+present mode
+o call present() from inside the code?
+o that if applet is 500x500, centers on a 800x600 window
+X no, that's nasty... use --present to launch in present window
+X though how do you get the screen size?
+X screen.width and screen.height? - yes
+X write java 1.4 code for full screen version of PApplet
+X this might be used for presentation mode
+X proper full screen code for present mode
+X why do mouse motion events go away in full screen mode
+X or with a Window object
+X use screen manager to run present mode properly
+X set both versions to require java 1.4
+X change the Info.plist inside macosx
+X and add something to PdeBase to make sure that it's in 1.4
+X running present mode with a bug in the program hoses things
+X make sure the program compiles before starting present mode
+
+
+0080 core
+X PApplet.saveFrame() is saving to sketch folder, PApplet.save() is not
+X PApplet.save() will save to the applet folder,
+X but PImage.save() or PGraphics.save() will save only to the current
+X working directory, usually the Processing folder.
+X removed static version of mask() from PImage
+X no more PImage.mask(theImage, maskImage)
+X just use theImage.mask(maskImage)
+X PImage.filter()
+X maybe use quasimondo's gaussian blur code?
+X http://incubator.quasimondo.com/processing/gaussian_blur_1.php
+o filter() on subsections? yes, in keeping with rest of api
+X no, in keeping with getting shit done
+X BLUR - write simple blur
+X how does photoshop handle this?
+X BLUR - add gaussian blur
+X email re: credit/attribution and descrepancy between algos
+X forgot to mention the line hack to get points working in 78
+X implemented PGraphicsGL.set(x, y, argb)
+X implement PGraphicsGL.set(x, y, PImage)
+X blend, copy, filter all implemented for opengl
+X copy(Pimage, x, y) has become set(x, y, PImage)
+X textMode -> textAlign
+X ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT -> LEFT, CENTER, RIGHT
+X textSpace -> textMode
+X NORMAL_SPACE -> NORMALIZED, OBJECT_SPACE -> OBJECT
+X text in a box is broken (at least for PGraphics2)
+o check to see if it's a rounding error with width()
+o get text rect working again (seems to be in infinite loop)
+X nope, was just that the space width wasn't being scaled up properly
+X clean up the javadoc so no more errors
+X change mbox to PFont.size?
+o make width() return values based on natural size?
+X not a great idea.. plus java2d uses 1 pixel font for things
+X email simon re: lighting api
+X things are actually more on track than expected
+X camera is swapping colors in gl (on mac?)
+X in fact, all textures on mac were swapping colors
+X test this on windows to see if fixed
+X sphere x,y,z,r or box w,h,d.. need to make them consistent
+X goodbye sphere(x, y, z, r)
+o should available() be waiting() or something like that instead?
+o go through and see what functions (no pixel ops?) frame recorders should have
+X decided instead to use recordFrame(PGraphics)
+o remove SCREEN_SPACE altogether?
+X can't do this for now
+
+implemented in 79
+X make sure arc goes in the right direction that we want it to
+X (make sure that PGraphics3 goes the same direction)
+
+
+0079 core
+X no changes to core in this release
+
+
+0078 core
+X text fixes
+X lines were getting horizontally mashed together
+X lines also getting vertically smashed together
+X make a note of the change to font.width()
+X backwards rects and backwards ellipses weren't properly drawn
+X code now compensates for negative widths or swapped x1/x2
+X what to do about backwards images
+X imageMode() wasn't being set properly
+X fix noLoop() not properly running
+X If noLoop() is called in setup(), nothing is drawn to the screen.
+X also fix redraw() to include interrupt() again
+X loadPixels throwing NPEs
+X fixes to SCREEN_SPACE text not being sized properly
+X loadPixels()/updatePixels() on screen space text (ouch)
+X get SCREEN_SPACE text working again
+X patch in newer jogl.. too many BSODs
+X saveFrame seems to be broken
+X fixed for PGraphics2
+X fixed for PGraphicsGL
+X also implemented loadPixels/updatePixels for gl
+X fix tint() with color and alpha for PGraphics2
+X alpha() colors are inverted (white is opaque.. doesn't make sense)
+X should we swap this around? no - this is how photoshop works
+X fix arc
+X get() is back
+X set camera.modified so that it draws properly
+X it's annoying not having a copy() function inside PImage
+X formerly get() with no params
+o clone throws an exception
+o PImage constructor that takes itself?
+o PImage copy = new PImage(another);
+X got rid of CONCAVE_POLYGON and CONVEX_POLYGON
+X hack for points to work in opengl, but still not working broadly
+X work on filter() functions
+X POSTERIZE - find simple code that does it?
+X there must be a straightforward optimized version of it
+o EDGES - find edges in casey's example is differen than photoshop
+o which version do people want with their stuff
+X edges filter removed
+X several fixes to Movie and Camera to work with the new gfx model
+X PImage.get(x, y, w, h) had a bug when things went off the edge
+X set defaults for strokeCap and strokeJoin
+X get() and gl images were broken for screen sizes less than full size
+X fix arcs, were badly broken between java2d and pgraphics
+X look at curve functions more closely
+X should we switch to curveVertex(1,2,3) (ala curveto)
+X because some confusion with mixing types of curves
+o make sure we don't want curveVertices(1,2,3,u,v)
+o also make test cases so that java2d and java11 behave the same
+X implement PGraphics2.curveVertex()
+X updatePixels() not setting PApplet.pixels
+X make loadPixels in PGraphics ignored, and put it in PApplet
+X made loadStrings() and openStream(File) static again
+X test loadPixels()/updatePixels()/saveFrame() on the pc
+X better, just assume that they need the endian swap
+X fixed draw mode apps for opengl
+X (gl was missing a beginFrame)
+X pmouseX, pmouseY are not working in OpenGL mode
+X (as they are working in Processing mode)
+
+o screenX/Y aren't properly working for 2D points against a 3D matrix
+o (ryan alexander rounding bug)
+o Just to clarify, it works completely correctly with rounding
+o screenX/Y and also using the 3 arg version of translate -
+o ie translate(hw,hh,0) instead of just translate(hw,hh).
+X no longer an issue because moving to 2D and 3D modes
+o PImage: remove the static versions of manipulators?
+o probably not, because they're inherited by PApplet
+o i.e. mask(image, themask);
+X no PImage needed b/c PGraphics is a PImage
+o colorMode(GRAY) to avoid stroke(0) causing trouble?
+o or maybe get rid of stroke(0)? hrm
+
+
+0077 core
+X bring back pmouseX/Y using a tricky method of storing separate
+X values for inside draw() versus inside the event handler versions
+X debug handling, and make firstMouse public
+X explicitly state depth()/nodepth()
+X don't allocate zbuffer & stencil until depth() is called
+X arc with stroke only draws the arc shape itself
+X may need a 'wedge' function to draw a stroke around the whole thing
+X only allocate stencil and zbuffer on first call to depth()
+X this will require changes to PTriangle and PLine inside their loops
+X try running javadoc
+X die() may need to throw a RuntimeException
+o call filter() to convert RGB/RGBA/ALPHA/GRAY
+o cuz the cache is gonna be bad going rgb to rgba
+X don't bother, people can re-create the image or set cache null
+X fix font coloring in PGraphics2
+X fix tint() for PGraphics2
+X get text working again
+X partially the problem is with ALPHA images
+X how should they be stored internally
+X also colored text, requires tint() to work properly
+X move textMode and textSpace back out of PFont
+X use die() to fail in font situations
+X can't, just use a RuntimeException
+
+covered in previous
+X before graphics engine change, attach jogl stuff
+X need to try jogl to make sure no further changes
+X and the illustrator stuff
+o massive graphics engine changes
+o move to new graphics engine
+o test with rgb cube, shut off smoothing
+o make sure line artifacts are because of smoothing
+o implement 2x oversampling for anti-aliasing
+o renderers can plug in:
+o at direct api level
+o taking over all color() functions and vertex collection
+o at endShape() level
+o where vertices are collected by core and blit on endShape()
+o (takes polygons and lines)
+o at post tesselation level
+o takes only line segments and triangles to blit (dxf writer)
+o api for file-based renderers
+o need to work this out since it will affect other api changes
+o size(0, 0) and then ai.size(10000, 20000)
+o size 0 is code for internal to not show any window
+o saveFrame(PRenderer) or saveFrame("name", PRenderer)
+o saveFrame gets called at the beginning of loop()
+o or is just a message to save the next frame (problem for anim)
+X vertices max out at 512.. make it grow
+X add gzipInput and gzipOutput
+X light(x, y, z, c1, c2, c3, TYPE)
+X also BLight with same constructor, and on() and off() fxn
+X make sure applet is stopping in draw mode
+X loadImage() is broken on some machines
+X hacked for a fix in 72, but need to better coordinate with openStream()
+
+postscript
+X pushing all intelligence down into class that implements PMethods
+o keep hints about type of geometry used to reconstruct
+o no special class, just uses public vars from PGraphics
+o how to hook into curve rendering so that curve segments are drawn
+o maybe lines are rendered and sorted,
+o but they point to an original version of the curve geometry
+o that can be re-rendered
+o also integrate catmull-rom -> bezier inverse matrices
+o even with the general catmull-rom, to render via ai beziers
+
+api changes
+X removed circle.. it's dumb when ellipse() is in there
+X (it's not like we have square() in the api)
+X arcMode is gone.. just uses ellipseMode()
+X save tga and tif methods are static and public
+X imageMode(CORNER) and CORNERS are the only usable versions
+X alpha(PImage) is now called mask() instead
+X already have an alpha() function that gets alpha bits
+X on start, mouseX is 0.. how to avoid?
+X use firstMouse variable.. figure out naming
+X get frame recording working
+X not tested, but at least it's there
+
+image stuff
+o could also do PImage2, which would need a getPixels() before messing w/ it
+o bad idea, distinction not clear
+o even in java 1.1, could use regular java.awt.Image and require getPixels()
+o -> 1.1 wouldn't help anything, because needs pixels to render, oops
+X the updatePixels() in PGraphics has to be overridden (from PImage)
+X to make itself actually update on-screen
+X actually, should be no different than the check_image function
+X PGraphics2 and PGraphicsGL will need loadPixels() to be called
+X in order to read pixels from the buffer
+X loadPixels() and updatePixels() prolly should be shut off in opengl
+X make people use get() instead to grab sub-images
+X PGraphicsGL.copy() needs to be overridden.. use glDrawBitmap
+o loadImage() needs to handle 1.1 vs 1.3 loading
+o set image.format to be BUFFERED? no.. just use RGBA always
+o have a flag to always use the cache, i.e. with BufferedImage
+o turn that off when someone modifies it (nope, no need to)
+X PImage.getPixels(), updatePixels(), updatePixels(x, y, w, h),
+o PImage.setPixels(int another[]);
+X imageMode(CENTER) is weird for copy() and updatePixels()
+X perhaps copy() and get() ignore imageMode and use xywh or x1y1x2y2?
+X or disallow imageMode(CENTER) altogether?
+o in java 1.3, getPixels() can call getRGB() via reflection
+o cache.getClass().getName().equals("BufferedImage")
+X readPixels/writePixels?
+X has to happen, since this is so fundamental to gl as well
+X loadImage in 1.3 leaves pixels[] null (not in 1.1)
+X 1.3 plus gl is a problem, since conflicting caches
+X gl has no need for a bufferedimage tho
+X so maybe checks to see if the cache is a BufferedImage
+X if it is, calls getPixels to set the int array
+X then replaces cache with glimageache
+X pappletgl loadimage could take care of this instead
+X calls super.loadImage(), if cache != null, proceed..
+X this is prolly a mess
+X PImage.getPixels() and PImage.getPixels(x, y, w, h) ->
+X (the xywh version still allocates the entire array, but only updates those)
+X only needed for java2d
+X not (necessarily) needed when loading images,
+X but definitely needed when setting pixels on PGraphics
+X PImage.updatePixels() and PImage.updatePixels(x, y, w, h)
+X (this is actually just setModified)
+X in opengl, marks all or some as modified
+X so next time it's drawn, the texture is updated PGraphicsGL.image()
+X in java2d, updates the BufferedImage on next draw
+X can't use regular getPixels() on PGraphics, because its image isn't 'cache'
+X also, the cache may be used to draw the whole surface as a gl texture (?)
+X not a problem for the main PGraphics, but for any others created to draw on
+
+opengl
+X make light() functions actually do something in PGraphicsGL
+X box() and sphere() working again
+X make opengl work in draw mode
+X set initial size using --size=
+X color channels seem to be swapped on windows in image example
+X check on the mac to see what it looks like
+
+X default to single byte input from serial port
+X and add serial.setBuffer() for message length as alternative
+X or serial.setDelimiter() to fire message on delim
+X named it bufferUntil();
+
+
+0076 core
+X no changes, only launcher issues
+
+
+0075
+X textureMode(NORMAL_SPACE) screws up the image() command
+X image() appears to require IMAGE_SPACE to function properly.
+X added focusGained() and focusLost()
+X lots of changes to internal naming of vars
+X screenX(x, y) and screenY(x, y) added for noDepth()
+X add TRIANGLE_FAN
+X eyeX, eyeY etc have been renamed cameraX/Y/Z, and cameraNear/Far
+X modify targa and tiff writing routines to break into header writing
+X writeTIFF, writeHeaderTIFF, writeTGA, writeHeaderTGA
+X MAJOR CHANGE: RGBA becomes ARGB for accuracy
+o uv coords > 1 shouldn't clamp, they should just repeat ala opengl
+o actually i think opengl has a setting for it
+o remove need to use depth() at the beginning
+X need only be set once
+X pmouseX is broken again
+X remove pmouseX/Y altogether
+X maintain things a bit different
+o email the beta@ list to see how people are using pmouseX
+X changed PMovie.length to PMovie.duration
+X move around/simplify loadImage() inside PApplet
+X working to add more die() statements inside PApplet
+o can ALPHA fonts work using the other replace modes?
+
+fixed in previous releases
+X text stuff
+X text() with alignment doesn't work for multiple lines
+X don't change the size of a font when in screen space mode
+X patch rotated text (from visualclusto) into bfont
+X what sort of api? textSpace(ROTATED) ?
+X rotated text has a bug for when it goes offscreen
+
+opengl
+X why is the thing hanging until 'stop' is hit?
+X what happens when stop is hit that sets it free?
+X (at what point does it start working properly?)
+X cache needs to also make things a power of 2
+X if images are already a power of 2, then needn't re-alloc
+X cacheIndex needs to be set to -1 when the image is modified
+X or maybe have a modified() function?
+X debug why certain spots are having errors (see 'problem here' notes)
+X INVALID_OPERATION after drawing lines for cube
+X fix noLoop bug
+X remove errors when drawing textures
+X reverse y coordinates
+X make play button un-highlight with opengl
+X also make window move messages work properly
+X very necessary, since opens window at 100x100
+X problem was the threading issues
+X bring back renderer menu
+X reading/saving pref for opengl renderer
+X remove cameraMode(PERSPECTIVE) on each frame
+X why is the first one failing?
+X still threading issues with running opengl
+X threading really horks up dual processor machine..
+X first run hangs until quit
+X though doesn't seem to replicate when p5 is restarted
+X make sure background() gets called at least once with opengl
+X otherwise screen never actually updates
+X beginFrame() around setup()
+X draw mode stuff happens inside setup..
+o or maybe need to get better at size() inside of draw() ?
+X make this consistent with the regular PApplet
+X otherwise things are going to be weird/difficult for debugging
+
+
+0074 core
+X removed zbuffer precision hack in PLine to improve z ordering
+X no longer set g.dimensions = 3 when using vertex(x, y, 0)
+
+
+0073 core
+X tweak to fonts to use TEXT_ANTIALIAS because of macosx @#$(*&
+X loadImage() is broken on some machines
+X hacked for a fix in 72, but need to better coordinate with openStream()
+
+
+0072 core
+X make m00, m01 etc public
+X hack to make loadImage() work
+X cache settings are ignored, may be slow as hell
+X make hints[] no longer static
+X they weren't properly resetting
+
+
+0071 core
+X properly swap alpha values when lines need to be rendered backwards
+X make cursor() commands public
+X ltext and rtext for screen space stuff
+X ltext is broken when it goes y < 0 or y > height
+X ltext & rtext completely working
+X make sure font creator is making fonts properly fixed width
+X probably not using java charwidth for the char's width
+X probably wasn't using textFont() properly
+X now that it's actually a key, should it be a char? (what's keyChar?)
+X that way println(c) would work a little better..
+X libraryCalls() not properly working for pre, post, or draw()
+o image(myg, x, y) doesn't work but image(myg, x, y, w, h) does
+o (image kind prolly not set right and so image() gets pissy)
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1091798655
+
+text fixes
+X make text rect use rectMode for placement
+X if a word (no spaces) is too long to fit, insert a 'space'
+X move left/center/right aligning into the font class
+X otherwise text with alignment has problems with returns
+X could PFont2 be done entirely with reflection?
+X that way other font types can properly extend PFont
+o font char widths from orator were not fixed width
+o may just need to regenerate. if not, widths may be set wrong.
+
+
+0070 core
+o check ordering of split() in java vs perl for regexp
+X don't include empty chars in font builder
+X .vlw font files are enormous with full charset
+X check to see if the character exists before adding it to the font
+X fixed (unreported) problem with char lookup code
+o split() with multiple args (i think this is completed)
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1078985667
+X trim() not chop().. whups
+X random(5, 5) -> return 5, random(6, 4) return error
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1083275855;start=0
+X use random.nextFloat() because it's faster
+X make grayscale image in p5
+X could be used with alpha() to properly set alpha values
+X made into filter(GRAYSCALE) and filter(BLACK_WHITE) functions
+X make g.depthTest settable as a hint
+X http://processing.org/discourse/yabb/YaBB.cgi?board=BugFixes;action=display;num=1096303102;start=0
+X #ifdef to remove client and server code as well
+X need to resolve issues between rendering screen/file
+X illustrator-based rendering needs to work for ars projects
+X screen may be 400x400 pixels, but file be 36x36"
+X launcher.cpp broke serial.. see versions in processing.notcvs
+X rewrite bagel code..
+X for this release, because it will break things along with the lib stuff
+X switch to PImage, PApplet, etc
+o bug in BImage.smooth() when resizing an image
+o http://processing.org/discourse/yabb/YaBB.cgi?board=BugFixes;action=display;num=1096303158;start=0
+X shut off the automatic gunzipping of streams, keep for fonts
+X fix for duplicated points in polygons that foiled the tesselator
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1077819175
+X cleaned up texture() code between NEW/OLD graphics
+X not quite so much duplicated in cases etc.
+X lines: vertex coloring bug with my swap hack
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1085348942
+X last vertex on LINE_LOOP fades out
+X http://processing.org/discourse/yabb/YaBB.cgi?board=BugFixes;action=display;num=1096303406;start=0
+X include values in PConstants for additional blend modes:
+X DIFFERENCE, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT
+X include a lerp()? is there one in flash?
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Programs;action=display;num=1083289030
+X should it be called lerp or mix?
+X acos, asin, atan, log, exp, ceil/floor, pow, mag(x,y,z)
+X color issues
+X doesn't work when outside a function:
+X color bg_color = color(255,0,0);
+X colorMode broken for red() green() etc
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1068664455
+X add color(gray) and color(gray, alpha)
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1089898189;start=0
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_Software;action=display;num=1090133107
+o update() mode needs to be hacked in (?)
+X make 'online' a boolean
+X pass in args[] from main
+X angleMode(DEGREES) and angleMode(RADIANS)
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_Software;action=display;num=1075507381;start=0
+X fixes to line and curve code
+X api to properly sense when applet has focus
+X add a 'focused' variable to the applet
+X code now in zipdecode, maybe just list this as a standard thing?
+X do applets know when they're stopped? stop? dispose?
+X would be good to set a param in p5 so that the thread dies
+X if people have other threads they've spawned, impossible to stop
+
+cleaning up
+X make bagel more usable as standalone
+X breakout BGraphics (have its own BImage)
+o breakout BApplet into BComponent ? (fix out-of-bounds mouse - doesn't)
+o opengl export / rendering mode
+o currently implemented, but somewhat broken
+o finish this once all the line code is done
+o make possible to use buzz.pl to create versions w/ stuff removed
+o build gl4java for java 1.4
+o separating of BGraphics and BApplet
+o change copyrights on the files again (to match ?)
+X loadStrings has a problem with URLs and a code folder
+o turned out to be a problem with firewall/antivirus software
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1086551792
+o when running as an applet, need to loadStream from documentBase too
+o problem is that BGraphics has the loadStream code, not BApplet
+o new sphere code from toxi
+o already added a while back
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1067005325
+o sphere code needs only front face polygon
+o all triangles must be counter-clockwise (front-facing)
+X fix loadImage to be inside PApplet
+
+040715
+X saveFrame() to a folder horks things up if a mkdirs() is required
+X on macosx, this makes things hang; on windows it complains
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1081706752;start=0
+X decide on whether to use PTools
+X decided against, since it doesn't help anything
+X and some functions need the applet object, so it's just annoying
+o i.e. move math functions into utility library
+o check what other functions require PGraphics to exist but shouldn't
+o look at BGraphics to see if setting an 'applet' could be used
+o then other than that, if no applet set, no connection to PApplet
+
+040716
+X change font api to not use leading() as a way to reset the leading
+X resetLeading and resetSize are the things
+X embed all available chars from a font, so japanese, etc works
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_Software;action=display;num=1083598817;start=3
+X fix a bunch of font bugs regarding charsets and lookup
+X array operations: boolean, byte, char, int, float, String
+X expand/contract
+X append, shorten
+o shift/unshift
+o slice
+X splice
+X reverse
+X concat
+
+040717
+X make clone() into copy()
+X add a method BApplet.setPath() or something like that
+X use it to repair saveBytes, saveStrings, etc
+X put screenshots into their sketch folder
+o http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1046185738;start=0
+X full casting operations on primitives and arrays of them
+X text(String text, x, y, width, height) // based on rectMode
+X textMode() for align left, center, right (no justify.. har!)
+X hex(), binary(), unhex(), unbinary()
+
+040725
+X fix array functions not returning a value
+
+040726
+X noiseSeed and randomSeed
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_Software;action=display;num=1090749784;start=0
+
+040727
+X incorporated NO_FLYING_POO line/poly hack developed for axel
+
+040902
+X sort() should return an array, rather than sort in place
+X fix binary function, had wrong offset number
+X casey: i wan't able to get binary() to work at all:
+o Typography: Helix won't compile
+o works fine, just needs BFont -> PFont
+X standalone 'alpha' function for PImage (static methods for alpha fxns)
+X Image: Edge, Image: Blur: Alpha not set? The error is easier to see on Blur
+X turns out bounds checking wasn't working properly on colors
+
+040903
+X fix mouse/key events, make properly public for the package stuff
+X The biggest problem was the key and mouse functions not working.
+X Input: Mouse_Functions
+X Input: Keyboard_Functions
+X processing.net -> PClient, PServer
+X write client/server implementations for new-style api
+X basic test with old net server has things working fine
+
+040908
+X inputFile, outputFile, reader, writer commands
+X also loadStrings(File file)
+
+040913
+X printarr instead of print/println for arrays
+X println(Object o) conflicts with println(int a[])
+X but println(Object o) is very needed
+
+040919
+X loop/noLoop setup
+
+040920
+X make loop/noLoop work properly
+X fixes/changes to key and mousehandling
+X tab key not working?
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1091853942;start=0
+X mousePressed, keyPressed, others.. queue them all
+X queue multiple times
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1079555200;start=0
+X strangeness with key codes on keyPressed
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1083406438;start=0
+X key codes not properly coming through for UP/DOWN/etc
+X had to bring back keyCode
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1075138932;start=0
+X add redraw() function
+X call redraw() on the first time through (to force initial draw)
+X otherwise noLoop() in setup means no drawing happens at all
+
+040920 evening
+X defaults for PApplet and PGraphics are different
+o PGraphics has none.. PApplet has fill/stroke
+X actually not the case, only that wasn't calling decent superclass
+X set PImage.format as RGB by default?
+X this was problem with rendering an image from PGraphics on board
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1091798655;start=0
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1080671926;start=0
+
+040921 morning
+X bug in get() that was removing the high bits (rather than adding)
+
+040921 evening
+X lots of work on libraries, figuring out PLibrary api
+
+040922
+X get library stuff debugged
+X port arcball and finish up dxf writer
+X beginCamera() no longer sets an identity matrix
+
+040925
+X make savePath() and createPath() accessible to the outside world
+X useful for libraries saving files etc.
+
+
+0070p8
+X sizing bug fix to fonts, they now match platform standards
+X however, *this will break people's code*
+X text in a box not written
+X make sure to note in the docs that text/textrect position differently
+o for this reason, should it be called textrect()?
+X font heights and leading are bad
+X get good values for ascent and descent
+X if ScreenFont subclasses PFont.. can that be used in textFont()?
+X check to make sure the tops of fonts not getting chopped in font builder
+
+
+0069 bagel
+X text(x, y, z)
+X fixed camera modes / replaced how isometric is handled
+X whoa.. BGraphics.screenX() et al had the camera stuff shut off
+X and that's what shipped in 67. shite.
+X need to get things fixed up properly so camera is properly set
+X ISOMETRIC was completely broken.. need to implement properly
+X also, the default camera is perspective
+X cameraMode(PERSPECTIVE) and cameraMode(ORTHOGRAPHIC) setup basic cameras
+X if the user wants a custom camera, call cameraMode(CUSTOM); before begin()
+X printMatrix() and printCamera() to output the matrices for each
+X more functions made static (loadStrings, loadBytes) that could be
+X print() commands in BApplet were among these
+X die() command to exit an application or just stall out an applet
+X die(String error) and die(String error, Exception e)
+X more documentation in comments for functions
+X chop() function that properly also handles nbsp
+X join() was handled weird
+X run nf() and nfs() on arrays
+X nfp() to show plus sign
+X toInt, toFloat, toDouble (nf is for toString.. inconsistent)
+o split() function splits strings instead of splitStrings()
+o ints() converts an array of strings/doubles/floats to an int array
+o split() should also use StringTokenizer
+o to do countTokens() and then stuff into an array
+o shave() or chomp() or trim() method to remove whitespace on either side
+o including unicode nbsp
+X min() and max() with three values were broken (now fixed)
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1076804172
+X CONTROL wasn't properly set in BConstants
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1077058788
+X macosx.. flickering several times on startup
+X fixed this, along with other sluggishness related threading issues
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1073111031
+X bug with charset table on older fonts
+X index_hunt was look through the table, not what was in the font
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1077475307;start=0
+X seems to be some difficult threading problems still present
+X fixed many threading issues across macosx and linux
+X side-porting changes
+X new(er) line code is not in the main 'processing'
+X making perlin non-static not in the main bagel
+X polygon stroking hack code from the end of 68
+X erikb found a bug inside split(), it would die on empty strings
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Proce55ing_software_bugs;action=display;num=1077664736
+X fixed it, also modified behavior of split() with a delimeter
+X previously, it would remove the final delimeter and an empty entry
+X but that's now disabled, since the split cmd is very specific
+X code from toxi to support .tga files in loadImage
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Programs;action=display;num=1078459847;start=0
+X fix bug where single pixel points were ignoring their alpha values
+X static loadStrings and loadBytes aren't being added to BApplet
+X (the versions that use an inputstream)
+X added support for handling static functions in make.pl
+X threading is broken again on windows
+X windows needs a sleep(1) instead of the yield()
+X random(3) should be non-inclusive of the 3
+X http://processing.org/discourse/yabb/YaBB.cgi?board=Syntax;action=display;num=1079935258;start=5
+
+api changes
+X loadStream -> openStream for better consistency
+
+jdf
+X dynamic loading of code for setting cursor (removed JDK13 ifdef)
+X why aren't cursors working on the mac?
+X fix from jdf to just set size to 0,0
diff --git a/core/license.txt b/core/license.txt
new file mode 100644
index 000000000..16f1ad162
--- /dev/null
+++ b/core/license.txt
@@ -0,0 +1,456 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[ This is the first released version of the Lesser GPL.
+ It also counts as the successor of the GNU Library Public
+ License, version 2, hence the version number 2.1. ]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
\ No newline at end of file
diff --git a/core/make.sh b/core/make.sh
new file mode 100755
index 000000000..78d91b33a
--- /dev/null
+++ b/core/make.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+#javadoc -public -d doc *.java
+#javadoc -private -d doc *.java
+chmod +x preproc.pl
+./preproc.pl
+jikes -d . +D *.java
diff --git a/core/preproc.pl b/core/preproc.pl
new file mode 100755
index 000000000..40ba9bba2
--- /dev/null
+++ b/core/preproc.pl
@@ -0,0 +1,186 @@
+#!/usr/bin/perl -w
+
+$basedir = 'src/processing/core';
+
+@contents = ();
+
+# next slurp methods from PGraphics
+open(F, "$basedir/PGraphics.java") || die $!;
+foreach $line () {
+ push @contents, $line;
+}
+close(F);
+
+# PGraphics subclasses PImage.. now get those methods
+open(F, "$basedir/PImage.java") || die $!;
+foreach $line () {
+ push @contents, $line;
+}
+close(F);
+
+#open(DEBUG, ">debug.java") || die $!;
+#print DEBUG @contents;
+#close(DEBUG);
+#exit;
+
+
+open(APPLET, "$basedir/PApplet.java") || die $!;
+@applet =