# Name :          Layer_manager
# Description :   Create and manage your layers configuration in your SU models
# Author :        Didier Bur
# Usage :         Select Tools/Layer Manager/Option
# All layers visible: unhide all layers
# Invert all layers: layers visible become invisible and vice-versa, except current layer
# Isolate current layer: hide all layers except active layer
# Isolate selection: hide all layers except all layers of selected objects
# Hide selection: hide all layers of selected objects, except current layer
# Save layer configuration: save the current status of all layers. When used the first time, enter a config name, otherwise either select a config name to update an existing config, or enter a new config name to create a new one.
# Load layers configuration: select a config name in the list, SU reads it and switches layers on/off
# Display layers config: select a config name in the list and see the message.
# KNOWN BUG:      SU layers window doesn't reflect changes when loading a config. Help @Last !
# Date :          07.March.2oo5
# Type :          tool
# History:        1.0 (07.March.2oo5) beta version (needs an external SLM file)
#                 1.1 (09.March.2oo5) no more external file, data stored within the SKP
#                 2.0 (24. Nov.2007) filter added
#-----------------------------------------------------------------------------

# Permission to use, copy, modify, and distribute this software for 
# any purpose and without fee is hereby granted, provided that the above
# copyright notice appear in all copies.

# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#-----------------------------------------------------------------------------
# FIXED FOR v2015 TIG 2015.

module DBUR

	#-----------------------------------------------------------------------------------------------------
	#                                        MENU ITEMS
	#-----------------------------------------------------------------------------------------------------

	unless file_loaded?(__FILE__)
	  
	  layers_tb = UI::Toolbar.new("Layer Manager")
	  
	  UI.menu("Tools").add_separator
	  layers_menu = UI.menu("Tools").add_submenu("Layer Manager")
	  
	  # Set layer of current selection as current layer
	  cmd0 = UI::Command.new(("Set layer of selection current")) { (self.lm_set_current) }
	  cmd0.small_icon = "Calques_selection_courant_Small.png"
	  cmd0.large_icon = "Calques_selection_courant_Large.png"
	  cmd0.tooltip = "Set layer of selection current"
	  layers_tb.add_item(cmd0)
	  layers_menu.add_item(cmd0)
	  
	  # move selection to current layer
	  cmd00 = UI::Command.new(("Move selection to current layer")) { (self.lm_selection_to_current) }
	  cmd00.small_icon = "Calques_selection_vers_courant_Small.png"
	  cmd00.large_icon = "Calques_selection_vers_courant_Large.png"
	  cmd00.tooltip = "Move selection to current layer"
	  layers_tb.add_item(cmd00)
	  layers_menu.add_item(cmd00)
	  
	  layers_tb.add_separator
	  
	  #Display layer config
	  cmd1 = UI::Command.new(("Display layers config")) { (self.lm_display_config) }
	  cmd1.small_icon = "Config_calques_afficher_Small.png"
	  cmd1.large_icon = "Config_calques_afficher_Large.png"
	  cmd1.tooltip = "Display layer config"
	  layers_tb.add_item(cmd1)
	  layers_menu.add_item(cmd1)
	  
	  #Save layer config in SKP
	  cmd3 = UI::Command.new(("Save layers config")) { self.lm_save_layers_config_skp }
	  cmd3.small_icon = "Config_calques_enregistrer_Small.png"
	  cmd3.large_icon = "Config_calques_enregistrer_Large.png"
	  cmd3.tooltip = "Save layers config"
	  layers_tb.add_item(cmd3)
	  layers_menu.add_item(cmd3)
	  
	  #Restore layer config from SKP
	  cmd2 = UI::Command.new(("Restore layers config")) { self.lm_load_layers_config_skp }
	  cmd2.small_icon = "Config_calques_charger_Small.png"
	  cmd2.large_icon = "Config_calques_charger_Large.png"
	  cmd2.tooltip = "Restore layers config"
	  layers_tb.add_item(cmd2)
	  layers_menu.add_item(cmd2)
	  
	  #Restore layer config from SKP - Show only
	  cmd21 = UI::Command.new(("Restore layers config - Show only")) { self.lm_load_layers_config_skp_show_only }
	  cmd21.small_icon = "Config_calques_chargerso_Small.png"
	  cmd21.large_icon = "Config_calques_chargerso_Large.png"
	  cmd21.tooltip = "Restore layers config - Show only"
	  layers_tb.add_item(cmd21)
	  layers_menu.add_item(cmd21)
	  
	  #Restore layer config from SKP - Append
	  cmd211 = UI::Command.new(("Restore layers config - Append")) { self.lm_load_layers_config_skp_append }
	  cmd211.small_icon = "Config_calques_chargerap_Small.png"
	  cmd211.large_icon = "Config_calques_chargerap_Large.png"
	  cmd211.tooltip = "Restore layers config - Append"
	  layers_tb.add_item(cmd211)
	  layers_menu.add_item(cmd21)
	  
	  #Save layer config to file
	  cmd31 = UI::Command.new(("Save layers configs to file")) { self.lm_save_layers_config_file }
	  cmd31.small_icon = "Config_calques_enregistrerf_Small.png"
	  cmd31.large_icon = "Config_calques_enregistrerf_Large.png"
	  cmd31.tooltip = "Save layers configs to file"
	  layers_tb.add_item(cmd31)
	  layers_menu.add_item(cmd31)
	  
	  #Restore layer config from file
	  cmd2111 = UI::Command.new(("Restore layers configs from file")) { self.lm_load_layers_config_file }
	  cmd2111.small_icon = "Config_calques_chargerf_Small.png"
	  cmd2111.large_icon = "Config_calques_chargerf_Large.png"
	  cmd2111.tooltip = "Restore layers configs from file"
	  layers_tb.add_item(cmd2111)
	  layers_menu.add_item(cmd2111)
	  
	  #Delete layer config
	  cmd9 = UI::Command.new(("Delete layers config")) { self.lm_delete_layers_config }
	  cmd9.small_icon = "Config_calques_effacer_Small.png"
	  cmd9.large_icon = "Config_calques_effacer_Large.png"
	  cmd9.tooltip = "Delete layers config"
	  layers_tb.add_item(cmd9)
	  layers_menu.add_item(cmd9)
	  
	  layers_tb.add_separator
	  layers_menu.add_separator
	  
	  #All layers visible
	  cmd4 = UI::Command.new(("All layers visible")) { self.lm_all_visible }
	  cmd4.small_icon = "Calques_afficher_tous_Small.png"
	  cmd4.large_icon = "Calques_afficher_tous_Large.png"
	  cmd4.tooltip = "All layers visible"
	  layers_tb.add_item(cmd4)
	  layers_menu.add_item(cmd4)
	  
	  #All layers invisible
	  cmd6 = UI::Command.new(("All layers invisible")) { self.lm_all_invisible }
	  cmd6.small_icon = "Calques_cacher_tous_Small.png"
	  cmd6.large_icon = "Calques_cacher_tous_Large.png"
	  cmd6.tooltip = "All layers invisible (except current)"
	  layers_tb.add_item(cmd6)
	  layers_menu.add_item(cmd6)
	  
	  #Isolate selection
	  cmd5 = UI::Command.new(("Isolate layers of selection")) { self.lm_isolate_selection }
	  cmd5.small_icon = "Calques_isoler_selection_Small.png"
	  cmd5.large_icon = "Calques_isoler_selection_Large.png"
	  cmd5.tooltip = "Isolate layers of selection"
	  layers_tb.add_item(cmd5)
	  layers_menu.add_item(cmd5)
	  
	  #Hide selection
	  cmd7 = UI::Command.new(("Hide layers of selection")) { self.lm_hide_selection }
	  cmd7.small_icon = "Calques_cacher_selection_Small.png"
	  cmd7.large_icon = "Calques_cacher_selection_Large.png"
	  cmd7.tooltip = "Hide layers of selection"
	  layers_tb.add_item(cmd7)
	  layers_menu.add_item(cmd7)
	  
	  #Invert all layers status
	  cmd8 = UI::Command.new(("Invert visibility of all layers")) { self.lm_invert }
	  cmd8.small_icon = "Calques_inverser_Small.png"
	  cmd8.large_icon = "Calques_inverser_Large.png"
	  cmd8.tooltip = "Invert visibility of all layers"
	  layers_tb.add_item(cmd8)
	  layers_menu.add_item(cmd8)
	  
	  layers_tb.add_separator
	  
	  #Isolate using a filter string
	  cmd9 = UI::Command.new(("Isolate layers by filter")) { self.lm_filter("isolate") }
	  cmd9.small_icon = "Calques_isoler_filtre_Small.png"
	  cmd9.large_icon = "Calques_isoler_filtre_Large.png"
	  cmd9.tooltip = "Isolate layers by filter"
	  layers_tb.add_item(cmd9)
	  layers_menu.add_item(cmd9)
	  
	  #Add using a filter string
	  cmd91 = UI::Command.new(("Show layers by filter")) { self.lm_filter("show") }
	  cmd91.small_icon = "Calques_ajouter_filtre_Small.png"
	  cmd91.large_icon = "Calques_ajouter_filtre_Large.png"
	  cmd91.tooltip = "Show layers by filter"
	  layers_tb.add_item(cmd91)
	  layers_menu.add_item(cmd91)
	  
	  #Hide using a filter string
	  cmd10 = UI::Command.new(("Hide layers by filter")) { self.lm_filter("hide") }
	  cmd10.small_icon = "Calques_cacher_filtre_Small.png"
	  cmd10.large_icon = "Calques_cacher_filtre_Large.png"
	  cmd10.tooltip = "Hide layers by filter"
	  layers_tb.add_item(cmd10)
	  layers_menu.add_item(cmd10)
	  
	  layers_tb.restore
	  
	  layers_menu.add_item("Isolate current layer") { self.lm_none_but_current }
	  
	  file_loaded(__FILE__)
	  
	end
	###
	# ----------------------------------------------------- Layers names dialog
	def self.lm_layers_names_dialog(box_title)
		model=Sketchup.active_model
		layers = model.layers
		@lm_filter_string = "" if ! @lm_filter_string
		prompts=["Filter string:                   "]
		values=[@lm_filter_string]
		results = inputbox(prompts, values, box_title)
		return nil if ! results
		@lm_filter_string = results[0]
		return nil if ! results
	end
	# ----------------------------------------------------- Turns all layers visible
	def self.lm_all_visible
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("All layers visible", true)
		layers.each do |lay|
		  lay.visible = true
		end
		model.commit_operation
	end

	# ----------------------------------------------------- Turns all layers invisible
	def self.lm_all_invisible
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("All layers invisible", true)
		layers.each do |lay|
			if lay.visible? && lay.name != model.active_layer.name
			  lay.visible = false
			end
		end
		model.commit_operation
	end

	# ----------------------------------------------------- Turns all layers invisible, except current
	def self.lm_none_but_current
		model=Sketchup.active_model
		layers = model.layers
		current = model.active_layer
		model.start_operation("Isolate current layer", true)
		layers.each do |lay|
		  if lay.name != current
			lay.visible = false
		  end
		end
		model.commit_operation
	end

	# ----------------------------------------------------- Turns all layers of selection visible
	def self.lm_isolate_selection
		model = Sketchup.active_model
		ss = model.selection
		layers = model.layers
		current = model.active_layer
		model.start_operation("Isolate layers of selection", true)
		selection_layers = []
		if ss.empty? 
		  UI.messagebox("No selection. Please select object(s).")
		  return nil
		end
		ss.each do |element|
		  selection_layers.push(element.layer)
		end
		selection_layers.uniq!
		layers.each do |lay|
		  if selection_layers.include?(lay)
			lay.visible = true
		  else
			lay.visible = false if lay.name != current
		  end
		end
		model.commit_operation
	end

	# ----------------------------------------------------- Hides all layers of selection visible
	def self.lm_hide_selection
		model = Sketchup.active_model
		ss = model.selection
		layers = model.layers
		current = model.active_layer
		selection_layers = []
		model.start_operation("Hide layers of selection", true)
		if ss.empty? 
		  UI.messagebox("No selection. Please select object(s)")
		  return nil
		end
		ss.each do |element|
		  selection_layers.push(element.layer)
		end
		selection_layers.uniq!
		layers.each do |lay|
		  if selection_layers.include?(lay)
			lay.visible = false if lay.name != current
		  end
		end
		model.commit_operation
	end

	# ----------------------------------------------------- Invert all layers 
	def self.lm_invert
		model = Sketchup.active_model
		layers = model.layers
		current = model.active_layer
		model.start_operation("Invert all layers status", true)
		layers.each do |lay|
		  if lay.visible? == true && lay.name != current
			lay.visible = false
		  else
			  lay.visible = true
		  end
		end
		model.active_layer = current
		model.active_layer.visible = true
		model.commit_operation
	end

	# ----------------------------------------------------- Displays a config in a message box
	def self.lm_display_config
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("Display layers state", true)
		# Get all the existing lm_configs
		config_list = self.collect_lm_user_config
		@lm_last_used = config_list[0] if ! @lm_last_used
		# Supress the default config
		if config_list.length == 0
		  # No LMAD's in the model
		  UI.messagebox("No layers states saved in this model.")
		  return
		end

		# Dialog
		  dropdown = [config_list.join("|")]
		  prompts=["Display state:           "]
		  #values=[config_list[0]]
		  values=[@lm_last_used]
		  results = inputbox(prompts, values, dropdown, "LM state display")
		  return nil if ! results
		  config_name = results[0]
		  @lm_last_used = results[0]
		  # Get the corresponding LMAD
		  lm_ad = model.attribute_dictionary("lm_" + config_name)
		  current_layer=lm_ad["current"]
		  # Dispatch visible/invisible layers to build report
		  vis=[]
		  invis=[]
		  lm_ad.each_pair do | key, value |
			if value == false
			  invis.push key if key != "current"
			  else
			  vis.push key if key != "current"
			end
		  end
		  vis.sort!
		  invis.sort!
		  # Construct message
		  message = "\n"
		  message = message + "ACTIVE LAYER: " + current_layer + "\n" + ("--" * (current_layer.length+10)) + "\n\n"
		  message = message + "VISIBLE LAYERS:\n------------------------------\n"
		  vis.each do |l|
			  message = message + l + "\n"
		  end
		  message = message + "\nINVISIBLE LAYERS:\n---------------------------------\n"
		  invis.each do |l|
			  message = message + l + "\n"
		  end
		  UI.messagebox(message,MB_MULTILINE, "Layers state: " + config_name)

		model.commit_operation
	end

	# ----------------------------------------------------- Restores the selected config
	def self.lm_restore_config(config)
		model = Sketchup.active_model
		layers = model.layers
		existing_layers = collect_layers_names
		layers_from_config=[]
		layers_from_skp=collect_layers_names

		model.start_operation("Restore layers state", true)
		
		if config != "All layers visible" && config != "Isolate current layer   " && config != "Isolate selection" && config != "" && config != "Invert all layers" && config != "Hide selection" && config != "All layers invisible"
		  # Get the keys and values of this config
		  lm_ad = model.attribute_dictionary("lm_" + config)
		  layers_from_config=lm_ad.keys
		  # Set active layer
		  current_layer=lm_ad["current"]
		  if layers_from_skp.include?(current_layer)
			model.active_layer = lm_ad["current"]
			else
			  rep = UI.messagebox("Active layer of state " + config + " is: " + current_layer + " and doesn't exist in the drawing.\n Create it now ?",MB_YESNO,"Layers creation")
			  if rep == 6
				layers.add(current_layer)
				model.active_layer = current_layer
			  end
		  end
		  # Browse layers, find the corresponding pair key-value and set visibility
		  layers.each do |lay|
			if layers_from_config.include?(lay.name)
			  lay.visible = lm_ad[lay.name]
			end
		  end
		  
		else # default config selected
		
		  if config == "All layers visible"
			self.lm_all_visible
		  end
		  if config == "All layers invisible"
			self.lm_all_invisible
		  end
		  if config == "Invert all layers"
			self.lm_invert
		  end
		  if config == "Isolate current layer   "
			self.lm_none_but_current
		  end
		  if config == "Isolate selection"
			self.lm_isolate_selection
		  end
		  if config == "Hide selection"
			self.lm_hide_selection
		  end
		  if config == ""
			UI.messagebox("Not a valid layers state.")
		  end
		end
		model.commit_operation
	end

	def self.lm_restore_config_show_only(config)
		model = Sketchup.active_model
		layers = model.layers
		existing_layers = collect_layers_names
		layers_from_config=[]
		layers_from_skp=collect_layers_names

		model.start_operation("Restore layers state - Show only", true)
		if config != "All layers visible" && config != "Isolate current layer   " && config != "Isolate selection" && config != "" && config != "Invert all layers" && config != "Hide selection" && config != "All layers invisible"
			# Get the keys and values of this config
			lm_ad = model.attribute_dictionary("lm_" + config)
			layers_from_config=lm_ad.keys

			# Set active layer
			  current_layer=lm_ad["current"]
			  if current_layer && layers_from_skp.include?(current_layer)
				  model.active_layer = lm_ad["current"]
			  else
				  rep = UI.messagebox("Active layer of state " + config + " is: " + current_layer + " and doesn't exist in the drawing.\n Create it now ?",MB_YESNO,"Layers creation")
				  if rep == 6
					layers.add(current_layer)
					model.active_layer = current_layer
				  end
			  end

			# Browse layers, find the corresponding pair key-value and set visibility
			layers.each do |lay|
				if layers_from_config.include?(lay.name) && lm_ad[lay.name] == true
				  lay.visible = true
				else
				  lay.visible = false
				end
			end
	  
		else
		  # default config selected
		  if config == "All layers visible"
			self.lm_all_visible
		  end
		  if config == "All layers invisible"
			self.lm_all_invisible
		  end
		  if config == "Invert all layers"
			self.lm_invert
		  end
		  if config == "Isolate current layer   "
			self.lm_none_but_current
		  end
		  if config == "Isolate selection"
			self.lm_isolate_selection
		  end
		  if config == "Hide selection"
			self.lm_hide_selection
		  end
		  if config == ""
			UI.messagebox("Not a valid layers state.")
		  end
		end
	end


	# ----------------------------------------------------- Restores the selected config, adding visible layers of config to the current visible layers
	def self.lm_restore_config_append(config)
		model = Sketchup.active_model
		layers = model.layers
		existing_layers = collect_layers_names
		layers_from_config=[]
		layers_from_skp=collect_layers_names

		model.start_operation("Restore layers state - Append", true)
		if config != "All layers visible" && config != "Isolate current layer   " && config != "Isolate selection" && config != "" && config != "Invert all layers" && config != "Hide selection" && config != "All layers invisible"
			# Get the keys and values of this config
			lm_ad = model.attribute_dictionary("lm_" + config)
			layers_from_config=lm_ad.keys

			# Set active layer
			  current_layer=lm_ad["current"]
			  if current_layer && layers_from_skp.include?(current_layer)
				  model.active_layer = lm_ad["current"]
			  else
				  rep = UI.messagebox("Active layer of state " + config + " is: " + current_layer + " and doesn't exist in the drawing.\n Create it now ?",MB_YESNO,"Layers creation")
				  if rep == 6
					layers.add(current_layer)
					model.active_layer = current_layer
				  end
			  end

			# Browse layers, find the corresponding pair key-value and set visibility
			layers.each do |lay|
				if layers_from_config.include?(lay.name) && lm_ad[lay.name] == true
				  lay.visible = true
				end
			end
		  
		else
		  # default config selected
		  if config == "All layers visible"
			self.lm_all_visible
		  end
		  if config == "All layers invisible"
			self.lm_all_invisible
		  end
		  if config == "Invert all layers"
			self.lm_invert
		  end
		  if config == "Isolate current layer   "
			self.lm_none_but_current
		  end
		  if config == "Isolate selection"
			self.lm_isolate_selection
		  end
		  if config == "Hide selection"
			self.lm_hide_selection
		  end
		  if config == ""
			UI.messagebox("Not a valid layers state.")
		  end
		end
	end

	# ----------------------------------------------------- Saves or overwrites a lm_config_name key-value = layer-status
	def self.lm_save_layers_config_file
		model=Sketchup.active_model
		layers = model.layers
		@lm_path =  FOLDER
		# Save working dir and set dir to Layer Manager
		current_dir = Dir.getwd
		Dir.chdir @lm_path
		path_file = UI.openpanel( "Select file to save", "." , "*.lmi" )
		lmi_file = File.basename(path_file)
		if ! lmi_file.split(".")[1] || lmi_file.split(".")[1] != "lmi"
		  lmi_file = lmi_file+".lmi"
		end
		out_lmi_file = File.new( @lm_path+lmi_file , "w" )

		# Get all the existing user lm_configs
		config_list = self.collect_lm_user_config

		if config_list.length == 0
		  # No user config
		  UI.messagebox("No layers state to save !")
		  return
		end

		# There's at least one user config in the model
		  config_list.each do |config|
			lm_ad = model.attribute_dictionary("lm_" + config)
			#out_lmi_file.puts "[" + config + "§" + lm_ad["current"] + "]"
			out_lmi_file.puts("[" + config + "]")
			lm_ad.each_pair{ | key, value | out_lmi_file.puts key + "=" + value.to_s}
		  end

		out_lmi_file.close
		UI.messagebox("Layers states saved to " + @lm_path+lmi_file )
		# Reset dir to its original state
		Dir.chdir(current_dir)
	end

	# ----------------------------------------------------- Saves or overwrites a lm_config_name key-value = layer-status
	def self.lm_save_layers_config_skp
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("Save layers state in drawing", true)
		# Get all the existing lm_configs
		config_list = self.collect_lm_user_config
		@lm_last_used = config_list[0] if ! @lm_last_used
		if config_list.length == 0
		  # Give the first config a name
		  prompts=["Layers state name:  "]
		  values=[""]
		  results = inputbox(prompts, values, "LM state saver")
		  return nil if ! results
		  # Creates the LMAD
		  lm_ad = model.attribute_dictionary("lm_" + results[0], true)
		  #Add pairs keys-values: layer-status
		  lm_ad["current"] = model.active_layer.name
		  layers.each do |lay|
			lm_ad[lay.name] = lay.visible?
		  end
		  else
		  # There's at least one LMAD in the model
		  dropdown = [config_list.join("|")]
		  prompts=["Overwrite layers state:  ", "New state:  "]
		  values=[@lm_last_used, ""]
		  results = inputbox(prompts, values, dropdown, "LM state saver")
		  return nil if ! results
		  existing_config = results[0]
		  @lm_last_used = results[0]
		  new_config = results[1]
		  if new_config != "" && ! config_list.include?(new_config)
			# new config
			(lm_write_config new_config)
			UI.messagebox("Layers state " + new_config + " saved.")
		  else
			# Existing config needs overwrite, so first clear it
			self.lm_delete_config existing_config
			# Then write it
			self.lm_write_config existing_config
			UI.messagebox("Layers state " + existing_config + " updated.")
		  end
		end
		model.commit_operation
	end
	# ----------------------------------------------------- Loads a lm_config_name from SKP and restores it
	def self.lm_load_layers_config_skp
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("Load layers state from drawing", true)
		# Get all the existing user lm_configs
		config_list = self.collect_lm_config
		@lm_last_used = collect_lm_config[0] if ! @lm_last_used
		#Dialog
		  dropdown = [config_list.join("|")]
		  prompts=["Layers state to restore:  "]
		  values=[@lm_last_used, ""]
		  results = inputbox(prompts, values, dropdown, "LM state loader")
		  return nil if ! results
		  config = results[0]
		  @lm_last_used = results[0]

		self.lm_restore_config(config)
		model.commit_operation
	end

	# ----------------------------------------------------- Loads a lm_config_name from SKP and restores it - Show only
	def self.lm_load_layers_config_skp_show_only
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("Load layers state from drawing - Show only",true)
		# Get all the existing user lm_configs
		config_list = self.collect_lm_config
		@lm_last_used = collect_lm_config[0] if ! @lm_last_used
		#Dialog
		  dropdown = [config_list.join("|")]
		  prompts=["Layers state to restore:  "]
		  values=[@lm_last_used, ""]
		  results = inputbox(prompts, values, dropdown, "LM state loader")
		  return nil if ! results
		  config = results[0]
		  @lm_last_used = results[0]

		self.lm_restore_config_show_only(config)
		model.commit_operation
	end

	# ----------------------------------------------------- Loads a lm_config_name from SKP and restores it - Append
	def self.lm_load_layers_config_skp_append
		model=Sketchup.active_model
		layers = model.layers
		model.start_operation("Load layers state from drawing - Append", true)
		# Get all the existing user lm_configs
		config_list = self.collect_lm_config
		@lm_last_used = collect_lm_config[0] if ! @lm_last_used
		#Dialog
		  dropdown = [config_list.join("|")]
		  prompts=["Layers state to append:  "]
		  values=[@lm_last_used, ""]
		  results = inputbox(prompts, values, dropdown, "LM state loader")
		  return nil if ! results
		  config = results[0]
		  @lm_last_used = results[0]

		self.lm_restore_config_append(config)
		model.commit_operation
	end

	# ----------------------------------------------------- Loads a lm_config_name from file and restores it
	def self.lm_load_layers_config_file
		model=Sketchup.active_model
		layers = model.layers
		# In current SKP
		configs_skp=self.collect_lm_config
		layers_skp=self.collect_layers_names
		# In LMI file
		file_sections=[]
		cfgs=[]
		configs_from_file=[]
		configs_array=[]
		layers_from_file=[]
		# Select file to load
		@lm_path = FOLDER
		# Save working dir and set dir to Layer Manager
		current_dir=Dir.getwd
		Dir.chdi(@lm_path)
		path_file = UI.openpanel( "Select file to load", "." , "*.lmi" )
		lmi_file = File.basename(path_file)
		# Read LMI file
		configs_array=IO.readlines(@lm_path+lmi_file)
		#@configs_array.pop
		current_cfg=[]
		configs_array.each do|line|
		  if line["["]
			file_sections.push(line.chomp.gsub("[","").gsub("]",""))
			if line != configs_array[0]
			  configs_from_file.push(current_cfg)
			end
			current_cfg=[]
			current_cfg.push(line.chomp.gsub("[","").gsub("]",""))
		  else
			current_cfg.push(line.chomp)
			if line == configs_array[configs_array.length-1]
			  configs_from_file.push(current_cfg)
			end
		  end
		end
		# Duplicate configs array
		cfgs=configs_from_file
		# Builds layers array from file
		configs_from_file.each do |cfg|
		  cfg.shift
		  cfg.each do |lay|
			  layers_from_file.push(lay.split("=")[0]) if lay.split("=")[0] != "current"
			  layers_from_file.push(lay.split("=")[1]) if lay.split("=")[0] == "current"
		  end
		end
		layers_from_file.uniq!

		# Compare configs in file with configs in drawing
		exist_configs=false
		file_sections.each do |cfg|
		  if configs_skp.include?(cfg)
			exist_configs=true
		  end
		end
		cfg_rep = 7
		if exist_configs
		  cfg_rep = UI.messagebox("Imported file contains states that are already present in your drawing.\nOverwrite existing states ?",MB_YESNO,"States update")
		end

		# Compare layers in file with layers in drawing
		not_exist_layers=false
		layers_from_file.each do |l|
		  if ! layers_skp.include?(l)
			not_exist_layers=true
		  end
		end
		lm_rep = 7
		if not_exist_layers
		  lm_rep = UI.messagebox("States file contains layers that are not present in your drawing.\nCreate them now ?",MB_YESNO,"Layers creation")
		end
		if lm_rep == 6
		  layers_from_file.each do |l|
			if ! layers_skp.include?(l)
			  #Create layer
			  layers.add(l)
			end
		  end
		end

		i=0
		file_sections.each do |cfg_name|
		  # create config with LMAD if needed: don't overwrite configs with same name !
		  if ! configs_skp.include?(cfg_name)
			# New config to create
			lm_ad = model.attribute_dictionary("lm_" + cfg_name, true)
			# Add pairs keys-values: layer-status
			cfg=cfgs[i]
			cfg.each do |entry|
			  if entry.split("=")[0] != "current"
				lm_ad[entry.split("=")[0]] = eval(entry.split("=")[1]) #if entry.split("=")[0] != "current"
			  else
				lm_ad["current"] = entry.split("=")[1]
			  end
			end
			else
			# Existing config: overwrite or not ?
			if cfg_rep == 6
			  #overwrite
			  self.lm_delete_config(cfg_name)
			  # Re-create config
			  lm_ad = model.attribute_dictionary("lm_" + cfg_name, true)
			  # Add pairs keys-values: layer-status
			  cfg=cfgs[i]
			  cfg.each do |entry|
				  if entry.split("=")[0] != "current"
					  lm_ad[entry.split("=")[0]] = eval(entry.split("=")[1]) #if entry.split("=")[0] != "current"
				  else
					  lm_ad["current"] = entry.split("=")[1]
				  end
			  end
			end
		  end
		  i=i+1
		end
		# Reset working dir to its original state
		Dir.chdir(current_dir)
	end

	# ----------------------------------------------------- Delete existing configs
	def self.lm_delete_layers_config
		model=Sketchup.active_model
		model.start_operation("Delete layers state", true)
		ads=model.attribute_dictionaries
		# Get all the existing lm_configs
		config_list = self.collect_lm_user_config
		config_list.push("")
		config_list.push("All")
		@lm_last_used = config_list[0] if ! @lm_last_used
		if config_list.length == 0
		  # No LMAD's in the model
		  UI.messagebox("No layers states saved in this model.")
		  return
		end

		# Dialog
		dropdown = [config_list.join("|")]
		prompts=["Delete state(s):           "]
		values=[@lm_last_used]
		results = inputbox(prompts, values, dropdown, "LM state delete")
		return nil if ! results
		config_name = results[0]

		if config_name == ""
		  UI.messagebox("Not a valid layers state.")
		  return
		end
		if config_name != "" && config_name != "All"
		  # Delete the corresponding LMAD
		  ads.delete("lm_" + config_name)
		  UI.messagebox("Layers state " + config_name + " deleted.")
		  if config_list.length > 1
			@lm_last_used = config_list[1]
		  else
			@lm_last_used = ""
		  end
		else
		  # All selected
		  rep = UI.messagebox("Are you sure to delete all layers states ?",MB_YESNO,"LM delete")
		  if rep == 6
			  # Delete all
			  config_list.pop
			  config_list.pop
			  config_list.each do |cfg|
				lm_delete_config(cfg)
		      end
		  end
		end
		model.commit_operation
	end

	# ----------------------------------------------------- List existing configs in AD's
	def self.collect_lm_config
		model=Sketchup.active_model
		ad = model.attribute_dictionaries
		config_array = []
		# Adds the default configs
		config_array.push("All layers visible")
		config_array.push("All layers invisible" )
		config_array.push("Isolate current layer   ")
		config_array.push("Isolate selection")
		config_array.push("Hide selection")
		config_array.push("Invert all layers")
		config_array.push("")
		# Browse Ad's to find LMAD's
		if ad != nil
		  # At least an AD in the model
		  ad.each do |dict|
			if dict.name["lm_"]
			  config_array.push(dict.name.split("lm_")[1])
			end
		  end
		end
		config_array.sort
		return config_array
	end

	# ----------------------------------------------------- List existing configs in AD's
	def self.collect_lm_user_config
		model=Sketchup.active_model
		ad = model.attribute_dictionaries
		config_array = []
		# Browse Ad's to find LMAD's
		if ad != nil
		  # At least an AD in the model
		  ad.each do |dict|
			if dict.name["lm_"]
			  config_array.push(dict.name.split("lm_")[1])
			end
		  end
		end
		config_array.sort
		return config_array
	end

	def self.collect_layers_names
		model=Sketchup.active_model
		layers = model.layers
		layers_array=[]
		layers.each {|l| layers_array.push(l.name) }
		layers_array
	end

	# ----------------------------------------------------- Writes a lm_config_name key-value = layer-status
	def self.lm_write_config( config_name )
		model=Sketchup.active_model
		layers = model.layers
		# Creates the LMAD if needed
		lm_ad = model.attribute_dictionary("lm_" + config_name, true)
		# Add pairs keys-values: layer-status
		lm_ad["current"] = model.active_layer.name
		layers.each do |lay|
			lm_ad[lay.name] = lay.visible?
		end
	end

	# ----------------------------------------------------- Deletes all pairs key-value of a lm_config_name
	def self.lm_clear_config( config_name )
		model=Sketchup.active_model
		layers = model.layers
		# Get the LMAD
		lm_ad = model.attribute_dictionary("lm_" + config_name)
		#Add pairs keys-values: layer-status
		lm_ad.each_pair{|k, v| 
			lm_ad.delete_key(k)
		}
	end

	# ----------------------------------------------------- Deletes a lm_config_name
	def self.lm_delete_config( config_name )
	    model=Sketchup.active_model
	    model_dicts = model.attribute_dictionaries
	    lm_ad = model.attribute_dictionary("lm_" + config_name)
	    model_dicts.delete(lm_ad)
	end

	# ----------------------------------------------------- Filter layers wether * or ?
	def self.lm_filter(action)
		model=Sketchup.active_model
		lm_layers_names_dialog(action.capitalize + " layers")
		if ! @lm_filter_string["*"] && ! @lm_filter_string["?"]
		  UI.messagebox(@lm_filter_string + ": no wildcards in this " +  action + " filter !")
		  return
		end
		self.lm_filters(action)
	end

	def self.lm_filters(action)
		model=Sketchup.active_model
		model.start_operation(action.capitalize + " layers", true)

		# Hi TIG ! I was not familiar at all with Regexp,
		# so I had to spend several hours finding docs over the Net
		# and figure out how to build the right Regexp that will do the trick.
		# It turned out to be quite simple in fact...

		a=@lm_filter_string.gsub("*",".*")
		b=a.gsub("?",".")
		reg=Regexp.new(b)

		layers = model.layers
		layers.each do |layer|
		  name = layer.name
		  case action
			when "isolate"
			  if name.scan(reg)[0]==name
				layer.visible = true
			  else
				layer.visible = false if layer != model.active_layer
			  end
			when "show"
			  if name.scan(reg)[0]==name
				layer.visible = true
			  end
			when "hide"
			  if name.scan(reg)[0]==name
				layer.visible = false if layer != model.active_layer
			  end
		  end
		end
		model.commit_operation
	end

	def self.lm_set_current
		model=Sketchup.active_model
		model.start_operation("Set selection layer current", true)
		s=model.selection
		if s.empty?
		  UI.messagebox("No selection. Please select an object.")
		  return
		end
		case s.length
		  when 1
			model.active_layer=s[0].layer
		  else
			UI.messagebox(s.length.to_s + " object selected.\nPlease select only one object.")
		end
	end

	def self.lm_selection_to_current
		model = Sketchup.active_model
		model.start_operation("Put selection to current layer", true)
		sel=model.selection
		if sel.empty?
		  UI.messagebox("No selection. Please select object(s).")
		  return
		end
		sel.each do |obj|
		  obj.layer=model.active_layer if obj.layer != model.active_layer
		end
		model.commit_operation
	end

end#module
