[Pkg-osm-commits] [SCM] jmapviewer branch, master, updated. upstream/0.0+svn29245+dfsg-27-gc4a178a

Felix Natter fnatter at gmx.net
Thu Oct 3 10:51:51 UTC 2013


The following commit has been merged in the master branch:
commit b7ff9e7493c0a51e6ba590beec934602845b3df4
Author: Felix Natter <fnatter at gmx.net>
Date:   Thu Oct 3 11:59:20 2013 +0200

    Imported Upstream version 1.0

diff --git a/.classpath b/.classpath
deleted file mode 100644
index d171cd4..0000000
--- a/.classpath
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/.project b/.project
deleted file mode 100644
index b18095b..0000000
--- a/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>OSM</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 80b990a..0000000
--- a/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-#Wed Jul 16 10:49:16 CEST 2008
-eclipse.preferences.version=1
-encoding/<project>=UTF-8
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 3408a14..0000000
--- a/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,280 +0,0 @@
-#Sun Jan 31 13:16:40 CET 2010
-eclipse.preferences.version=1
-org.eclipse.jdt.core.codeComplete.argumentPrefixes=
-org.eclipse.jdt.core.codeComplete.argumentSuffixes=
-org.eclipse.jdt.core.codeComplete.fieldPrefixes=
-org.eclipse.jdt.core.codeComplete.fieldSuffixes=
-org.eclipse.jdt.core.codeComplete.localPrefixes=
-org.eclipse.jdt.core.codeComplete.localSuffixes=
-org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
-org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
-org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
-org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
-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=error
-org.eclipse.jdt.core.compiler.source=1.6
-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=16
-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=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=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=false
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=false
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
-org.eclipse.jdt.core.formatter.comment.format_line_comments=false
-org.eclipse.jdt.core.formatter.comment.format_source_code=false
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
-org.eclipse.jdt.core.formatter.comment.line_length=100
-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=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_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=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not 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=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not 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=do not 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.join_lines_in_comments=true
-org.eclipse.jdt.core.formatter.join_wrapped_lines=true
-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=120
-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=4
-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
deleted file mode 100644
index d6d3a9b..0000000
--- a/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,8 +0,0 @@
-#Sun Jan 31 13:16:40 CET 2010
-eclipse.preferences.version=1
-formatter_profile=_JOSM
-formatter_settings_version=11
-org.eclipse.jdt.ui.exception.name=e
-org.eclipse.jdt.ui.gettersetter.use.is=true
-org.eclipse.jdt.ui.keywordthis=false
-org.eclipse.jdt.ui.overrideannotation=true
diff --git a/build.xml b/build.xml
index 3efca1e..234f438 100644
--- a/build.xml
+++ b/build.xml
@@ -1,13 +1,15 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <project default="all" name="Compile and build java classes plus jar archives">
 
-	<target name="all" depends="clean,build,pack,create_run_jar,create_release_zip" />
+	<target name="all" depends="clean,build,svn_info,pack,create_run_jar,create_release_zip,create_source_release_zip" />
 
 	<target name="clean">
+		<mkdir dir="bin" />
 		<delete>
 			<fileset dir="bin">
 				<include name="**" />
 			</fileset>
+			<fileset dir="." includes="*.jar"/>
 		</delete>
 	</target>
 
@@ -22,10 +24,16 @@
 			</fileset>
 		</copy>
 	</target>
-
+	
+    <target name="svn_info" description="Get SVN info for use in JAR/ZIP filenames.">
+        <!-- Get the svn ReleaseVersion property -->
+        <exec executable="svn" outputproperty="svnReleaseVersion">
+            <arg line="propget ReleaseVersion" />
+            <env key="LANG" value="en_US"/>
+        </exec>
+    </target>
+	
 	<target name="pack">
-		<delete file="JMapViewer.jar" />
-		<delete file="JMapViewer_src.jar" />
 		<!-- Create the JAR file containing the compiled class files -->
 		<jar destfile="JMapViewer.jar" filesetmanifest="mergewithoutmain">
 			<fileset dir="bin" includes="**/jmapviewer/**" />
@@ -35,24 +43,36 @@
 			<fileset dir="src" includes="**/jmapviewer/**" />
 		</jar>
 	</target>
-
-	<target name="create_run_jar" description="Create a JAR file that can be used to excute the JMapViewer demo app. Requires JMapViewer.jar to be present.">
-		<delete file="JMapViewer_Demo.jar" />
+	
+	<!-- if you want to build outside of svn, use "ant clean build [pack]" -->
+	
+	<target name="create_run_jar" description="Create a JAR file that can be used to execute the JMapViewer demo app. Requires JMapViewer.jar to be present.">
 		<jar destfile="JMapViewer_Demo.jar" filesetmanifest="mergewithoutmain">
 			<manifest>
 				<attribute name="Main-Class" value="org.openstreetmap.gui.jmapviewer.Demo" />
-				<attribute name="Class-Path" value="JMapViewer.jar" />
+				<attribute name="Class-Path" value="JMapViewer_${svnReleaseVersion}.jar" />
 			</manifest>
 		</jar>
 	</target>
 
 	<target name="create_release_zip" description="Create a release zip file containing the binary and source jar files as well as the demo starter">
-		<delete file="JMapViewer.zip" />
-		<zip basedir="." destfile="JMapViewer.zip">
+		<zip basedir="." destfile="releases/${svnReleaseVersion}/JMapViewer-${svnReleaseVersion}.zip">
 			<include name="JMapViewer*.jar" />
 			<include name="Readme.txt" />
 			<include name="Gpl.txt" />
 		</zip>
+		<delete>
+			<fileset dir="." includes="JMapViewer*.jar"/>
+		</delete> 
+	</target>
+	
+	<target name="create_source_release_zip" description="Create a release zip file containing the source files">
+		<zip destfile="releases/${svnReleaseVersion}/JMapViewer-${svnReleaseVersion}-Source.zip">
+			<zipfileset file="Readme.txt" prefix="jmapviewer-${svnReleaseVersion}"/>
+			<zipfileset file="build.xml" prefix="jmapviewer-${svnReleaseVersion}"/>
+			<zipfileset file="Gpl.txt" prefix="jmapviewer-${svnReleaseVersion}"/>
+			<zipfileset dir="src" includes="**/jmapviewer/**" prefix="jmapviewer-${svnReleaseVersion}/src"/>
+		</zip>
 	</target>
 
 </project>
diff --git a/src/org/openstreetmap/gui/jmapviewer/AbstractLayer.java b/src/org/openstreetmap/gui/jmapviewer/AbstractLayer.java
new file mode 100644
index 0000000..49b41ff
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/AbstractLayer.java
@@ -0,0 +1,87 @@
+package org.openstreetmap.gui.jmapviewer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AbstractLayer {
+    private LayerGroup parent;
+    private String name;
+    private String description;
+    private Style style;
+    private Boolean visible;
+    private Boolean visibleTexts=true;
+    
+    public AbstractLayer(String name){
+        this(name, (String)null);
+    }
+    public AbstractLayer(String name, String description){
+        this(name, description, MapMarkerCircle.getDefaultStyle());
+    }
+    public AbstractLayer(String name, Style style){
+        this(name, null, style);
+    }
+    public AbstractLayer(String name, String description, Style style){
+        this(null, name, description, style);
+    }
+    public AbstractLayer(LayerGroup parent, String name){
+        this(parent, name, MapMarkerCircle.getDefaultStyle());
+    }
+    public AbstractLayer(LayerGroup parent, String name, Style style){
+        this(parent, name, null, style);
+    }
+    public AbstractLayer(LayerGroup parent, String name, String description, Style style){
+        setParent(parent);
+        setName(name);
+        setDescription(description);
+        setStyle(style);
+        setVisible(true);
+
+        if(parent!=null) parent.add(this);
+    }
+    public LayerGroup getParent() {
+        return parent;
+    }
+    public void setParent(LayerGroup parent) {
+        this.parent = parent;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public void setDescription(String description) {
+        this.description = description;
+    }
+    public Style getStyle() {
+        return style;
+    }
+    public void setStyle(Style style) {
+        this.style = style;
+    }
+    public Boolean isVisible() {
+        return visible;
+    }
+    public void setVisible(Boolean visible) {
+        this.visible = visible;
+    }
+    public static <E> List<E> add(List<E> list, E element) {
+        if(element!=null){
+            if(list==null) list = new ArrayList<E>();
+            if(!list.contains(element)) list.add(element);
+        }
+        return list;
+    }
+    public Boolean isVisibleTexts() {
+        return visibleTexts;
+    }
+    public void setVisibleTexts(Boolean visibleTexts) {
+        this.visibleTexts = visibleTexts;
+    }
+    public String toString(){
+        return name;
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java b/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java
index 42aa1d5..62d01e7 100644
--- a/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java
+++ b/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java
@@ -1,153 +1,164 @@
-package org.openstreetmap.gui.jmapviewer;
-
-//License: GPL.
-
-import static org.openstreetmap.gui.jmapviewer.FeatureAdapter.tr;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.font.TextAttribute;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ImageObserver;
-import java.util.HashMap;
-
-import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
-
-public class AttributionSupport {
-
-    private Attributed source;
-
-    private Image attrImage;
-    private String attrTermsText;
-    private String attrTermsUrl;
-    public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
-    public static final Font ATTR_LINK_FONT;
-    
-    protected Rectangle attrTextBounds = null;
-    protected Rectangle attrToUBounds = null;
-    protected Rectangle attrImageBounds = null;
-
-    static {
-        HashMap<TextAttribute, Integer> aUnderline = new HashMap<TextAttribute, Integer>();
-        aUnderline.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
-        ATTR_LINK_FONT = ATTR_FONT.deriveFont(aUnderline);
-    }
-
-    public void initialize(Attributed source) {
-        this.source = source;
-        boolean requireAttr = source.requiresAttribution();
-        if (requireAttr) {
-            attrImage = source.getAttributionImage();
-            attrTermsText = source.getTermsOfUseText();
-            attrTermsUrl = source.getTermsOfUseURL();
-            if (attrTermsUrl != null && attrTermsText == null) {
-                attrTermsText = tr("Background Terms of Use");
-            }
-        } else {
-            attrImage = null;
-            attrTermsUrl = null;
-        }
-    }
-
-    public void paintAttribution(Graphics g, int width, int height, Coordinate topLeft, Coordinate bottomRight, int zoom, ImageObserver observer) {
-        if (source == null || !source.requiresAttribution())
-            return;
-        // Draw attribution
-        Font font = g.getFont();
-        g.setFont(ATTR_LINK_FONT);
-
-        // Draw terms of use text
-        int termsTextHeight = 0;
-        int termsTextY = height;
-
-        if (attrTermsText != null) {
-            Rectangle2D termsStringBounds = g.getFontMetrics().getStringBounds(attrTermsText, g);
-            int textRealHeight = (int) termsStringBounds.getHeight();
-            termsTextHeight = textRealHeight - 5;
-            int termsTextWidth = (int) termsStringBounds.getWidth();
-            termsTextY = height - termsTextHeight;
-            int x = 2;
-            int y = height - termsTextHeight;
-            attrToUBounds = new Rectangle(x, y-termsTextHeight, termsTextWidth, textRealHeight);
-            g.setColor(Color.black);
-            g.drawString(attrTermsText, x + 1, y + 1);
-            g.setColor(Color.white);
-            g.drawString(attrTermsText, x, y);
-        }
-
-        // Draw attribution logo
-        if (attrImage != null) {
-            int x = 2;
-            int imgWidth = attrImage.getWidth(observer);
-            int imgHeight = attrImage.getHeight(observer);
-            int y = termsTextY - imgHeight - termsTextHeight - 5;
-            attrImageBounds = new Rectangle(x, y, imgWidth, imgHeight);
-            g.drawImage(attrImage, x, y, null);
-        }
-
-        g.setFont(ATTR_FONT);
-        String attributionText = source.getAttributionText(zoom, topLeft, bottomRight);
-        if (attributionText != null) {
-            Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
-            int textHeight = (int) stringBounds.getHeight() - 5;
-            int x = width - (int) stringBounds.getWidth();
-            int y = height - textHeight;
-            g.setColor(Color.black);
-            g.drawString(attributionText, x + 1, y + 1);
-            g.setColor(Color.white);
-            g.drawString(attributionText, x, y);
-            attrTextBounds = new Rectangle(x, y-textHeight, (int) stringBounds.getWidth(), (int) stringBounds.getHeight());
-        }
-
-        g.setFont(font);
-    }
-
-    public boolean handleAttributionCursor(Point p) {
-        if (attrTextBounds != null && attrTextBounds.contains(p)) {
-            return true;
-        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
-            return true;
-        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
-            return true;
-        }
-        return false;
-    }
-    
-    public boolean handleAttribution(Point p, boolean click) {
-        if (source == null || !source.requiresAttribution())
-            return false;
-
-        if (attrTextBounds != null && attrTextBounds.contains(p)) {
-            String attributionURL = source.getAttributionLinkURL();
-            if (attributionURL != null) {
-                if (click) {
-                    FeatureAdapter.openLink(attributionURL);
-                }
-                return true;
-            }
-        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
-            String attributionImageURL = source.getAttributionImageURL();
-            if (attributionImageURL != null) {
-                if (click) {
-                    FeatureAdapter.openLink(source.getAttributionImageURL());
-                }
-                return true;
-            }
-        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
-            String termsOfUseURL = source.getTermsOfUseURL();
-            if (termsOfUseURL != null) {
-                if (click) {
-                    FeatureAdapter.openLink(termsOfUseURL);
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
-
+package org.openstreetmap.gui.jmapviewer;
+
+//License: GPL.
+
+import static org.openstreetmap.gui.jmapviewer.FeatureAdapter.tr;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ImageObserver;
+import java.util.HashMap;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
+
+public class AttributionSupport {
+
+    private Attributed source;
+
+    private Image attrImage;
+    private String attrTermsText;
+    private String attrTermsUrl;
+    public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
+    public static final Font ATTR_LINK_FONT;
+
+    protected Rectangle attrTextBounds = null;
+    protected Rectangle attrToUBounds = null;
+    protected Rectangle attrImageBounds = null;
+
+    static {
+        HashMap<TextAttribute, Integer> aUnderline = new HashMap<TextAttribute, Integer>();
+        aUnderline.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
+        ATTR_LINK_FONT = ATTR_FONT.deriveFont(aUnderline);
+    }
+
+    public void initialize(Attributed source) {
+        this.source = source;
+        boolean requireAttr = source.requiresAttribution();
+        if (requireAttr) {
+            attrImage = source.getAttributionImage();
+            attrTermsText = source.getTermsOfUseText();
+            attrTermsUrl = source.getTermsOfUseURL();
+            if (attrTermsUrl != null && attrTermsText == null) {
+                attrTermsText = tr("Background Terms of Use");
+            }
+        } else {
+            attrImage = null;
+            attrTermsUrl = null;
+        }
+    }
+
+    public void paintAttribution(Graphics g, int width, int height, Coordinate topLeft, Coordinate bottomRight, int zoom, ImageObserver observer) {
+        if (source == null || !source.requiresAttribution()) {
+            attrToUBounds = null;
+            attrImageBounds = null;
+            attrTextBounds = null;
+            return;
+        }
+
+        // Draw attribution
+        Font font = g.getFont();
+        g.setFont(ATTR_LINK_FONT);
+
+        // Draw terms of use text
+        int termsTextHeight = 0;
+        int termsTextY = height;
+
+        if (attrTermsText != null) {
+            Rectangle2D termsStringBounds = g.getFontMetrics().getStringBounds(attrTermsText, g);
+            int textRealHeight = (int) termsStringBounds.getHeight();
+            termsTextHeight = textRealHeight - 5;
+            int termsTextWidth = (int) termsStringBounds.getWidth();
+            termsTextY = height - termsTextHeight;
+            int x = 2;
+            int y = height - termsTextHeight;
+            attrToUBounds = new Rectangle(x, y-termsTextHeight, termsTextWidth, textRealHeight);
+            g.setColor(Color.black);
+            g.drawString(attrTermsText, x + 1, y + 1);
+            g.setColor(Color.white);
+            g.drawString(attrTermsText, x, y);
+        } else {
+            attrToUBounds = null;
+        }
+
+        // Draw attribution logo
+        if (attrImage != null) {
+            int x = 2;
+            int imgWidth = attrImage.getWidth(observer);
+            int imgHeight = attrImage.getHeight(observer);
+            int y = termsTextY - imgHeight - termsTextHeight - 5;
+            attrImageBounds = new Rectangle(x, y, imgWidth, imgHeight);
+            g.drawImage(attrImage, x, y, null);
+        } else {
+            attrImageBounds = null;
+        }
+
+        g.setFont(ATTR_FONT);
+        String attributionText = source.getAttributionText(zoom, topLeft, bottomRight);
+        if (attributionText != null) {
+            Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
+            int textHeight = (int) stringBounds.getHeight() - 5;
+            int x = width - (int) stringBounds.getWidth();
+            int y = height - textHeight;
+            g.setColor(Color.black);
+            g.drawString(attributionText, x + 1, y + 1);
+            g.setColor(Color.white);
+            g.drawString(attributionText, x, y);
+            attrTextBounds = new Rectangle(x, y-textHeight, (int) stringBounds.getWidth(), (int) stringBounds.getHeight());
+        } else {
+            attrTextBounds = null;
+        }
+
+        g.setFont(font);
+    }
+
+    public boolean handleAttributionCursor(Point p) {
+        if (attrTextBounds != null && attrTextBounds.contains(p)) {
+            return true;
+        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
+            return true;
+        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean handleAttribution(Point p, boolean click) {
+        if (source == null || !source.requiresAttribution())
+            return false;
+
+        if (attrTextBounds != null && attrTextBounds.contains(p)) {
+            String attributionURL = source.getAttributionLinkURL();
+            if (attributionURL != null) {
+                if (click) {
+                    FeatureAdapter.openLink(attributionURL);
+                }
+                return true;
+            }
+        } else if (attrImageBounds != null && attrImageBounds.contains(p)) {
+            String attributionImageURL = source.getAttributionImageURL();
+            if (attributionImageURL != null) {
+                if (click) {
+                    FeatureAdapter.openLink(source.getAttributionImageURL());
+                }
+                return true;
+            }
+        } else if (attrToUBounds != null && attrToUBounds.contains(p)) {
+            String termsOfUseURL = source.getTermsOfUseURL();
+            if (termsOfUseURL != null) {
+                if (click) {
+                    FeatureAdapter.openLink(termsOfUseURL);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
+
diff --git a/src/org/openstreetmap/gui/jmapviewer/Coordinate.java b/src/org/openstreetmap/gui/jmapviewer/Coordinate.java
index 47b20cf..f98338b 100644
--- a/src/org/openstreetmap/gui/jmapviewer/Coordinate.java
+++ b/src/org/openstreetmap/gui/jmapviewer/Coordinate.java
@@ -8,6 +8,8 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 
+import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
+
 /**
  * This class encapsulates a Point2D.Double and provide access
  * via <tt>lat</tt> and <tt>lon</tt>.
@@ -15,7 +17,7 @@ import java.io.Serializable;
  * @author Jan Peter Stotz
  *
  */
-public class Coordinate implements Serializable {
+public class Coordinate implements Serializable, ICoordinate {
     private transient Point2D.Double data;
 
     public Coordinate(double lat, double lon) {
diff --git a/src/org/openstreetmap/gui/jmapviewer/Demo.java b/src/org/openstreetmap/gui/jmapviewer/Demo.java
index cb6da22..68c466b 100644
--- a/src/org/openstreetmap/gui/jmapviewer/Demo.java
+++ b/src/org/openstreetmap/gui/jmapviewer/Demo.java
@@ -4,6 +4,7 @@ package org.openstreetmap.gui.jmapviewer;
 
 import java.awt.BorderLayout;
 import java.awt.Cursor;
+import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
@@ -21,6 +22,7 @@ import javax.swing.JPanel;
 
 import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
 import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener;
+import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 import org.openstreetmap.gui.jmapviewer.tilesources.BingAerialTileSource;
@@ -39,7 +41,7 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
 
     private static final long serialVersionUID = 1L;
 
-    private JMapViewer map = null;
+    private JMapViewerTree treeMap = null;
 
     private JLabel zoomLabel=null;
     private JLabel zoomValue=null;
@@ -47,15 +49,18 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
     private JLabel mperpLabelName=null;
     private JLabel mperpLabelValue = null;
 
+    /**
+     * Constructs the {@code Demo}.
+     */
     public Demo() {
         super("JMapViewer Demo");
         setSize(400, 400);
 
-        map = new JMapViewer();
+        treeMap = new JMapViewerTree("Zones");
 
         // Listen to the map viewer for user operations so components will
         // recieve events and update
-        map.addJMVListener(this);
+        map().addJMVListener(this);
 
         // final JMapViewer map = new JMapViewer(new MemoryTileCache(),4);
         // map.setTileLoader(new OsmFileCacheTileLoader(map));
@@ -70,10 +75,10 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
         JPanel helpPanel = new JPanel();
 
         mperpLabelName=new JLabel("Meters/Pixels: ");
-        mperpLabelValue=new JLabel(String.format("%s",map.getMeterPerPixel()));
+        mperpLabelValue=new JLabel(String.format("%s",map().getMeterPerPixel()));
 
         zoomLabel=new JLabel("Zoom: ");
-        zoomValue=new JLabel(String.format("%s", map.getZoom()));
+        zoomValue=new JLabel(String.format("%s", map().getZoom()));
 
         add(panel, BorderLayout.NORTH);
         add(helpPanel, BorderLayout.SOUTH);
@@ -87,62 +92,76 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
         button.addActionListener(new ActionListener() {
 
             public void actionPerformed(ActionEvent e) {
-                map.setDisplayToFitMapMarkers();
+                map().setDisplayToFitMapMarkers();
             }
         });
         JComboBox tileSourceSelector = new JComboBox(new TileSource[] { new OsmTileSource.Mapnik(),
                 new OsmTileSource.CycleMap(), new BingAerialTileSource(), new MapQuestOsmTileSource(), new MapQuestOpenAerialTileSource() });
         tileSourceSelector.addItemListener(new ItemListener() {
             public void itemStateChanged(ItemEvent e) {
-                map.setTileSource((TileSource) e.getItem());
+                map().setTileSource((TileSource) e.getItem());
             }
         });
         JComboBox tileLoaderSelector;
         try {
-            tileLoaderSelector = new JComboBox(new TileLoader[] { new OsmFileCacheTileLoader(map),
-                    new OsmTileLoader(map) });
+            tileLoaderSelector = new JComboBox(new TileLoader[] { new OsmFileCacheTileLoader(map()),
+                    new OsmTileLoader(map()) });
         } catch (IOException e) {
-            tileLoaderSelector = new JComboBox(new TileLoader[] { new OsmTileLoader(map) });
+            tileLoaderSelector = new JComboBox(new TileLoader[] { new OsmTileLoader(map()) });
         }
         tileLoaderSelector.addItemListener(new ItemListener() {
             public void itemStateChanged(ItemEvent e) {
-                map.setTileLoader((TileLoader) e.getItem());
+                map().setTileLoader((TileLoader) e.getItem());
             }
         });
-        map.setTileLoader((TileLoader) tileLoaderSelector.getSelectedItem());
+        map().setTileLoader((TileLoader) tileLoaderSelector.getSelectedItem());
         panelTop.add(tileSourceSelector);
         panelTop.add(tileLoaderSelector);
         final JCheckBox showMapMarker = new JCheckBox("Map markers visible");
-        showMapMarker.setSelected(map.getMapMarkersVisible());
+        showMapMarker.setSelected(map().getMapMarkersVisible());
         showMapMarker.addActionListener(new ActionListener() {
-
             public void actionPerformed(ActionEvent e) {
-                map.setMapMarkerVisible(showMapMarker.isSelected());
+                map().setMapMarkerVisible(showMapMarker.isSelected());
             }
         });
         panelBottom.add(showMapMarker);
+        ///
+        final JCheckBox showTreeLayers = new JCheckBox("Tree Layers visible");
+        showTreeLayers.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                treeMap.setTreeVisible(showTreeLayers.isSelected());
+            }
+        });
+        panelBottom.add(showTreeLayers);
+        ///
+        final JCheckBox showToolTip = new JCheckBox("ToolTip visible");
+        showToolTip.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                map().setToolTipText(null);
+            }
+        });
+        panelBottom.add(showToolTip);
+        ///
         final JCheckBox showTileGrid = new JCheckBox("Tile grid visible");
-        showTileGrid.setSelected(map.isTileGridVisible());
+        showTileGrid.setSelected(map().isTileGridVisible());
         showTileGrid.addActionListener(new ActionListener() {
-
             public void actionPerformed(ActionEvent e) {
-                map.setTileGridVisible(showTileGrid.isSelected());
+                map().setTileGridVisible(showTileGrid.isSelected());
             }
         });
         panelBottom.add(showTileGrid);
         final JCheckBox showZoomControls = new JCheckBox("Show zoom controls");
-        showZoomControls.setSelected(map.getZoomContolsVisible());
+        showZoomControls.setSelected(map().getZoomContolsVisible());
         showZoomControls.addActionListener(new ActionListener() {
-
             public void actionPerformed(ActionEvent e) {
-                map.setZoomContolsVisible(showZoomControls.isSelected());
+                map().setZoomContolsVisible(showZoomControls.isSelected());
             }
         });
         panelBottom.add(showZoomControls);
         final JCheckBox scrollWrapEnabled = new JCheckBox("Scrollwrap enabled");
         scrollWrapEnabled.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
-                map.setScrollWrapEnabled(scrollWrapEnabled.isSelected());
+                map().setScrollWrapEnabled(scrollWrapEnabled.isSelected());
             }
         });
         panelBottom.add(scrollWrapEnabled);
@@ -153,39 +172,72 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
         panelTop.add(mperpLabelName);
         panelTop.add(mperpLabelValue);
 
-        add(map, BorderLayout.CENTER);
+        add(treeMap, BorderLayout.CENTER);
 
         //
-        map.addMapMarker(new MapMarkerDot(49.814284999, 8.642065999));
-        map.addMapMarker(new MapMarkerDot(49.91, 8.24));
-        map.addMapMarker(new MapMarkerDot(49.71, 8.64));
-        map.addMapMarker(new MapMarkerDot(48.71, -1));
-        map.addMapMarker(new MapMarkerDot(49.8588, 8.643));
+        LayerGroup germanyGroup = new LayerGroup("Germany");
+        Layer germanyWestLayer = germanyGroup.addLayer("Germany West");
+        Layer germanyEastLayer = germanyGroup.addLayer("Germany East");
+        MapMarkerDot eberstadt = new MapMarkerDot(germanyEastLayer, "Eberstadt", 49.814284999, 8.642065999);
+        MapMarkerDot ebersheim = new MapMarkerDot(germanyWestLayer, "Ebersheim", 49.91, 8.24);
+        MapMarkerDot empty = new MapMarkerDot(germanyEastLayer, 49.71, 8.64);
+        MapMarkerDot darmstadt = new MapMarkerDot(germanyEastLayer, "Darmstadt", 49.8588, 8.643);
+        map().addMapMarker(eberstadt);
+        map().addMapMarker(ebersheim);
+        map().addMapMarker(empty);
+        Layer franceLayer = treeMap.addLayer("France");
+        map().addMapMarker(new MapMarkerDot(franceLayer, "La Gallerie", 48.71, -1));
+        map().addMapMarker(new MapMarkerDot(43.604, 1.444));
+        map().addMapMarker(new MapMarkerCircle(53.343, -6.267, 0.666));
+        map().addMapRectangle(new MapRectangleImpl(new Coordinate(53.343, -6.267), new Coordinate(43.604, 1.444)));
+        map().addMapMarker(darmstadt);
+        treeMap.addLayer(germanyWestLayer);
+        treeMap.addLayer(germanyEastLayer);
+
+        MapPolygon bermudas = new MapPolygonImpl(c(49,1), c(45,10), c(40,5));
+        map().addMapPolygon( bermudas );
+        map().addMapPolygon( new MapPolygonImpl(germanyEastLayer, "Riedstadt", ebersheim, darmstadt, eberstadt, empty));
+
+        map().addMapMarker(new MapMarkerCircle(germanyWestLayer, "North of Suisse", new Coordinate(48, 7), .5));
+        Layer spain = treeMap.addLayer("Spain");
+        map().addMapMarker(new MapMarkerCircle(spain, "La Garena", new Coordinate(40.4838, -3.39), .002));
+        spain.setVisible(false);
+
+        Layer wales = treeMap.addLayer("UK");
+        map().addMapRectangle(new MapRectangleImpl(wales, "Wales", c(53.35,-4.57), c(51.64,-2.63)));
 
         // map.setDisplayPositionByLatLon(49.807, 8.6, 11);
         // map.setTileGridVisible(true);
-        
-        map.addMouseListener(new MouseAdapter() {
+
+        map().addMouseListener(new MouseAdapter() {
             @Override
             public void mouseClicked(MouseEvent e) {
                 if (e.getButton() == MouseEvent.BUTTON1) {
-                    map.getAttribution().handleAttribution(e.getPoint(), true);
+                    map().getAttribution().handleAttribution(e.getPoint(), true);
                 }
             }
         });
-        
-        map.addMouseMotionListener(new MouseAdapter() {
+
+        map().addMouseMotionListener(new MouseAdapter() {
             @Override
             public void mouseMoved(MouseEvent e) {
-                boolean cursorHand = map.getAttribution().handleAttributionCursor(e.getPoint());
+                Point p = e.getPoint();
+                boolean cursorHand = map().getAttribution().handleAttributionCursor(p);
                 if (cursorHand) {
-                    map.setCursor(new Cursor(Cursor.HAND_CURSOR));
+                    map().setCursor(new Cursor(Cursor.HAND_CURSOR));
                 } else {
-                    map.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+                    map().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                 }
+                if(showToolTip.isSelected()) map().setToolTipText(map().getPosition(p).toString());
             }
         });
     }
+    private JMapViewer map(){
+        return treeMap.getViewer();
+    }
+    private static Coordinate c(double lat, double lon){
+        return new Coordinate(lat, lon);
+    }
 
     /**
      * @param args
@@ -199,9 +251,9 @@ public class Demo extends JFrame implements JMapViewerEventListener  {
 
     private void updateZoomParameters() {
         if (mperpLabelValue!=null)
-            mperpLabelValue.setText(String.format("%s",map.getMeterPerPixel()));
+            mperpLabelValue.setText(String.format("%s",map().getMeterPerPixel()));
         if (zoomValue!=null)
-            zoomValue.setText(String.format("%s", map.getZoom()));
+            zoomValue.setText(String.format("%s", map().getZoom()));
     }
 
     @Override
diff --git a/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java b/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
index e7f0887..83e6d37 100644
--- a/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
+++ b/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
@@ -1,64 +1,64 @@
-package org.openstreetmap.gui.jmapviewer;
-
-//License: GPL.
-
-import java.awt.Desktop;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.MessageFormat;
-
-public class FeatureAdapter {
-
-    public static interface BrowserAdapter {
-        void openLink(String url);
-    }
-
-    public static interface TranslationAdapter {
-        String tr(String text, Object... objects);
-        // TODO: more i18n functions
-    }
-
-    private static BrowserAdapter browserAdapter = new DefaultBrowserAdapter();
-    private static TranslationAdapter translationAdapter = new DefaultTranslationAdapter();
-
-    public static void registerBrowserAdapter(BrowserAdapter browserAdapter) {
-        FeatureAdapter.browserAdapter = browserAdapter;
-    }
-
-    public static void registerTranslationAdapter(TranslationAdapter translationAdapter) {
-        FeatureAdapter.translationAdapter = translationAdapter;
-    }
-
-    public static void openLink(String url) {
-        browserAdapter.openLink(url);
-    }
-
-    public static String tr(String text, Object... objects) {
-        return translationAdapter.tr(text, objects);
-    }
-
-    public static class DefaultBrowserAdapter implements BrowserAdapter {
-        @Override
-        public void openLink(String url) {
-            if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
-                try {
-                    Desktop.getDesktop().browse(new URI(url));
-                } catch (IOException e) {
-                    e.printStackTrace();
-                } catch (URISyntaxException e) {
-                    e.printStackTrace();
-                }
-            } else {
-                System.err.println(tr("Opening link not supported on current platform (''{0}'')", url));
-            }
-        }
-    }
-
-    public static class DefaultTranslationAdapter implements TranslationAdapter {
-        @Override
-        public String tr(String text, Object... objects) {
-            return MessageFormat.format(text, objects);
-        }
-    }
-}
+package org.openstreetmap.gui.jmapviewer;
+
+//License: GPL.
+
+import java.awt.Desktop;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.MessageFormat;
+
+public class FeatureAdapter {
+
+    public static interface BrowserAdapter {
+        void openLink(String url);
+    }
+
+    public static interface TranslationAdapter {
+        String tr(String text, Object... objects);
+        // TODO: more i18n functions
+    }
+
+    private static BrowserAdapter browserAdapter = new DefaultBrowserAdapter();
+    private static TranslationAdapter translationAdapter = new DefaultTranslationAdapter();
+
+    public static void registerBrowserAdapter(BrowserAdapter browserAdapter) {
+        FeatureAdapter.browserAdapter = browserAdapter;
+    }
+
+    public static void registerTranslationAdapter(TranslationAdapter translationAdapter) {
+        FeatureAdapter.translationAdapter = translationAdapter;
+    }
+
+    public static void openLink(String url) {
+        browserAdapter.openLink(url);
+    }
+
+    public static String tr(String text, Object... objects) {
+        return translationAdapter.tr(text, objects);
+    }
+
+    public static class DefaultBrowserAdapter implements BrowserAdapter {
+        @Override
+        public void openLink(String url) {
+            if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
+                try {
+                    Desktop.getDesktop().browse(new URI(url));
+                } catch (IOException e) {
+                    e.printStackTrace();
+                } catch (URISyntaxException e) {
+                    e.printStackTrace();
+                }
+            } else {
+                System.err.println(tr("Opening link not supported on current platform (''{0}'')", url));
+            }
+        }
+    }
+
+    public static class DefaultTranslationAdapter implements TranslationAdapter {
+        @Override
+        public String tr(String text, Object... objects) {
+            return MessageFormat.format(text, objects);
+        }
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java b/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
index 40d0307..dcce880 100644
--- a/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
+++ b/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
@@ -23,6 +23,7 @@ import javax.swing.event.EventListenerList;
 
 import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
 import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent.COMMAND;
+import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
 import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener;
 import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
 import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
@@ -80,7 +81,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     protected JSlider zoomSlider;
     protected JButton zoomInButton;
     protected JButton zoomOutButton;
-        
+
     public static enum ZOOM_BUTTON_STYLE {
         HORIZONTAL,
         VERTICAL
@@ -268,33 +269,39 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
 
         if (markers) {
             for (MapMarker marker : mapMarkerList) {
-                int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
-                int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
-                x_max = Math.max(x_max, x);
-                y_max = Math.max(y_max, y);
-                x_min = Math.min(x_min, x);
-                y_min = Math.min(y_min, y);
+                if(marker.isVisible()){
+                    int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
+                    int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
+                    x_max = Math.max(x_max, x);
+                    y_max = Math.max(y_max, y);
+                    x_min = Math.min(x_min, x);
+                    y_min = Math.min(y_min, y);
+                }
             }
         }
 
         if (rectangles) {
             for (MapRectangle rectangle : mapRectangleList) {
-                x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
-                y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
-                x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
-                y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
+                if(rectangle.isVisible()){
+                    x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax));
+                    y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax));
+                    x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax));
+                    y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax));
+                }
             }
         }
 
         if (polygons) {
             for (MapPolygon polygon : mapPolygonList) {
-                for (Coordinate c : polygon.getPoints()) {
-                    int x = OsmMercator.LonToX(c.getLon(), mapZoomMax);
-                    int y = OsmMercator.LatToY(c.getLat(), mapZoomMax);
-                    x_max = Math.max(x_max, x);
-                    y_max = Math.max(y_max, y);
-                    x_min = Math.min(x_min, x);
-                    y_min = Math.min(y_min, y);
+                if(polygon.isVisible()){
+                    for (ICoordinate c : polygon.getPoints()) {
+                        int x = OsmMercator.LonToX(c.getLon(), mapZoomMax);
+                        int y = OsmMercator.LatToY(c.getLat(), mapZoomMax);
+                        x_max = Math.max(x_max, x);
+                        y_max = Math.max(y_max, y);
+                        x_min = Math.min(x_min, x);
+                        y_min = Math.min(y_min, y);
+                    }
                 }
             }
         }
@@ -421,6 +428,24 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     /**
      * Calculates the position on the map of a given coordinate
      *
+     * @param lat Latitude
+     * @param offset Offset respect Latitude
+     * @param checkOutside
+     * @return Integer the radius in pixels
+     */
+    public Integer getLatOffset(double lat, double offset, boolean checkOutside) {
+        int y = OsmMercator.LatToY(lat+offset, zoom);
+        y -= center.y - getHeight() / 2;
+        if (checkOutside) {
+            if (y < 0 || y > getHeight())
+                return null;
+        }
+        return y;
+    }
+
+    /**
+     * Calculates the position on the map of a given coordinate
+     *
      * @param lat
      * @param lon
      * @return point on the map or <code>null</code> if the point is not visible
@@ -432,6 +457,22 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     /**
      * Calculates the position on the map of a given coordinate
      *
+     * @param marker MapMarker object that define the x,y coordinate
+     * @return Integer the radius in pixels
+     */
+    public Integer getRadius(MapMarker marker, Point p) {
+        if(marker.getMarkerStyle() == MapMarker.STYLE.FIXED)
+            return (int)marker.getRadius();
+        else if(p!=null){
+            Integer radius = getLatOffset(marker.getLat(), marker.getRadius(), false);
+            radius = radius==null?null:p.y-radius.intValue();
+            return radius;
+        }else return null;
+    }
+
+    /**
+     * Calculates the position on the map of a given coordinate
+     *
      * @param coord
      * @return point on the map or <code>null</code> if the point is not visible
      */
@@ -449,7 +490,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * @return point on the map or <code>null</code> if the point is not visible
      *         and checkOutside set to <code>true</code>
      */
-    public Point getMapPosition(Coordinate coord, boolean checkOutside) {
+    public Point getMapPosition(ICoordinate coord, boolean checkOutside) {
         if (coord != null)
             return getMapPosition(coord.getLat(), coord.getLon(), checkOutside);
         else
@@ -519,7 +560,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         int y_min = -tilesize;
         int x_max = getWidth();
         int y_max = getHeight();
-        
+
         // calculate the length of the grid (number of squares per edge)
         int gridLength = 1 << zoom;
 
@@ -575,22 +616,22 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         if (scrollWrapEnabled) {
             center.x = center.x % mapSize;
         }
-        
+
         if (mapPolygonsVisible && mapPolygonList != null) {
             for (MapPolygon polygon : mapPolygonList) {
-                paintPolygon(g, polygon);
+                if(polygon.isVisible()) paintPolygon(g, polygon);
             }
         }
 
         if (mapRectanglesVisible && mapRectangleList != null) {
             for (MapRectangle rectangle : mapRectangleList) {
-                paintRectangle(g, rectangle);
+                if(rectangle.isVisible()) paintRectangle(g, rectangle);
             }
         }
 
         if (mapMarkersVisible && mapMarkerList != null) {
             for (MapMarker marker : mapMarkerList) {
-                paintMarker(g, marker);
+                if(marker.isVisible())paintMarker(g, marker);
             }
         }
 
@@ -601,29 +642,31 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * Paint a single marker.
      */
     protected void paintMarker(Graphics g, MapMarker marker) {
-        Point p = getMapPosition(marker.getLat(), marker.getLon());
+        Point p = getMapPosition(marker.getLat(), marker.getLon(), marker.getMarkerStyle()==MapMarker.STYLE.FIXED);
+        Integer radius = getRadius(marker, p);
         if (scrollWrapEnabled) {
             int tilesize = tileSource.getTileSize();
             int mapSize = tilesize << zoom;
             if (p == null) {
                 p = getMapPosition(marker.getLat(), marker.getLon(), false);
+                radius = getRadius(marker, p);
             }
-            marker.paint(g, p);
+            marker.paint(g, p, radius);
             int xSave = p.x;
             int xWrap = xSave;
             // overscan of 15 allows up to 30-pixel markers to gracefully scroll off the edge of the panel
             while ((xWrap -= mapSize) >= -15) {
                 p.x = xWrap;
-                marker.paint(g, p);
+                marker.paint(g, p, radius);
             }
             xWrap = xSave;
             while ((xWrap += mapSize) <= getWidth() + 15) {
                 p.x = xWrap;
-                marker.paint(g, p);
+                marker.paint(g, p, radius);
             }
         } else {
             if (p != null) {
-                marker.paint(g, p);
+                marker.paint(g, p, radius);
             }
         }
     }
@@ -660,7 +703,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
                         pBottomRight.x = xBottomRightWrap;
                         rectangle.paint(g, pTopLeft, pBottomRight);
                     }
-                    
+
                 }
             }
         }
@@ -670,10 +713,10 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
      * Paint a single polygon.
      */
     protected void paintPolygon(Graphics g, MapPolygon polygon) {
-        List<Coordinate> coords = polygon.getPoints();
+        List<? extends ICoordinate> coords = polygon.getPoints();
         if (coords != null && coords.size() >= 3) {
             List<Point> points = new LinkedList<Point>();
-            for (Coordinate c : coords) {
+            for (ICoordinate c : coords) {
                 Point p = getMapPosition(c, false);
                 if (p == null) {
                     return;
@@ -966,20 +1009,20 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
         this.mapPolygonsVisible = mapPolygonsVisible;
         repaint();
     }
-    
+
     public boolean isScrollWrapEnabled() {
         return scrollWrapEnabled;
     }
-    
+
     public void setScrollWrapEnabled(boolean scrollWrapEnabled) {
         this.scrollWrapEnabled = scrollWrapEnabled;
         repaint();
     }
-    
+
     public ZOOM_BUTTON_STYLE getZoomButtonStyle() {
         return zoomButtonStyle;
     }
-    
+
     public void setZoomButtonStyle(ZOOM_BUTTON_STYLE style) {
         zoomButtonStyle = style;
         if (zoomSlider == null || zoomInButton == null || zoomOutButton == null) {
@@ -1008,7 +1051,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     public TileController getTileController() {
         return tileController;
     }
-    
+
     /**
      * Return tile information caching class
      * @see TileLoaderListener#getTileCache()
@@ -1044,7 +1087,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener {
     /**
      * Send an update to all objects registered with viewer
      *
-     * @param event to dispatch
+     * @param evt event to dispatch
      */
     void fireJMVEvent(JMVCommandEvent evt) {
         Object[] listeners = listenerList.getListenerList();
diff --git a/src/org/openstreetmap/gui/jmapviewer/JMapViewerTree.java b/src/org/openstreetmap/gui/jmapviewer/JMapViewerTree.java
new file mode 100644
index 0000000..38eeb57
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/JMapViewerTree.java
@@ -0,0 +1,176 @@
+package org.openstreetmap.gui.jmapviewer;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.List;
+
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JSplitPane;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+
+import org.openstreetmap.gui.jmapviewer.checkBoxTree.CheckBoxNodePanel;
+import org.openstreetmap.gui.jmapviewer.checkBoxTree.CheckBoxTree;
+import org.openstreetmap.gui.jmapviewer.interfaces.MapObject;
+
+/**
+ * Tree of layers for JMapViewer component
+ * @author galo
+ */
+public class JMapViewerTree extends JPanel{
+    /** Serial Version UID */
+    private static final long serialVersionUID = 3050203054402323972L;
+
+    private JMapViewer map;
+    private CheckBoxTree tree;
+    private JPanel treePanel;
+    private JSplitPane splitPane;
+
+    public JMapViewerTree(String name){
+        this(name, false);
+    }
+    public JMapViewerTree(String name, boolean treeVisible){
+        super();
+        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+        
+        tree = new CheckBoxTree(name);
+        treePanel = new JPanel();
+        treePanel.setLayout(new BorderLayout());
+        treePanel.add(tree, BorderLayout.CENTER);
+        treePanel.add(new JLabel("<html><center>Use right mouse button to<br />show/hide texts</center></html>"), BorderLayout.SOUTH);
+        map = new JMapViewer();
+
+        splitPane.setOneTouchExpandable(true);
+        splitPane.setDividerLocation(150);
+        
+        //Provide minimum sizes for the two components in the split pane
+        Dimension minimumSize = new Dimension(100, 50);
+        //tree.setMinimumSize(minimumSize);
+        map.setMinimumSize(minimumSize);
+        createRefresh();
+        setLayout(new BorderLayout());
+        setTreeVisible(treeVisible);
+        tree.addNodeListener(new MouseAdapter() {
+            public void mousePressed(MouseEvent e) {
+                maybeShowPopup(e);
+            }
+            public void mouseReleased(MouseEvent e) {
+                maybeShowPopup(e);
+            }
+            private void maybeShowPopup(MouseEvent e) {
+                if (e.isPopupTrigger()) {
+                    e.getSource();
+                    AbstractLayer layer = ((CheckBoxNodePanel)e.getComponent()).getData().getAbstractLayer();
+                    if(layer!=null)
+                        JMapViewerTree.this.createPopupMenu(layer).show(e.getComponent(), e.getX(), e.getY());
+                }
+            }
+        });
+    }
+    private JPopupMenu createPopupMenu(final AbstractLayer layer) {
+        JMenuItem menuItemShow = new JMenuItem("show texts");
+        JMenuItem menuItemHide = new JMenuItem("hide texts");
+ 
+        //Create the popup menu.
+        JPopupMenu popup = new JPopupMenu();
+        
+        // Create items
+        if(layer.isVisibleTexts()==null){
+            popup.add(menuItemShow);
+            popup.add(menuItemHide);
+        }else if(layer.isVisibleTexts()) popup.add(menuItemHide);
+        else popup.add(menuItemShow);
+        
+        menuItemShow.addActionListener(new ActionListener(){
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                setVisibleTexts(layer, true);
+                if(layer.getParent()!=null) layer.getParent().calculateVisibleTexts();
+                map.repaint();
+            }
+        });
+        menuItemHide.addActionListener(new ActionListener(){
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                setVisibleTexts(layer, false);
+                if(layer.getParent()!=null) layer.getParent().calculateVisibleTexts();
+                map.repaint();
+            }
+        });
+ 
+        return popup;
+    }
+    private void setVisibleTexts(AbstractLayer layer, boolean visible){
+        layer.setVisibleTexts(visible);
+        if(layer instanceof LayerGroup){
+            LayerGroup group = (LayerGroup)layer;
+            if(group.getLayers()!=null) for(AbstractLayer al: group.getLayers()) setVisibleTexts(al, visible);
+        }
+    }
+    public Layer addLayer(String name){
+        Layer layer = new Layer(name);
+        this.addLayer(layer);
+        return layer;
+    }
+    public JMapViewerTree addLayer(Layer layer){
+        tree.addLayer(layer);
+        return this;
+    }
+    public JMapViewerTree addLayer(MapObject element){
+        //element.getLayer().add(element);
+        return addLayer(element.getLayer());
+    }
+    public Layer removeFromLayer(MapObject element){
+        element.getLayer().getElements().remove(element);
+        return element.getLayer();
+    }
+    public static int size(List<?> list){
+        return list==null?0:list.size();
+    }
+    public JMapViewer getViewer(){
+        return map;
+    }
+    public CheckBoxTree getTree(){
+        return tree;
+    }
+    public void addMapObject(MapObject o){
+        
+    }
+    public void setTreeVisible(boolean visible){
+        removeAll();
+        revalidate();
+        if(visible){
+            splitPane.setLeftComponent(treePanel);
+            splitPane.setRightComponent(map);
+            add(splitPane, BorderLayout.CENTER);
+        }else add(map, BorderLayout.CENTER);
+        repaint();
+    }
+    private void createRefresh(){
+        tree.getModel().addTreeModelListener(new TreeModelListener() {
+            @Override
+            public void treeNodesChanged(final TreeModelEvent e) {
+                repaint();
+            }
+            @Override
+            public void treeNodesInserted(TreeModelEvent arg0) {
+                // TODO Auto-generated method stub
+            }
+            @Override
+            public void treeNodesRemoved(TreeModelEvent arg0) {
+                // TODO Auto-generated method stub
+            }
+            @Override
+            public void treeStructureChanged(TreeModelEvent arg0) {
+                // TODO Auto-generated method stub
+            }
+        });
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/Layer.java b/src/org/openstreetmap/gui/jmapviewer/Layer.java
new file mode 100644
index 0000000..18aff1f
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/Layer.java
@@ -0,0 +1,42 @@
+package org.openstreetmap.gui.jmapviewer;
+
+import java.util.List;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.MapObject;
+
+public class Layer extends AbstractLayer{
+    private List<MapObject> elements;
+    
+    public Layer(String name){
+        super(name);
+    }
+    public Layer(String name, String description){
+        super(name, description);
+    }
+    public Layer(String name, Style style){
+        super(name, style);
+    }
+    public Layer(String name, String description, Style style){
+        super(name, description, style);
+    }
+    public Layer(LayerGroup parent, String name){
+        super(parent, name);
+    }
+    public Layer(LayerGroup parent, String name, Style style){
+        super(parent, name, style);
+    }
+    public Layer(LayerGroup parent, String name, String description, Style style){
+        super(parent, name, description, style);
+    }
+    public List<MapObject> getElements() {
+        return elements;
+    }
+    public void setElements(List<MapObject> elements) {
+        this.elements = elements;
+    }
+    public Layer add(MapObject element) {
+        element.setLayer(this);
+        elements = add(elements, element);
+        return this;
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/LayerGroup.java b/src/org/openstreetmap/gui/jmapviewer/LayerGroup.java
new file mode 100644
index 0000000..04cffb3
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/LayerGroup.java
@@ -0,0 +1,58 @@
+package org.openstreetmap.gui.jmapviewer;
+
+import java.util.List;
+
+public class LayerGroup extends AbstractLayer{
+    private List<AbstractLayer> layers;
+    
+    public LayerGroup(String name){
+        super(name);
+    }
+    public LayerGroup(String name, String description){
+        super(name, description);
+    }
+    public LayerGroup(String name, Style style){
+        super(name, style);
+    }
+    public LayerGroup(String name, String description, Style style){
+        super(name, description, style);
+    }
+    public LayerGroup(LayerGroup parent, String name){
+        super(parent, name);
+    }
+    public LayerGroup(LayerGroup parent, String name, String description, Style style){
+        super(name, description, style);
+    }
+    public List<AbstractLayer> getLayers() {
+        return layers;
+    }
+    public void setElements(List<AbstractLayer> layers) {
+        this.layers = layers;
+    }
+    public Layer addLayer(String name) {
+        Layer layer = new Layer(this, name);
+        layers = add(layers, layer);
+        return layer;
+    }
+    public LayerGroup add(AbstractLayer layer) {
+        layer.setParent(this);
+        layers = add(layers, layer);
+        return this;
+    }
+    public void calculateVisibleTexts(){
+        Boolean calculate=null;
+        if(layers!=null&&layers.size()>0){
+            calculate=layers.get(0).isVisibleTexts();
+            for(int i=1;i<layers.size(); i++){
+                calculate = resultOf(calculate, layers.get(i).isVisibleTexts());
+            }
+        }
+        setVisibleTexts(calculate);
+        if(getParent()!=null) getParent().calculateVisibleTexts();
+    }
+    public Boolean resultOf(Boolean b1, Boolean b2){
+        if(b1==null||b2==null) return null;
+        else if(b1.booleanValue() == b2.booleanValue()) return b1.booleanValue();
+        else return null;
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/MapMarkerCircle.java b/src/org/openstreetmap/gui/jmapviewer/MapMarkerCircle.java
new file mode 100644
index 0000000..d7a2472
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/MapMarkerCircle.java
@@ -0,0 +1,107 @@
+package org.openstreetmap.gui.jmapviewer;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
+
+/**
+ * A simple implementation of the {@link MapMarker} interface. Each map marker
+ * is painted as a circle with a black border line and filled with a specified
+ * color.
+ *
+ * @author Jan Peter Stotz
+ *
+ */
+public class MapMarkerCircle extends MapObjectImpl implements MapMarker {
+
+    Coordinate coord;
+    double radius;
+    STYLE markerStyle;
+
+    public MapMarkerCircle(Coordinate coord, double radius) {
+        this(null, null, coord, radius);
+    }
+    public MapMarkerCircle(String name, Coordinate coord, double radius) {
+        this(null, name, coord, radius);
+    }
+    public MapMarkerCircle(Layer layer, Coordinate coord, double radius) {
+        this(layer, null, coord, radius);
+    }
+    public MapMarkerCircle(double lat, double lon, double radius) {
+        this(null, null, new Coordinate(lat,lon), radius);
+    }
+    public MapMarkerCircle(Layer layer, double lat, double lon, double radius) {
+        this(layer, null, new Coordinate(lat,lon), radius);
+    }
+    public MapMarkerCircle(Layer layer, String name, Coordinate coord, double radius) {
+        this(layer, name, coord, radius, STYLE.VARIABLE, getDefaultStyle());
+    }
+    public MapMarkerCircle(Layer layer, String name, Coordinate coord, double radius, STYLE markerStyle, Style style) {
+        super(layer, name, style);
+        this.markerStyle = markerStyle;
+        this.coord = coord;
+        this.radius = radius;
+    }
+
+    public Coordinate getCoordinate(){
+        return coord;
+    }
+    public double getLat() {
+        return coord.getLat();
+    }
+
+    public double getLon() {
+        return coord.getLon();
+    }
+
+    public double getRadius() {
+        return radius;
+    }
+
+    public STYLE getMarkerStyle() {
+        return markerStyle;
+    }
+
+    public void paint(Graphics g, Point position, int radio) {
+        int size_h = radio;
+        int size = size_h * 2;
+
+        if (g instanceof Graphics2D && getBackColor()!=null) {
+            Graphics2D g2 = (Graphics2D) g;
+            Composite oldComposite = g2.getComposite();
+            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+            g2.setPaint(getBackColor());
+            g.fillOval(position.x - size_h, position.y - size_h, size, size);
+            g2.setComposite(oldComposite);
+        }
+        g.setColor(getColor());
+        g.drawOval(position.x - size_h, position.y - size_h, size, size);
+
+        if(getLayer()==null||getLayer().isVisibleTexts()) paintText(g, position);
+    }
+
+    public static Style getDefaultStyle(){
+        return new Style(Color.ORANGE, new Color(200,200,200,200), null, getDefaultFont());
+    }
+    @Override
+    public String toString() {
+        return "MapMarker at " + getLat() + " " + getLon();
+    }
+    @Override
+    public void setLat(double lat) {
+        if(coord==null) coord = new Coordinate(lat,0);
+        else coord.setLat(lat);
+    }
+    @Override
+    public void setLon(double lon) {
+        if(coord==null) coord = new Coordinate(0,lon);
+        else coord.setLon(lon);
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java b/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java
index e6d658f..4b55e4f 100644
--- a/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java
+++ b/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java
@@ -3,8 +3,6 @@ package org.openstreetmap.gui.jmapviewer;
 //License: GPL. Copyright 2008 by Jan Peter Stotz
 
 import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Point;
 
 import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
 
@@ -16,43 +14,40 @@ import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
  * @author Jan Peter Stotz
  *
  */
-public class MapMarkerDot implements MapMarker {
+public class MapMarkerDot extends MapMarkerCircle {
 
-    double lat;
-    double lon;
-    Color color;
+    public static final int DOT_RADIUS = 5;
 
-    public MapMarkerDot(double lat, double lon) {
-        this(Color.YELLOW, lat, lon);
+    public MapMarkerDot(Coordinate coord) {
+        this(null, null, coord);
+    }
+    public MapMarkerDot(String name, Coordinate coord) {
+        this(null, name, coord);
+    }
+    public MapMarkerDot(Layer layer, Coordinate coord) {
+        this(layer, null, coord);
+    }
+    public MapMarkerDot(Layer layer, String name, Coordinate coord) {
+        this(layer, name, coord, getDefaultStyle());
     }
-
     public MapMarkerDot(Color color, double lat, double lon) {
-        super();
-        this.color = color;
-        this.lat = lat;
-        this.lon = lon;
+        this(null, null, lat, lon);
+        setColor(color);
     }
-
-    public double getLat() {
-        return lat;
+    public MapMarkerDot(double lat, double lon) {
+        this(null, null, lat, lon);
     }
-
-    public double getLon() {
-        return lon;
+    public MapMarkerDot(Layer layer, double lat, double lon) {
+        this(layer, null, lat, lon);
     }
-
-    public void paint(Graphics g, Point position) {
-        int size_h = 5;
-        int size = size_h * 2;
-        g.setColor(color);
-        g.fillOval(position.x - size_h, position.y - size_h, size, size);
-        g.setColor(Color.BLACK);
-        g.drawOval(position.x - size_h, position.y - size_h, size, size);
+    public MapMarkerDot(Layer layer, String name, double lat, double lon) {
+        this(layer, name, new Coordinate(lat, lon), getDefaultStyle());
     }
-
-    @Override
-    public String toString() {
-        return "MapMarker at " + lat + " " + lon;
+    public MapMarkerDot(Layer layer, String name, Coordinate coord, Style style) {
+        super(layer, name, coord, DOT_RADIUS, STYLE.FIXED, style);
     }
 
+    public static Style getDefaultStyle(){
+        return new Style(Color.BLACK, Color.YELLOW, null, getDefaultFont());
+    }
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/MapObjectImpl.java b/src/org/openstreetmap/gui/jmapviewer/MapObjectImpl.java
new file mode 100644
index 0000000..69b8b01
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/MapObjectImpl.java
@@ -0,0 +1,109 @@
+package org.openstreetmap.gui.jmapviewer;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Stroke;
+
+import javax.swing.UIManager;
+
+public abstract class MapObjectImpl {
+    private Layer layer;
+    private String name;
+    private Style style;
+    private Boolean visible;
+
+    public MapObjectImpl(String name) {
+        this(null, name, null);
+    }
+    public MapObjectImpl(Layer layer) {
+        this(layer, null, null);
+    }
+    public MapObjectImpl(Layer layer, String name, Style style) {
+        super();
+        this.layer = layer;
+        this.name = name;
+        this.style = style;
+    }
+    public Layer getLayer() {
+        return layer;
+    }
+    public void setLayer(Layer layer) {
+        this.layer = layer;
+    }
+    public Style getStyle(){
+        return style;
+    }
+    public Style getStyleAssigned(){
+        return style == null ? (layer == null ? null : layer.getStyle()) : style;
+    }
+    public void setStyle(Style style){
+        this.style = style;
+    }
+    public Color getColor() {
+        Style styleAssigned = getStyleAssigned();
+        return styleAssigned == null ? null : getStyleAssigned().getColor();
+    }
+    public void setColor(Color color) {
+        if(style==null&&color!=null) style=new Style();
+        if(style!=null) style.setColor(color);
+    }
+
+    public Color getBackColor() {
+        Style styleAssigned = getStyleAssigned();
+        return styleAssigned == null ? null : getStyleAssigned().getBackColor();
+    }
+    public void setBackColor(Color backColor) {
+        if(style==null&&backColor!=null) style=new Style();
+        if(style!=null) style.setBackColor(backColor);
+    }
+
+    public Stroke getStroke() {
+        Style styleAssigned = getStyleAssigned();
+        return styleAssigned == null ? null : getStyleAssigned().getStroke();
+    }
+    public void setStroke(Stroke stroke) {
+        if(style==null&&stroke!=null) style=new Style();
+        if(style!=null) style.setStroke(stroke);
+    }
+    
+    public Font getFont() {
+        Style styleAssigned = getStyleAssigned();
+        return styleAssigned == null ? null : getStyleAssigned().getFont();
+    }
+    public void setFont(Font font) {
+        if(style==null&&font!=null) style=new Style();
+        if(style!=null) style.setFont(font);
+    }
+    private boolean isVisibleLayer(){
+        return layer==null||layer.isVisible()==null?true:layer.isVisible();
+    }
+    public boolean isVisible() {
+        return visible==null?isVisibleLayer():visible.booleanValue();
+    }
+    public void setVisible(Boolean visible) {
+        this.visible = visible;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String txt) {
+        this.name = txt;
+    }
+    public static Font getDefaultFont(){
+        Font f = UIManager.getDefaults().getFont("TextField.font");
+        return new Font(f.getName(), Font.BOLD, f.getSize());
+    }
+    public void paintText(Graphics g, Point position) {
+        if(name!=null && g!=null && position!=null){
+            if(getFont()==null){
+                Font f = getDefaultFont(); // g.getFont();
+                setFont(new Font(f.getName(), Font.BOLD, f.getSize()));
+            }
+            g.setColor(Color.DARK_GRAY);
+            g.setFont(getFont());
+            g.drawString(name, position.x+MapMarkerDot.DOT_RADIUS+2, position.y+MapMarkerDot.DOT_RADIUS);
+        }
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java b/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java
index 7f97433..4ea4515 100644
--- a/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java
+++ b/src/org/openstreetmap/gui/jmapviewer/MapPolygonImpl.java
@@ -1,85 +1,120 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.gui.jmapviewer;
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Polygon;
-import java.awt.Stroke;
-import java.util.List;
-
-import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
-
-/**
- * @author Vincent
- *
- */
-public class MapPolygonImpl implements MapPolygon {
-
-    private List<Coordinate> points;
-    private Color color;
-    private Stroke stroke;
-
-    public MapPolygonImpl(List<Coordinate> points) {
-        this(points, Color.BLUE, new BasicStroke(2));
-    }
-
-    public MapPolygonImpl(List<Coordinate> points, Color color, Stroke stroke) {
-        this.points = points;
-        this.color = color;
-        this.stroke = stroke;
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#getPoints()
-     */
-    @Override
-    public List<Coordinate> getPoints() {
-        return this.points;
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.util.List)
-     */
-    @Override
-    public void paint(Graphics g, List<Point> points) {
-        Polygon polygon = new Polygon();
-        for (Point p : points) {
-            polygon.addPoint(p.x, p.y);
-        }
-        paint(g, polygon);
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.awt.Polygon)
-     */
-    @Override
-    public void paint(Graphics g, Polygon polygon) {
-        // Prepare graphics
-        Color oldColor = g.getColor();
-        g.setColor(color);
-        Stroke oldStroke = null;
-        if (g instanceof Graphics2D) {
-            Graphics2D g2 = (Graphics2D) g;
-            oldStroke = g2.getStroke();
-            g2.setStroke(stroke);
-        }
-        // Draw
-        g.drawPolygon(polygon);
-        // Restore graphics
-        g.setColor(oldColor);
-        if (g instanceof Graphics2D) {
-            ((Graphics2D) g).setStroke(oldStroke);
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "MapPolygon [points=" + points + "]";
-    }
-}
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.gui.jmapviewer;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+import java.util.Arrays;
+import java.util.List;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
+import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
+
+/**
+ * @author Vincent
+ *
+ */
+public class MapPolygonImpl extends MapObjectImpl implements MapPolygon {
+
+    private List<? extends ICoordinate> points;
+
+    public MapPolygonImpl(ICoordinate ... points) {
+        this(null, null, points);
+    }
+    public MapPolygonImpl(List<? extends ICoordinate> points) {
+        this(null, null, points);
+    }
+    public MapPolygonImpl(String name, List<? extends ICoordinate> points) {
+        this(null, name, points);
+    }
+    public MapPolygonImpl(String name, ICoordinate ... points) {
+        this(null, name, points);
+    }
+    public MapPolygonImpl(Layer layer, List<? extends ICoordinate> points) {
+        this(layer, null, points);
+    }
+    public MapPolygonImpl(Layer layer, String name, List<? extends ICoordinate> points) {
+        this(layer, name, points, getDefaultStyle());
+    }
+    public MapPolygonImpl(Layer layer, String name, ICoordinate ... points) {
+        this(layer, name, Arrays.asList(points), getDefaultStyle());
+    }
+    public MapPolygonImpl(Layer layer, String name, List<? extends ICoordinate> points, Style style) {
+        super(layer, name, style);
+        this.points = points;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#getPoints()
+     */
+    @Override
+    public List<? extends ICoordinate> getPoints() {
+        return this.points;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.util.List)
+     */
+    @Override
+    public void paint(Graphics g, List<Point> points) {
+        Polygon polygon = new Polygon();
+        for (Point p : points) {
+            polygon.addPoint(p.x, p.y);
+        }
+        paint(g, polygon);
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon#paint(java.awt.Graphics, java.awt.Polygon)
+     */
+    @Override
+    public void paint(Graphics g, Polygon polygon) {
+        // Prepare graphics
+        Color oldColor = g.getColor();
+        g.setColor(getColor());
+
+        Stroke oldStroke = null;
+        if (g instanceof Graphics2D) {
+            Graphics2D g2 = (Graphics2D) g;
+            oldStroke = g2.getStroke();
+            g2.setStroke(getStroke());
+        }
+        // Draw
+        g.drawPolygon(polygon);
+        if (g instanceof Graphics2D && getBackColor()!=null) {
+            Graphics2D g2 = (Graphics2D) g;
+            Composite oldComposite = g2.getComposite();
+            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+            g2.setPaint(getBackColor());
+            g2.fillPolygon(polygon);
+            g2.setComposite(oldComposite);
+        }
+        // Restore graphics
+        g.setColor(oldColor);
+        if (g instanceof Graphics2D) {
+            ((Graphics2D) g).setStroke(oldStroke);
+        }
+        Rectangle rec = polygon.getBounds();
+        Point corner = rec.getLocation();
+        Point p= new Point(corner.x+(rec.width/2), corner.y+(rec.height/2));
+        if(getLayer()==null||getLayer().isVisibleTexts()) paintText(g, p);
+    }
+
+    public static Style getDefaultStyle(){
+        return new Style(Color.BLUE, new Color(100,100,100,50), new BasicStroke(2), getDefaultFont());
+    }
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "MapPolygon [points=" + points + "]";
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java b/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java
index 83889f6..08bc7d3 100644
--- a/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java
+++ b/src/org/openstreetmap/gui/jmapviewer/MapRectangleImpl.java
@@ -1,78 +1,89 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.gui.jmapviewer;
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Stroke;
-
-import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
-
-/**
- * @author Vincent
- *
- */
-public class MapRectangleImpl implements MapRectangle {
-
-    private Coordinate topLeft;
-    private Coordinate bottomRight;
-    private Color color;
-    private Stroke stroke;
-
-    public MapRectangleImpl(Coordinate topLeft, Coordinate bottomRight) {
-        this(topLeft, bottomRight, Color.BLUE, new BasicStroke(2));
-    }
-
-    public MapRectangleImpl(Coordinate topLeft, Coordinate bottomRight, Color color, Stroke stroke) {
-        this.topLeft = topLeft;
-        this.bottomRight = bottomRight;
-        this.color = color;
-        this.stroke = stroke;
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle#getTopLeft()
-     */
-    @Override
-    public Coordinate getTopLeft() {
-        return topLeft;
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle#getBottomRight()
-     */
-    @Override
-    public Coordinate getBottomRight() {
-        return bottomRight;
-    }
-
-    /* (non-Javadoc)
-     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle#paint(java.awt.Graphics, java.awt.Point, java.awt.Point)
-     */
-    @Override
-    public void paint(Graphics g, Point topLeft, Point bottomRight) {
-        // Prepare graphics
-        Color oldColor = g.getColor();
-        g.setColor(color);
-        Stroke oldStroke = null;
-        if (g instanceof Graphics2D) {
-            Graphics2D g2 = (Graphics2D) g;
-            oldStroke = g2.getStroke();
-            g2.setStroke(stroke);
-        }
-        // Draw
-        g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
-        // Restore graphics
-        g.setColor(oldColor);
-        if (g instanceof Graphics2D) {
-            ((Graphics2D) g).setStroke(oldStroke);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "MapRectangle from " + topLeft + " to " + bottomRight;
-    }
-}
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.gui.jmapviewer;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Stroke;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
+
+/**
+ * @author Vincent
+ *
+ */
+public class MapRectangleImpl extends MapObjectImpl implements MapRectangle {
+
+    private Coordinate topLeft;
+    private Coordinate bottomRight;
+
+    public MapRectangleImpl(Coordinate topLeft, Coordinate bottomRight) {
+        this(null, null, topLeft, bottomRight);
+    }
+    public MapRectangleImpl(String name, Coordinate topLeft, Coordinate bottomRight) {
+        this(null, name, topLeft, bottomRight);
+    }
+    public MapRectangleImpl(Layer layer, Coordinate topLeft, Coordinate bottomRight) {
+        this(layer, null, topLeft, bottomRight);
+    }
+    public MapRectangleImpl(Layer layer, String name, Coordinate topLeft, Coordinate bottomRight) {
+        this(layer, name, topLeft, bottomRight, getDefaultStyle());
+    }
+    public MapRectangleImpl(Layer layer, String name, Coordinate topLeft, Coordinate bottomRight, Style style) {
+        super(layer, name, style);
+        this.topLeft = topLeft;
+        this.bottomRight = bottomRight;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle#getTopLeft()
+     */
+    @Override
+    public Coordinate getTopLeft() {
+        return topLeft;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle#getBottomRight()
+     */
+    @Override
+    public Coordinate getBottomRight() {
+        return bottomRight;
+    }
+
+    /* (non-Javadoc)
+     * @see org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle#paint(java.awt.Graphics, java.awt.Point, java.awt.Point)
+     */
+    @Override
+    public void paint(Graphics g, Point topLeft, Point bottomRight) {
+        // Prepare graphics
+        Color oldColor = g.getColor();
+        g.setColor(getColor());
+        Stroke oldStroke = null;
+        if (g instanceof Graphics2D) {
+            Graphics2D g2 = (Graphics2D) g;
+            oldStroke = g2.getStroke();
+            g2.setStroke(getStroke());
+        }
+        // Draw
+        g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
+        // Restore graphics
+        g.setColor(oldColor);
+        if (g instanceof Graphics2D) {
+            ((Graphics2D) g).setStroke(oldStroke);
+        }
+        int width=bottomRight.x-topLeft.x;
+        int height=bottomRight.y-topLeft.y;
+        Point p= new Point(topLeft.x+(width/2), topLeft.y+(height/2));
+        if(getLayer()==null||getLayer().isVisibleTexts()) paintText(g, p);
+    }
+    public static Style getDefaultStyle(){
+        return new Style(Color.BLUE, null, new BasicStroke(2), getDefaultFont());
+    }
+    @Override
+    public String toString() {
+        return "MapRectangle from " + getTopLeft() + " to " + getBottomRight();
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java b/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
index 2591a99..f1d4dd1 100644
--- a/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
+++ b/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
@@ -2,7 +2,8 @@ package org.openstreetmap.gui.jmapviewer;
 
 //License: GPL. Copyright 2008 by Jan Peter Stotz
 
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.logging.Logger;
 
 import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
@@ -24,28 +25,31 @@ public class MemoryTileCache implements TileCache {
      */
     protected int cacheSize = 200;
 
-    protected Hashtable<String, CacheEntry> hashtable;
+    protected final Map<String, CacheEntry> hash;
 
     /**
      * List of all tiles in their last recently used order
      */
-    protected CacheLinkedListElement lruTiles;
+    protected final CacheLinkedListElement lruTiles;
 
     public MemoryTileCache() {
-        hashtable = new Hashtable<String, CacheEntry>(cacheSize);
+        hash = new HashMap<String, CacheEntry>(cacheSize);
         lruTiles = new CacheLinkedListElement();
     }
 
-    public void addTile(Tile tile) {
+    @Override
+    public synchronized void addTile(Tile tile) {
         CacheEntry entry = createCacheEntry(tile);
-        hashtable.put(tile.getKey(), entry);
-        lruTiles.addFirst(entry);
-        if (hashtable.size() > cacheSize)
-            removeOldEntries();
+            hash.put(tile.getKey(), entry);
+            lruTiles.addFirst(entry);
+            if (hash.size() > cacheSize) {
+                removeOldEntries();
+            }
     }
 
-    public Tile getTile(TileSource source, int x, int y, int z) {
-        CacheEntry entry = hashtable.get(Tile.getTileKey(source, x, y, z));
+    @Override
+    public synchronized Tile getTile(TileSource source, int x, int y, int z) {
+        CacheEntry entry = hash.get(Tile.getTileKey(source, x, y, z));
         if (entry == null)
             return null;
         // We don't care about placeholder tiles and hourglass image tiles, the
@@ -58,20 +62,18 @@ public class MemoryTileCache implements TileCache {
     /**
      * Removes the least recently used tiles
      */
-    protected void removeOldEntries() {
-        synchronized (lruTiles) {
-            try {
-                while (lruTiles.getElementCount() > cacheSize) {
-                    removeEntry(lruTiles.getLastElement());
-                }
-            } catch (Exception e) {
-                log.warning(e.getMessage());
+    protected synchronized void removeOldEntries() {
+        try {
+            while (lruTiles.getElementCount() > cacheSize) {
+                removeEntry(lruTiles.getLastElement());
             }
+        } catch (Exception e) {
+            log.warning(e.getMessage());
         }
     }
 
-    protected void removeEntry(CacheEntry entry) {
-        hashtable.remove(entry.tile.getKey());
+    protected synchronized void removeEntry(CacheEntry entry) {
+        hash.remove(entry.tile.getKey());
         lruTiles.removeEntry(entry);
     }
 
@@ -82,15 +84,14 @@ public class MemoryTileCache implements TileCache {
     /**
      * Clears the cache deleting all tiles from memory
      */
-    public void clear() {
-        synchronized (lruTiles) {
-            hashtable.clear();
-            lruTiles.clear();
-        }
+    public synchronized void clear() {
+        hash.clear();
+        lruTiles.clear();
     }
 
+    @Override
     public int getTileCount() {
-        return hashtable.size();
+        return hash.size();
     }
 
     public int getCacheSize() {
@@ -103,9 +104,9 @@ public class MemoryTileCache implements TileCache {
      * @param cacheSize
      *            new maximum number of tiles
      */
-    public void setCacheSize(int cacheSize) {
+    public synchronized void setCacheSize(int cacheSize) {
         this.cacheSize = cacheSize;
-        if (hashtable.size() > cacheSize)
+        if (hash.size() > cacheSize)
             removeOldEntries();
     }
 
@@ -153,7 +154,7 @@ public class MemoryTileCache implements TileCache {
             clear();
         }
 
-        public synchronized void clear() {
+        public void clear() {
             elementCount = 0;
             firstElement = null;
             lastElement = null;
@@ -164,7 +165,8 @@ public class MemoryTileCache implements TileCache {
          *
          * @param element new element to be added
          */
-        public synchronized void addFirst(CacheEntry element) {
+        public void addFirst(CacheEntry element) {
+            if (element == null) return;
             if (elementCount == 0) {
                 firstElement = element;
                 lastElement = element;
@@ -184,7 +186,8 @@ public class MemoryTileCache implements TileCache {
          *
          * @param element element to be removed
          */
-        public synchronized void removeEntry(CacheEntry element) {
+        public void removeEntry(CacheEntry element) {
+            if (element == null) return;
             if (element.next != null) {
                 element.next.prev = element.prev;
             }
@@ -200,7 +203,7 @@ public class MemoryTileCache implements TileCache {
             elementCount--;
         }
 
-        public synchronized void moveElementToFirstPos(CacheEntry entry) {
+        public void moveElementToFirstPos(CacheEntry entry) {
             if (firstElement == entry)
                 return;
             removeEntry(entry);
diff --git a/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java b/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
index ea82c74..7cc6dab 100644
--- a/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
+++ b/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
@@ -14,7 +14,6 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.lang.Thread;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
@@ -26,6 +25,8 @@ import java.util.Random;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.openstreetmap.gui.jmapviewer.interfaces.CachedTileLoader;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileClearController;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
@@ -40,7 +41,7 @@ import org.openstreetmap.gui.jmapviewer.interfaces.TileSource.TileUpdate;
  * @author Jan Peter Stotz
  * @author Stefan Zeller
  */
-public class OsmFileCacheTileLoader extends OsmTileLoader {
+public class OsmFileCacheTileLoader extends OsmTileLoader implements CachedTileLoader {
 
     private static final Logger log = Logger.getLogger(OsmFileCacheTileLoader.class.getName());
 
@@ -53,7 +54,7 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
     public static final long FILE_AGE_ONE_WEEK = FILE_AGE_ONE_DAY * 7;
 
     protected String cacheDirBase;
-    
+
     protected final Map<TileSource, File> sourceCacheDirMap;
 
     protected long maxCacheFileAge = FILE_AGE_ONE_WEEK;
@@ -126,7 +127,7 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
         }
         return dir;
     }
-    
+
     protected class FileLoadJob implements TileJob {
         InputStream input = null;
 
@@ -140,10 +141,12 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
             this.tile = tile;
         }
 
+        @Override
         public Tile getTile() {
             return tile;
         }
 
+        @Override
         public void run() {
             synchronized (tile) {
                 if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
@@ -159,9 +162,11 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
             if (fileTilePainted) {
                 TileJob job = new TileJob() {
 
+                    @Override
                     public void run() {
                         loadOrUpdateTile();
                     }
+                    @Override
                     public Tile getTile() {
                         return tile;
                     }
@@ -304,20 +309,25 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
 
         protected byte[] loadTileInBuffer(URLConnection urlConn) throws IOException {
             input = urlConn.getInputStream();
-            ByteArrayOutputStream bout = new ByteArrayOutputStream(input.available());
-            byte[] buffer = new byte[2048];
-            boolean finished = false;
-            do {
-                int read = input.read(buffer);
-                if (read >= 0) {
-                    bout.write(buffer, 0, read);
-                } else {
-                    finished = true;
-                }
-            } while (!finished);
-            if (bout.size() == 0)
-                return null;
-            return bout.toByteArray();
+            try {
+                ByteArrayOutputStream bout = new ByteArrayOutputStream(input.available());
+                byte[] buffer = new byte[2048];
+                boolean finished = false;
+                do {
+                    int read = input.read(buffer);
+                    if (read >= 0) {
+                        bout.write(buffer, 0, read);
+                    } else {
+                        finished = true;
+                    }
+                } while (!finished);
+                if (bout.size() == 0)
+                    return null;
+                return bout.toByteArray();
+            } finally {
+                input.close();
+                input = null;
+            }
         }
 
         /**
@@ -331,7 +341,7 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
          * <li>{@link tilesources.OsmTileSource.Mapnik} - not supported</li>
          * </ul>
          *
-         * @param fileAge time of the 
+         * @param fileAge time of the
          * @return <code>true</code> if the tile on the server is newer than the
          *         file
          * @throws IOException
@@ -481,24 +491,13 @@ public class OsmFileCacheTileLoader extends OsmTileLoader {
         dir.mkdirs();
         this.cacheDirBase = dir.getAbsolutePath();
     }
-    
-    public static interface TileClearController {
 
-        void initClearDir(File dir);
-
-        void initClearFiles(File[] files);
-
-        boolean cancel();
-
-        void fileDeleted(File file);
-
-        void clearFinished();
-    }
-    
+    @Override
     public void clearCache(TileSource source) {
         clearCache(source, null);
     }
-    
+
+    @Override
     public void clearCache(TileSource source, TileClearController controller) {
         File dir = getSourceCacheDir(source);
         if (dir != null) {
diff --git a/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java b/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
index 10d65a4..8bc92a1 100644
--- a/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
+++ b/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
@@ -18,7 +18,7 @@ public class OsmMercator {
     private static int TILE_SIZE = 256;
     public static final double MAX_LAT = 85.05112877980659;
     public static final double MIN_LAT = -85.05112877980659;
-    private static double EARTH_RADIUS = 6378137; // equatorial earth radius for EPSG:3857 (Mercator) 
+    private static double EARTH_RADIUS = 6378137; // equatorial earth radius for EPSG:3857 (Mercator)
 
     public static double radius(int aZoomlevel) {
         return (TILE_SIZE * (1 << aZoomlevel)) / (2.0 * Math.PI);
@@ -50,7 +50,7 @@ public class OsmMercator {
      * @param y1 the first y coordinate
      * @param x2 the second x coordinate
      * @param y2 the second y coordinate
-     * 
+     *
      * @param zoomLevel the zoom level
      * @return the distance
      * @author Jason Huntley
@@ -84,7 +84,7 @@ public class OsmMercator {
                 + Math.cos(aStartLat) * Math.cos(aEndLat)
                 * Math.cos(aEndLong - aStartLong));
 
-        return (EARTH_RADIUS * distance);		
+        return (EARTH_RADIUS * distance);
     }
 
     /**
diff --git a/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java b/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
index 1d80996..8f34039 100644
--- a/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
+++ b/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
@@ -7,14 +7,13 @@ import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.HashMap;
 
 import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
-import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 
 /**
  * A {@link TileLoader} implementation that loads tiles from OSM.
@@ -58,9 +57,12 @@ public class OsmTileLoader implements TileLoader {
                         tile.setError("No tile at this zoom level");
                     } else {
                         input = conn.getInputStream();
-                        tile.loadImage(input);
-                        input.close();
-                        input = null;
+                        try {
+                            tile.loadImage(input);
+                        } finally {
+                            input.close();
+                            input = null;
+                        }
                     }
                     tile.setLoaded(true);
                     listener.tileLoadingFinished(tile, true);
diff --git a/src/org/openstreetmap/gui/jmapviewer/Style.java b/src/org/openstreetmap/gui/jmapviewer/Style.java
new file mode 100644
index 0000000..b7e3e8f
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/Style.java
@@ -0,0 +1,61 @@
+package org.openstreetmap.gui.jmapviewer;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Stroke;
+
+public class Style {
+    private Color color;
+    private Color backColor;
+    private Stroke stroke;
+    private Font font;
+    
+    private static final AlphaComposite TRANSPARENCY = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
+    private static final AlphaComposite OPAQUE = AlphaComposite.getInstance(AlphaComposite.SRC);
+
+    public Style(){
+        super();
+    }
+    public Style(Color color, Color backColor, Stroke stroke, Font font) {
+        super();
+        this.color = color;
+        this.backColor = backColor;
+        this.stroke = stroke;
+        this.font = font;
+    }
+
+    public Color getColor() {
+        return color;
+    }
+    public void setColor(Color color) {
+        this.color = color;
+    }
+    public Color getBackColor() {
+        return backColor;
+    }
+    public void setBackColor(Color backColor) {
+        this.backColor = backColor;
+    }
+    public Stroke getStroke() {
+        return stroke;
+    }
+    public void setStroke(Stroke stroke) {
+        this.stroke = stroke;
+    }
+    public Font getFont() {
+        return font;
+    }
+    public void setFont(Font font) {
+        this.font = font;
+    }
+    private AlphaComposite getAlphaComposite(Color color){
+        return color.getAlpha()==255?OPAQUE:TRANSPARENCY;
+    }
+    public AlphaComposite getAlphaComposite(){
+        return getAlphaComposite(color);
+    }
+    public AlphaComposite getBackAlphaComposite(){
+        return getAlphaComposite(backColor);
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/Tile.java b/src/org/openstreetmap/gui/jmapviewer/Tile.java
index 389d09a..7a6086e 100644
--- a/src/org/openstreetmap/gui/jmapviewer/Tile.java
+++ b/src/org/openstreetmap/gui/jmapviewer/Tile.java
@@ -283,11 +283,11 @@ public class Tile {
 
     /**
      * Puts the given key/value pair to the metadata of the tile.
-     * If value is null, the (possibly existing) key/value pair is removed from 
+     * If value is null, the (possibly existing) key/value pair is removed from
      * the meta data.
-     * 
+     *
      * @param key
-     * @param value 
+     * @param value
      */
     public void putValue(String key, String value) {
         if (value == null || value.isEmpty()) {
@@ -310,4 +310,15 @@ public class Tile {
     public Map<String,String> getMetadata() {
         return metadata;
     }
+
+    public void initLoading() {
+        loaded = false;
+        error = false;
+        loading = true;
+    }
+
+    public void finishLoading() {
+        loading = false;
+        loaded = true;
+    }
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeData.java b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeData.java
new file mode 100644
index 0000000..152a15a
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeData.java
@@ -0,0 +1,43 @@
+package org.openstreetmap.gui.jmapviewer.checkBoxTree;
+
+import org.openstreetmap.gui.jmapviewer.AbstractLayer;
+import org.openstreetmap.gui.jmapviewer.LayerGroup;
+
+/**
+ * Node Data for checkBox Tree
+ * 
+ * @author galo
+ */
+public class CheckBoxNodeData {
+    private AbstractLayer layer;
+
+    public CheckBoxNodeData(final AbstractLayer layer) {
+        this.layer = layer;
+    }
+    public CheckBoxNodeData(final String txt) {
+        this(new LayerGroup(txt));
+    }
+    public CheckBoxNodeData(final String txt, final Boolean selected) {
+        this(new LayerGroup(txt));
+        layer.setVisible(selected);
+    }
+    public Boolean isSelected() {
+            return layer.isVisible();
+    }
+    public void setSelected(final Boolean newValue) {
+        layer.setVisible(newValue);
+    }
+    public String getText() {
+            return layer.getName();
+    }
+    public AbstractLayer getAbstractLayer() {
+        return layer;
+}
+    public void setAbstractLayer(final AbstractLayer layer) {
+            this.layer = layer;
+    }
+    @Override
+    public String toString() {
+            return getClass().getSimpleName() + "[" + getText() + "/" + isSelected() + "]";
+    }
+}
\ No newline at end of file
diff --git a/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeEditor.java b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeEditor.java
new file mode 100644
index 0000000..b55a15e
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeEditor.java
@@ -0,0 +1,101 @@
+package org.openstreetmap.gui.jmapviewer.checkBoxTree;
+
+import java.awt.Component;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.EventObject;
+
+import javax.swing.AbstractCellEditor;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeCellEditor;
+import javax.swing.tree.TreePath;
+
+/**
+ * Editor for checkBox Tree
+ * 
+ * @author galo
+ */
+public class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor{
+    /** SerialVersionUID */
+    private static final long serialVersionUID = -8921320784224636657L;
+
+    private final CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
+
+    private final CheckBoxTree theTree;
+
+    public CheckBoxNodeEditor(final CheckBoxTree tree) {
+        theTree = tree;
+    }
+
+    @Override
+    public Object getCellEditorValue() {
+        final CheckBoxNodePanel panel = renderer.getPanel();
+        /*final CheckBoxNodeData checkBoxNode =
+            new CheckBoxNodeData(panel.label.getText(), panel.check.isSelected());
+        return checkBoxNode;
+        CheckBoxNodeData data = search(theTree.rootNode(), panel.label.getText());
+        data.setSelected(panel.check.isSelected());*/
+        return panel.getData();
+    }
+    /*public CheckBoxNodeData search(DefaultMutableTreeNode node, String name){
+        CheckBoxNodeData data = CheckBoxTree.data(node);
+        if(data.getText().equals(name)) return data;
+        else{
+            data = null;
+            for(int i=0; i<node.getChildCount() && data==null; i++){
+                data = search((DefaultMutableTreeNode)node.getChildAt(i), name);
+            }
+            return data;
+        }
+    }*/
+    public void addNodeListener(MouseAdapter listener){
+        renderer.addNodeListener(listener);
+    }
+    @Override
+    public boolean isCellEditable(final EventObject event) {
+        if (!(event instanceof MouseEvent)) return false;
+        final MouseEvent mouseEvent = (MouseEvent) event;
+
+        final TreePath path =
+            theTree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
+        if (path == null) return false;
+
+        final Object node = path.getLastPathComponent();
+        if (!(node instanceof DefaultMutableTreeNode)) return false;
+        final DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
+
+        final Object userObject = treeNode.getUserObject();
+        return userObject instanceof CheckBoxNodeData;
+    }
+
+    @Override
+    public Component getTreeCellEditorComponent(final JTree tree,
+        final Object value, final boolean selected, final boolean expanded,
+        final boolean leaf, final int row)
+    {
+
+        final Component editor =
+            renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf,
+                row, true);
+
+        // editor always selected / focused
+        final ItemListener itemListener = new ItemListener() {
+
+            @Override
+            public void itemStateChanged(final ItemEvent itemEvent) {
+                if (stopCellEditing()) {
+                    fireEditingStopped();
+                }
+            }
+        };
+        if (editor instanceof CheckBoxNodePanel) {
+            final CheckBoxNodePanel panel = (CheckBoxNodePanel) editor;
+            panel.check.addItemListener(itemListener);
+        }
+
+        return editor;
+    }
+}
\ No newline at end of file
diff --git a/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodePanel.java b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodePanel.java
new file mode 100644
index 0000000..e8985dc
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodePanel.java
@@ -0,0 +1,48 @@
+package org.openstreetmap.gui.jmapviewer.checkBoxTree;
+
+import java.awt.BorderLayout;
+import java.awt.Insets;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * Node Panel for checkBox Tree
+ * 
+ * @author galo
+ */
+public class CheckBoxNodePanel extends JPanel {
+    /** Serial Version UID */
+    private static final long serialVersionUID = -7236481597785619029L;
+    private final JLabel label = new JLabel();
+    private CheckBoxNodeData data;
+    public final JCheckBox check = new JCheckBox();
+
+    public CheckBoxNodePanel() {
+        this.check.setMargin(new Insets(0, 0, 0, 0));
+        setLayout(new BorderLayout());
+        add(check, BorderLayout.WEST);
+        add(label, BorderLayout.CENTER);
+    }
+    public void setSelected(Boolean bool){
+        if(bool==null){
+            check.getModel().setPressed(true);
+            check.getModel().setArmed(true);
+        }else{
+            check.setSelected(bool.booleanValue());
+            check.getModel().setArmed(false);
+        }
+    }
+    public CheckBoxNodeData getData() {
+        data.setSelected(check.isSelected());
+        return data;
+    }
+    public void setData(CheckBoxNodeData data) {
+        this.data = data;
+        label.setText(data.getText());
+    }
+    public JLabel getLabel() {
+        return label;
+    }
+}
\ No newline at end of file
diff --git a/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeRenderer.java b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeRenderer.java
new file mode 100644
index 0000000..a85cb0e
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeRenderer.java
@@ -0,0 +1,126 @@
+package org.openstreetmap.gui.jmapviewer.checkBoxTree;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.UIManager;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreeCellRenderer;
+
+import org.openstreetmap.gui.jmapviewer.AbstractLayer;
+import org.openstreetmap.gui.jmapviewer.LayerGroup;
+
+/**
+ * Renderer for checkBox Tree
+ * 
+ * @author galo
+ */
+public class CheckBoxNodeRenderer implements TreeCellRenderer{
+
+    private final CheckBoxNodePanel panel = new CheckBoxNodePanel();
+    private final DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
+    private final Color selectionForeground, selectionBackground;
+    private final Color textForeground, textBackground;
+
+    protected CheckBoxNodePanel getPanel() {
+        return panel;
+    }
+
+    public CheckBoxNodeRenderer() {
+        final Font fontValue = UIManager.getFont("Tree.font");
+        if (fontValue != null) panel.getLabel().setFont(fontValue);
+
+        final Boolean focusPainted =
+            (Boolean) UIManager.get("Tree.drawsFocusBorderAroundIcon");
+        panel.check.setFocusPainted(focusPainted != null && focusPainted);
+
+        selectionForeground = UIManager.getColor("Tree.selectionForeground");
+        selectionBackground = UIManager.getColor("Tree.selectionBackground");
+        textForeground = UIManager.getColor("Tree.textForeground");
+        textBackground = UIManager.getColor("Tree.textBackground");
+    }
+    public void addNodeListener(MouseAdapter listener){
+        panel.addMouseListener(listener);
+    }
+    // -- TreeCellRenderer methods --
+
+    @Override
+    public Component getTreeCellRendererComponent(final JTree tree,
+        final Object value, final boolean selected, final boolean expanded,
+        final boolean leaf, final int row, final boolean hasFocus)
+    {
+        CheckBoxNodeData data = null;
+        if (value instanceof DefaultMutableTreeNode) {
+            final DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
+            final Object userObject = node.getUserObject();
+            if (userObject instanceof CheckBoxNodeData) {
+                data = (CheckBoxNodeData) userObject;
+            }
+        }
+
+        //final String stringValue =
+        //    tree.convertValueToText(value, selected, expanded, leaf, row, false);
+        //panel.label.setText(stringValue);
+
+        panel.setSelected(false);
+
+        panel.setEnabled(tree.isEnabled());
+
+        if (selected) {
+            panel.setForeground(selectionForeground);
+            panel.setBackground(selectionBackground);
+            panel.getLabel().setForeground(selectionForeground);
+            panel.getLabel().setBackground(selectionBackground);
+        }
+        else {
+            panel.setForeground(textForeground);
+            panel.setBackground(textBackground);
+            panel.getLabel().setForeground(textForeground);
+            panel.getLabel().setBackground(textBackground);
+        }
+
+        if (data == null) {
+            // not a check box node; return default cell renderer
+            return defaultRenderer.getTreeCellRendererComponent(tree, value,
+                selected, expanded, leaf, row, hasFocus);
+        }
+
+        //panel.label.setText(data.getText());
+        panel.setData(data);
+        panel.setSelected(data.isSelected());
+
+        return panel;
+    }
+    private JPopupMenu createPopupMenu(final AbstractLayer layer) {
+        JMenuItem menuItem;
+ 
+        //Create the popup menu.
+        if(layer.isVisibleTexts()) menuItem = new JMenuItem("hide texts");
+        else menuItem = new JMenuItem("show texts");
+        JPopupMenu popup = new JPopupMenu();
+        popup.add(menuItem);
+        menuItem.addActionListener(new ActionListener(){
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                setVisibleTexts(layer, !layer.isVisibleTexts());
+            }
+        });
+ 
+        return popup;
+    }
+    private void setVisibleTexts(AbstractLayer layer, boolean visible){
+        layer.setVisibleTexts(visible);
+        if(layer instanceof LayerGroup){
+            LayerGroup group = (LayerGroup)layer;
+            if(group.getLayers()!=null) for(AbstractLayer al: group.getLayers()) setVisibleTexts(al, visible);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxTree.java b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxTree.java
new file mode 100644
index 0000000..dcd0a7b
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxTree.java
@@ -0,0 +1,237 @@
+package org.openstreetmap.gui.jmapviewer.checkBoxTree;
+
+import java.awt.BorderLayout;
+import java.awt.event.MouseAdapter;
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+
+import org.openstreetmap.gui.jmapviewer.AbstractLayer;
+import org.openstreetmap.gui.jmapviewer.Layer;
+import org.openstreetmap.gui.jmapviewer.LayerGroup;
+
+/**
+ * JTree for checkBox Tree Layers
+ * 
+ * @author galo
+ */
+public class CheckBoxTree extends JTree{
+    /** Serial Version UID */
+    private static final long serialVersionUID = 6943401106938034256L;
+    
+    private final CheckBoxNodeEditor editor;
+
+    public CheckBoxTree(AbstractLayer layer){
+        this(new CheckBoxNodeData(layer));
+    }
+    public CheckBoxTree(String rootName){
+        this(new CheckBoxNodeData(rootName));
+    }
+    public CheckBoxTree(CheckBoxNodeData root ){
+        this(new DefaultMutableTreeNode(root));
+    }
+    public CheckBoxTree(DefaultMutableTreeNode node){
+        super(new DefaultTreeModel(node));
+
+        final CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
+        setCellRenderer(renderer);
+
+        editor = new CheckBoxNodeEditor(this);
+        setCellEditor(editor);
+        setEditable(true);
+        
+        // listen for changes in the model (including check box toggles)
+        getModel().addTreeModelListener(new TreeModelListener() {
+            @Override
+            public void treeNodesChanged(final TreeModelEvent e) {
+                DefaultTreeModel model = (DefaultTreeModel)e.getSource();
+                Object[] nodes = e.getChildren();
+                DefaultMutableTreeNode node;
+                if(nodes==null||nodes.length==0){
+                    node = node(model.getRoot());
+                }else{
+                    node = node(nodes[0]);
+                }
+                nodeChanged(node);
+                repaint();
+            }
+
+            @Override
+            public void treeNodesInserted(final TreeModelEvent e) {
+                //System.out.println("nodes inserted");
+            }
+
+            @Override
+            public void treeNodesRemoved(final TreeModelEvent e) {
+                //System.out.println("nodes removed");
+            }
+
+            @Override
+            public void treeStructureChanged(final TreeModelEvent e) {
+                //System.out.println("structure changed");
+            }
+        });
+    }
+    public void addNodeListener(MouseAdapter listener){
+        editor.addNodeListener(listener);
+    }
+    public static void main(final String args[]) {
+        final DefaultMutableTreeNode root = new DefaultMutableTreeNode(new CheckBoxNodeData("Root",true));
+
+        final DefaultMutableTreeNode accessibility =
+            add(root, "Accessibility", true);
+        add(accessibility, "Move system caret with focus/selection changes", false);
+        add(accessibility, "Always expand alt text for images", true);
+        root.add(accessibility);
+
+        final DefaultMutableTreeNode browsing =
+            new DefaultMutableTreeNode(new CheckBoxNodeData("Browsing", null));
+        add(browsing, "Notify when downloads complete", true);
+        add(browsing, "Disable script debugging", true);
+        add(browsing, "Use AutoComplete", true);
+        add(browsing, "Browse in a new process", false);
+        root.add(browsing);
+
+        final CheckBoxTree tree = new CheckBoxTree(root);
+        ((DefaultMutableTreeNode)tree.getModel().getRoot()).add(new DefaultMutableTreeNode(new CheckBoxNodeData("gggg", null)));
+        ((DefaultTreeModel)tree.getModel()).reload();
+        // listen for changes in the selection
+        tree.addTreeSelectionListener(new TreeSelectionListener() {
+            @Override
+            public void valueChanged(final TreeSelectionEvent e) {
+                //System.out.println("selection changed");
+            }
+        });
+        // show the tree on screen
+        final JFrame frame = new JFrame("CheckBox Tree");
+        final JScrollPane scrollPane = new JScrollPane(tree);
+        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.setSize(300, 150);
+        frame.setVisible(true);
+    }
+    private static Boolean childStatus(DefaultMutableTreeNode node){
+        Boolean status = data(node.getChildAt(0)).isSelected();
+        for(int i=1; i<node.getChildCount()&&status!=null; i++){
+            if(status != data(node.getChildAt(i)).isSelected()) return null;
+        }
+        return status;
+    }
+    private static void changeParents(DefaultMutableTreeNode node){
+        if(node!=null){
+            DefaultMutableTreeNode parent = node(node.getParent());
+            if(parent!=null){
+                CheckBoxNodeData dataParent = data(parent);
+                Boolean childStatus = childStatus(parent);
+                if(dataParent.isSelected()!=childStatus){
+                    dataParent.setSelected(childStatus);
+                    changeParents(parent);
+                }
+            }
+        }
+    }
+    private static void nodeChanged(DefaultMutableTreeNode node){
+        if(node!=null){
+            changeParents(node);
+            setChildrens(node, data(node).isSelected());
+        }
+    }
+    private static void setChildrens(DefaultMutableTreeNode node, Boolean value){
+        for(int i=0; i<node.getChildCount(); i++){
+            DefaultMutableTreeNode childNode = node(node.getChildAt(i));
+            if (data(childNode).isSelected() !=data(node).isSelected()){
+                data(childNode).setSelected(data(node).isSelected());
+                setChildrens(childNode, value);
+            }
+        }
+    }
+    public DefaultMutableTreeNode rootNode(){
+        return node(getModel().getRoot());
+    }
+    public LayerGroup rootLayer(){
+        return (LayerGroup)rootData().getAbstractLayer();
+    }
+    public CheckBoxNodeData rootData(){
+        return data(rootNode());
+    }
+    private static DefaultMutableTreeNode node(Object node){
+        return (DefaultMutableTreeNode)node;
+    }
+    public static CheckBoxNodeData data(DefaultMutableTreeNode node){
+        return node==null?null:(CheckBoxNodeData)node.getUserObject();
+    }
+    private static CheckBoxNodeData data(Object node){
+        return data(node(node));
+    }
+    private static DefaultMutableTreeNode add(final DefaultMutableTreeNode parent, final String text, final boolean checked){
+        final CheckBoxNodeData data = new CheckBoxNodeData(text, checked);
+        final DefaultMutableTreeNode node = new DefaultMutableTreeNode(data);
+        parent.add(node);
+        return node;
+    }
+    public static CheckBoxNodeData createNodeData(AbstractLayer layer){
+        return new CheckBoxNodeData(layer);
+    }
+    public static DefaultMutableTreeNode createNode(AbstractLayer layer){
+        return new DefaultMutableTreeNode(createNodeData(layer));
+    }
+    /*public DefaultMutableTreeNode addLayerGroup(LayerGroup group){
+        if(group!=null){
+            if(group.getParent()==null){
+                return add(rootNode(), group);
+            }else{
+                DefaultMutableTreeNode parentGroup = searchNode(group.getParent());
+                if(parentGroup==null) parentGroup = addLayerGroup(group.getParent());
+                DefaultMutableTreeNode node = add(parentGroup, group);
+                return node;
+            }
+        }else return null;
+    }*/
+    public Layer addLayer(String name){
+        Layer layer = new Layer(name);
+        addLayer(layer);
+        return layer;
+    }
+    public DefaultMutableTreeNode addLayer(AbstractLayer layer){
+        if (layer!=null){
+            DefaultMutableTreeNode parent;
+            if(layer.getParent()==null){
+                rootLayer().add(layer);
+                parent = rootNode();
+            }else{
+                parent = searchNode(layer.getParent());
+                if(parent==null) parent=addLayer(layer.getParent());
+            }
+            return add(parent, layer);
+        }else return null;
+    }
+    public DefaultMutableTreeNode add(DefaultMutableTreeNode parent, final AbstractLayer layer){
+        layer.setVisible(data(parent).isSelected());
+        DefaultMutableTreeNode node = createNode(layer); 
+        parent.add(node);
+        ((DefaultTreeModel)getModel()).reload();
+        //System.out.println("Created node "+layer+" upper of "+data(parent));
+        return node;
+    }
+    public DefaultMutableTreeNode searchNode(AbstractLayer layer){
+        return searchNode(rootNode(), layer);
+    }
+    public DefaultMutableTreeNode searchNode(DefaultMutableTreeNode node, AbstractLayer layer){
+        CheckBoxNodeData data = CheckBoxTree.data(node);
+        if(data.getAbstractLayer() == layer) return node;
+        else{
+            DefaultMutableTreeNode found = null;
+            for(int i=0; i<node.getChildCount() && found==null; i++){
+                found = searchNode((DefaultMutableTreeNode)node.getChildAt(i), layer);
+            }
+            return found;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java b/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java
index 2c1c668..74f9954 100644
--- a/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java
+++ b/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java
@@ -1,49 +1,49 @@
-package org.openstreetmap.gui.jmapviewer.events;
-
-//License: GPL.
-
-import java.util.EventObject;
-
-/**
- * Used for passing events between UI components and other
- * objects that register as a JMapViewerEventListener
- * 
- * @author Jason Huntley
- *
- */
-public class JMVCommandEvent extends EventObject {
-    public static enum COMMAND {
-        MOVE,
-        ZOOM
-    }
-
-    private COMMAND command;
-    /**
-     * 
-     */
-    private static final long serialVersionUID = 8701544867914969620L;
-
-    public JMVCommandEvent(COMMAND cmd, Object source) {
-        super(source);
-
-        setCommand(cmd);
-    }
-
-    public JMVCommandEvent(Object source) {
-        super(source);
-    }
-
-    /**
-     * @return the command
-     */
-    public COMMAND getCommand() {
-        return command;
-    }
-
-    /**
-     * @param command the command to set
-     */
-    public void setCommand(COMMAND command) {
-        this.command = command;
-    }
-}
+package org.openstreetmap.gui.jmapviewer.events;
+
+//License: GPL.
+
+import java.util.EventObject;
+
+/**
+ * Used for passing events between UI components and other
+ * objects that register as a JMapViewerEventListener
+ *
+ * @author Jason Huntley
+ *
+ */
+public class JMVCommandEvent extends EventObject {
+    public static enum COMMAND {
+        MOVE,
+        ZOOM
+    }
+
+    private COMMAND command;
+    /**
+     *
+     */
+    private static final long serialVersionUID = 8701544867914969620L;
+
+    public JMVCommandEvent(COMMAND cmd, Object source) {
+        super(source);
+
+        setCommand(cmd);
+    }
+
+    public JMVCommandEvent(Object source) {
+        super(source);
+    }
+
+    /**
+     * @return the command
+     */
+    public COMMAND getCommand() {
+        return command;
+    }
+
+    /**
+     * @param command the command to set
+     */
+    public void setCommand(COMMAND command) {
+        this.command = command;
+    }
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/images/bing_maps.png b/src/org/openstreetmap/gui/jmapviewer/images/bing_maps.png
new file mode 100644
index 0000000..ae4367e
Binary files /dev/null and b/src/org/openstreetmap/gui/jmapviewer/images/bing_maps.png differ
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/Attributed.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/Attributed.java
index dd5eeae..81a8ca0 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/Attributed.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/Attributed.java
@@ -1,51 +1,51 @@
-package org.openstreetmap.gui.jmapviewer.interfaces;
-
-import java.awt.Image;
-
-import org.openstreetmap.gui.jmapviewer.Coordinate;
-
-//License: GPL.
-
-public interface Attributed {
-    /**
-     * @return True if the tile source requires attribution in text or image form.
-     */
-    boolean requiresAttribution();
-
-    /**
-     * @param zoom The optional zoom level for the view.
-     * @param botRight The bottom right of the bounding box for attribution.
-     * @param topLeft The top left of the bounding box for attribution.
-     * @return Attribution text for the image source.
-     */
-    String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight);
-
-    /**
-     * @return The URL to open when the user clicks the attribution text.
-     */
-    String getAttributionLinkURL();
-
-    /**
-     * @return The URL for the attribution image. Null if no image should be displayed.
-     */
-    Image getAttributionImage();
-
-    /**
-     * @return The URL to open when the user clicks the attribution image.
-     * When return value is null, the image is still displayed (provided getAttributionImage()
-     * returns a value other than null), but the image does not link to a website.
-     */
-    String getAttributionImageURL();
-
-    /**
-     * @return The attribution "Terms of Use" text.
-     * In case it returns null, but getTermsOfUseURL() is not null, a default
-     * terms of use text is used.
-     */
-    String getTermsOfUseText();
-
-    /**
-     * @return The URL to open when the user clicks the attribution "Terms of Use" text.
-     */
-    String getTermsOfUseURL();
-}
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+import java.awt.Image;
+
+import org.openstreetmap.gui.jmapviewer.Coordinate;
+
+//License: GPL.
+
+public interface Attributed {
+    /**
+     * @return True if the tile source requires attribution in text or image form.
+     */
+    boolean requiresAttribution();
+
+    /**
+     * @param zoom The optional zoom level for the view.
+     * @param botRight The bottom right of the bounding box for attribution.
+     * @param topLeft The top left of the bounding box for attribution.
+     * @return Attribution text for the image source.
+     */
+    String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight);
+
+    /**
+     * @return The URL to open when the user clicks the attribution text.
+     */
+    String getAttributionLinkURL();
+
+    /**
+     * @return The URL for the attribution image. Null if no image should be displayed.
+     */
+    Image getAttributionImage();
+
+    /**
+     * @return The URL to open when the user clicks the attribution image.
+     * When return value is null, the image is still displayed (provided getAttributionImage()
+     * returns a value other than null), but the image does not link to a website.
+     */
+    String getAttributionImageURL();
+
+    /**
+     * @return The attribution "Terms of Use" text.
+     * In case it returns null, but getTermsOfUseURL() is not null, a default
+     * terms of use text is used.
+     */
+    String getTermsOfUseText();
+
+    /**
+     * @return The URL to open when the user clicks the attribution "Terms of Use" text.
+     */
+    String getTermsOfUseURL();
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/CachedTileLoader.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/CachedTileLoader.java
new file mode 100644
index 0000000..1a40956
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/CachedTileLoader.java
@@ -0,0 +1,10 @@
+// License: GPL
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+/**
+ * Interface that allow cleaning the tile cache without specifying exact type of loader
+ */
+public interface CachedTileLoader {
+    public void clearCache(TileSource source);
+    public void clearCache(TileSource source, TileClearController controller);
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/ICoordinate.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/ICoordinate.java
new file mode 100644
index 0000000..c34e00f
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/ICoordinate.java
@@ -0,0 +1,8 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+public interface ICoordinate {
+    public double getLat();
+    public void setLat(double lat);
+    public double getLon();
+    public void setLon(double lon);
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java
index b33f285..b56032e 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/JMapViewerEventListener.java
@@ -1,18 +1,18 @@
-package org.openstreetmap.gui.jmapviewer.interfaces;
-
-//License: GPL.
-
-import java.util.EventListener;
-
-import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
-
-/**
- * Must be implemented for processing commands while user
- * interacts with map viewer.
- * 
- * @author Jason Huntley
- *
- */
-public interface JMapViewerEventListener extends EventListener {
-	public void processCommand(JMVCommandEvent command);
-}
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+//License: GPL.
+
+import java.util.EventListener;
+
+import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
+
+/**
+ * Must be implemented for processing commands while user
+ * interacts with map viewer.
+ *
+ * @author Jason Huntley
+ *
+ */
+public interface JMapViewerEventListener extends EventListener {
+    public void processCommand(JMVCommandEvent command);
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java
index 4a96a8d..2c1dc34 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java
@@ -5,6 +5,7 @@ package org.openstreetmap.gui.jmapviewer.interfaces;
 import java.awt.Graphics;
 import java.awt.Point;
 
+import org.openstreetmap.gui.jmapviewer.Coordinate;
 import org.openstreetmap.gui.jmapviewer.JMapViewer;
 
 /**
@@ -14,8 +15,14 @@ import org.openstreetmap.gui.jmapviewer.JMapViewer;
  * @see JMapViewer#addMapMarker(MapMarker)
  * @see JMapViewer#getMapMarkerList()
  */
-public interface MapMarker {
+public interface MapMarker extends MapObject, ICoordinate{
 
+    public static enum STYLE {FIXED, VARIABLE};
+
+    /**
+     * @return Latitude and Longitude of the map marker position
+     */
+    public Coordinate getCoordinate();
     /**
      * @return Latitude of the map marker position
      */
@@ -27,11 +34,22 @@ public interface MapMarker {
     public double getLon();
 
     /**
+     * @return Radius of the map marker position
+     */
+    public double getRadius();
+
+    /**
+     * @return Style of the map marker
+     */
+    public STYLE getMarkerStyle();
+
+    /**
      * Paints the map marker on the map. The <code>position</code> specifies the
      * coordinates within <code>g</code>
      *
      * @param g
      * @param position
+     * @param radio
      */
-    public void paint(Graphics g, Point position);
+    public void paint(Graphics g, Point position, int radio);
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapObject.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapObject.java
new file mode 100644
index 0000000..9c0f7fe
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapObject.java
@@ -0,0 +1,22 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Stroke;
+
+import org.openstreetmap.gui.jmapviewer.Layer;
+import org.openstreetmap.gui.jmapviewer.Style;
+
+public interface MapObject {
+
+    public Layer getLayer();
+    public void setLayer(Layer layer);
+    public Style getStyle();
+    public Style getStyleAssigned();
+    public Color getColor();
+    public Color getBackColor();
+    public Stroke getStroke();
+    public Font getFont();
+    public String getName();
+    public boolean isVisible();
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java
index eaece53..aa054de 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapPolygon.java
@@ -1,40 +1,38 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.gui.jmapviewer.interfaces;
-
-import java.awt.Graphics;
-import java.awt.Point;
-import java.awt.Polygon;
-import java.util.List;
-
-import org.openstreetmap.gui.jmapviewer.Coordinate;
-
-/**
- * Interface to be implemented by polygons that can be displayed on the map.
- *
- * @author Vincent
- */
-public interface MapPolygon {
-
-    /**
-     * @return Latitude/Longitude of each point of polygon
-     */
-    public List<Coordinate> getPoints();
-
-    /**
-     * Paints the map rectangle on the map. The <code>points</code> 
-     * are specifying the coordinates within <code>g</code>
-     *
-     * @param g
-     * @param points
-     */
-    public void paint(Graphics g, List<Point> points);
-
-    /**
-     * Paints the map rectangle on the map. The <code>polygon</code> 
-     * is specifying the coordinates within <code>g</code>
-     *
-     * @param g
-     * @param polygon
-     */
-    public void paint(Graphics g, Polygon polygon);
-}
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.util.List;
+
+/**
+ * Interface to be implemented by polygons that can be displayed on the map.
+ *
+ * @author Vincent
+ */
+public interface MapPolygon extends MapObject{
+
+    /**
+     * @return Latitude/Longitude of each point of polygon
+     */
+    public List<? extends ICoordinate> getPoints();
+
+    /**
+     * Paints the map rectangle on the map. The <code>points</code>
+     * are specifying the coordinates within <code>g</code>
+     *
+     * @param g
+     * @param points
+     */
+    public void paint(Graphics g, List<Point> points);
+
+    /**
+     * Paints the map rectangle on the map. The <code>polygon</code>
+     * is specifying the coordinates within <code>g</code>
+     *
+     * @param g
+     * @param polygon
+     */
+    public void paint(Graphics g, Polygon polygon);
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java
index 9b4518f..8e0b942 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java
@@ -15,7 +15,7 @@ import org.openstreetmap.gui.jmapviewer.JMapViewer;
  * @see JMapViewer#addMapRectangle(MapRectangle)
  * @see JMapViewer#getMapRectangleList()
  */
-public interface MapRectangle {
+public interface MapRectangle extends MapObject{
 
     /**
      * @return Latitude/Longitude of top left of rectangle
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileClearController.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileClearController.java
new file mode 100644
index 0000000..3ae88c4
--- /dev/null
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileClearController.java
@@ -0,0 +1,16 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+import java.io.File;
+    
+public interface TileClearController {
+
+    void initClearDir(File dir);
+
+    void initClearFiles(File[] files);
+
+    boolean cancel();
+
+    void fileDeleted(File file);
+
+    void clearFinished();
+}
\ No newline at end of file
diff --git a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java
index da1d8a1..83de8a9 100644
--- a/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/interfaces/TileSource.java
@@ -1,9 +1,7 @@
 package org.openstreetmap.gui.jmapviewer.interfaces;
 
-import java.awt.Image;
 import java.io.IOException;
 
-import org.openstreetmap.gui.jmapviewer.Coordinate;
 import org.openstreetmap.gui.jmapviewer.JMapViewer;
 
 //License: GPL. Copyright 2008 by Jan Peter Stotz
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java
index 997ccbc..2dac34c 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractOsmTileSource.java
@@ -1,23 +1,30 @@
-/**
- * 
- */
 package org.openstreetmap.gui.jmapviewer.tilesources;
 
 import java.awt.Image;
-import java.io.IOException;
-
-import javax.swing.ImageIcon;
 
 import org.openstreetmap.gui.jmapviewer.Coordinate;
-import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 
+/**
+ * Abstract clas for OSM Tile sources
+ */
 public abstract class AbstractOsmTileSource extends AbstractTMSTileSource {
+    
+    /**
+     * The OSM attribution. Must be always in line with <a href="http://www.openstreetmap.org/copyright/en">http://www.openstreetmap.org/copyright/en</a>
+     */
+    public static final String DEFAULT_OSM_ATTRIBUTION = "\u00a9 OpenStreetMap contributors";
+    
+    /**
+     * Constructs a new OSM tile source
+     * @param name Source name as displayed in GUI
+     * @param base_url Source URL
+     */
     public AbstractOsmTileSource(String name, String base_url) {
         super(name, base_url);
     }
 
     public int getMaxZoom() {
-        return 18;
+        return 19;
     }
 
     @Override
@@ -27,7 +34,7 @@ public abstract class AbstractOsmTileSource extends AbstractTMSTileSource {
 
     @Override
     public String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight) {
-        return "\u00a9 OpenStreetMap contributors, CC-BY-SA ";
+        return DEFAULT_OSM_ATTRIBUTION;
     }
 
     @Override
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTileSource.java
index b756751..9c961f5 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTileSource.java
@@ -1,78 +1,78 @@
-package org.openstreetmap.gui.jmapviewer.tilesources;
-
-import java.awt.Image;
-
-import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
-import org.openstreetmap.gui.jmapviewer.Coordinate;
-
-//License: GPL. Copyright 2008 by Jan Peter Stotz
-
-abstract public class AbstractTileSource implements TileSource {
-
-    protected String attributionText;
-    protected String attributionLinkURL;
-    protected Image attributionImage;
-    protected String attributionImageURL;
-    protected String termsOfUseText;
-    protected String termsOfUseURL;
-
-    @Override
-    public boolean requiresAttribution() {
-        return attributionText != null || attributionImage != null || termsOfUseText != null || termsOfUseURL != null;
-    }
-
-    @Override
-    public String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight) {
-        return attributionText;
-    }
-
-    @Override
-    public String getAttributionLinkURL() {
-        return attributionLinkURL;
-    }
-
-    @Override
-    public Image getAttributionImage() {
-        return attributionImage;
-    }
-
-    @Override
-    public String getAttributionImageURL() {
-        return attributionImageURL;
-    }
-
-    @Override
-    public String getTermsOfUseText() {
-        return termsOfUseText;
-    }
-
-    @Override
-    public String getTermsOfUseURL() {
-        return termsOfUseURL;
-    }
-
-    public void setAttributionText(String attributionText) {
-        this.attributionText = attributionText;
-    }
-
-    public void setAttributionLinkURL(String attributionLinkURL) {
-        this.attributionLinkURL = attributionLinkURL;
-    }
-
-    public void setAttributionImage(Image attributionImage) {
-        this.attributionImage = attributionImage;
-    }
-
-    public void setAttributionImageURL(String attributionImageURL) {
-        this.attributionImageURL = attributionImageURL;
-    }
-
-    public void setTermsOfUseText(String termsOfUseText) {
-        this.termsOfUseText = termsOfUseText;
-    }
-
-    public void setTermsOfUseURL(String termsOfUseURL) {
-        this.termsOfUseURL = termsOfUseURL;
-    }
-
-}
+package org.openstreetmap.gui.jmapviewer.tilesources;
+
+import java.awt.Image;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
+import org.openstreetmap.gui.jmapviewer.Coordinate;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+abstract public class AbstractTileSource implements TileSource {
+
+    protected String attributionText;
+    protected String attributionLinkURL;
+    protected Image attributionImage;
+    protected String attributionImageURL;
+    protected String termsOfUseText;
+    protected String termsOfUseURL;
+
+    @Override
+    public boolean requiresAttribution() {
+        return attributionText != null || attributionImage != null || termsOfUseText != null || termsOfUseURL != null;
+    }
+
+    @Override
+    public String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight) {
+        return attributionText;
+    }
+
+    @Override
+    public String getAttributionLinkURL() {
+        return attributionLinkURL;
+    }
+
+    @Override
+    public Image getAttributionImage() {
+        return attributionImage;
+    }
+
+    @Override
+    public String getAttributionImageURL() {
+        return attributionImageURL;
+    }
+
+    @Override
+    public String getTermsOfUseText() {
+        return termsOfUseText;
+    }
+
+    @Override
+    public String getTermsOfUseURL() {
+        return termsOfUseURL;
+    }
+
+    public void setAttributionText(String attributionText) {
+        this.attributionText = attributionText;
+    }
+
+    public void setAttributionLinkURL(String attributionLinkURL) {
+        this.attributionLinkURL = attributionLinkURL;
+    }
+
+    public void setAttributionImage(Image attributionImage) {
+        this.attributionImage = attributionImage;
+    }
+
+    public void setAttributionImageURL(String attributionImageURL) {
+        this.attributionImageURL = attributionImageURL;
+    }
+
+    public void setTermsOfUseText(String termsOfUseText) {
+        this.termsOfUseText = termsOfUseText;
+    }
+
+    public void setTermsOfUseURL(String termsOfUseURL) {
+        this.termsOfUseURL = termsOfUseURL;
+    }
+
+}
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java
index 614fdc0..56c2359 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/MapQuestOsmTileSource.java
@@ -13,6 +13,6 @@ public class MapQuestOsmTileSource extends AbstractMapQuestTileSource {
     @Override
     public String getAttributionText(int zoom, Coordinate topLeft,
             Coordinate botRight) {
-        return super.getAttributionText(zoom, topLeft, botRight)+"- "+MAPQUEST_ATTRIBUTION;
+        return super.getAttributionText(zoom, topLeft, botRight)+" - "+MAPQUEST_ATTRIBUTION;
     }
 }
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
index 4f774d4..be0bc1c 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
@@ -1,10 +1,23 @@
 package org.openstreetmap.gui.jmapviewer.tilesources;
 
+/**
+ * OSM Tile source.
+ */
 public class OsmTileSource {
 
+    /**
+     * The default "Mapnik" OSM tile source URL
+     */
     public static final String MAP_MAPNIK = "http://tile.openstreetmap.org";
 
+    /**
+     * The default "Mapnik" OSM tile source.
+     */
     public static class Mapnik extends AbstractOsmTileSource {
+        
+        /**
+         * Constructs a new {@code "Mapnik"} tile source.
+         */
         public Mapnik() {
             super("Mapnik", MAP_MAPNIK);
         }
@@ -14,6 +27,9 @@ public class OsmTileSource {
         }
     }
 
+    /**
+     * The "Cycle Map" OSM tile source.
+     */
     public static class CycleMap extends AbstractOsmTileSource {
 
         private static final String PATTERN = "http://%s.tile.opencyclemap.org/cycle";
@@ -22,6 +38,9 @@ public class OsmTileSource {
 
         private int SERVER_NUM = 0;
 
+        /**
+         * Constructs a new {@code CycleMap} tile source.
+         */
         public CycleMap() {
             super("OSM Cycle Map", PATTERN);
         }
@@ -35,7 +54,7 @@ public class OsmTileSource {
 
         @Override
         public int getMaxZoom() {
-            return 17;
+            return 18;
         }
 
         public TileUpdate getTileUpdate() {
diff --git a/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java b/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
index 1b184a7..4d20822 100644
--- a/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
+++ b/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
@@ -64,9 +64,9 @@ public class ScanexTileSource extends AbstractTMSTileSource {
         return TileUpdate.IfNoneMatch;
     }
 
-    private static double RADIUS_E = 6378137;	/* radius of Earth at equator, m */
+    private static double RADIUS_E = 6378137;   /* radius of Earth at equator, m */
     private static double EQUATOR = 40075016.68557849; /* equator length, m */
-    private static double E = 0.0818191908426;	/* eccentricity of Earth's ellipsoid */
+    private static double E = 0.0818191908426;  /* eccentricity of Earth's ellipsoid */
 
     @Override
     public double latToTileY(double lat, int zoom) {
@@ -92,21 +92,21 @@ public class ScanexTileSource extends AbstractTMSTileSource {
 
     @Override
     public double tileYToLat(int y, int zoom) {
-	Random r= new Random();
+    Random r= new Random();
         double lat0, lat;
 
-	lat = cached_lat;
-	do {
-	    lat0 = lat;
+    lat = cached_lat;
+    do {
+        lat0 = lat;
             lat = lat - Math.toDegrees(NextTerm(Math.toRadians(lat), y, zoom));
             if (lat > OsmMercator.MAX_LAT || lat < OsmMercator.MIN_LAT) {
                 lat = OsmMercator.MIN_LAT +
                     (double )r.nextInt((int )(OsmMercator.MAX_LAT -
                     OsmMercator.MIN_LAT));
             }
-	} while ((Math.abs(lat0 - lat) > 0.000001));
+    } while ((Math.abs(lat0 - lat) > 0.000001));
 
-	cached_lat = lat;
+    cached_lat = lat;
 
         return (lat);
     }
@@ -115,13 +115,13 @@ public class ScanexTileSource extends AbstractTMSTileSource {
     private double NextTerm(double lat, double y, int zoom) {
         double sinl=Math.sin(lat);
         double cosl=Math.cos(lat);
-	double ec, f, df;
+    double ec, f, df;
 
         zoom = (int )Math.pow(2.0, zoom - 1);
-	ec = Math.exp((1 - y/zoom)*Math.PI);
+    ec = Math.exp((1 - y/zoom)*Math.PI);
 
-	f = (Math.tan(Math.PI/4+lat/2) -
-	    ec * Math.pow(Math.tan(Math.PI/4 + Math.asin(E * sinl)/2), E));
+    f = (Math.tan(Math.PI/4+lat/2) -
+        ec * Math.pow(Math.tan(Math.PI/4 + Math.asin(E * sinl)/2), E));
         df = 1/(1 - sinl) - ec * E * cosl/((1 - E * sinl) *
             (Math.sqrt (1 - E * E * sinl * sinl)));
 

-- 
Java OpenStreetMap Tile Viewer



More information about the Pkg-osm-commits mailing list