=begin
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
# Designed October 2012 by Fredo6

# Permission to use this software for any purpose and without fee is hereby granted
# Distribution of this software for commercial purpose is subject to:
#  - the expressed, written consent of the author
#  - the inclusion of the present copyright notice 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.
#-----------------------------------------------------------------------------
# Name			:   TopoShaper_Tool.rb
# Original Date	:   20 Oct 12 - version 1.0
# Description	:   TopoShaper Interactive Tool
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
=end

module F6_TopoShaper

T6[:TXT_InCurrentUnits] = "in Model Units"
T6[:TIT_AltitudeReference] = "Reference Altitude"
T6[:TIP_AltitudeReference] = "Real-field Altitude for which Z elevation is ZERO in Sketchup"
T6[:TIT_AltitudeIncrement] = "Altitude Increment"
T6[:TIP_AltitudeIncrement] = "Increment of altitude (typically between 2 adjacent contours)"
T6[:TIP_AltitudeMoveDown] = "Decrement altitude buttons (toward lower altitudes)"
T6[:TIP_AltitudeMoveUp] = "Increment altitude buttons (toward higher altitudes)"
T6[:TIP_AltitudeSenseDown] = "Automatically Decrement altitude at each contour assignment"
T6[:TIP_AltitudeSenseUp] = "Automatically Increment altitude at each contour assignment"
T6[:TIP_AltitudeCurrentSet] = "Click to set Current Altitude to value"
T6[:TIP_AltitudeCurrent] = "Current Altitude for assignment to contours"

T6[:BOX_PictureMap] = "Back Map"
T6[:TIP_PictureMap] = "Picture to serve as a background map for altitude edition"
T6[:TIP_PictureMapSelect] = "Choose a picture file for the background map"
T6[:TIP_PictureMapMatch] = "Adjust the background map to the terrain map"
T6[:TIP_PictureMapToggle] = "Toggle visibility of the picture map"

T6[:TIT_PictureMatch] = "Back Map matching"
T6[:BOX_PictureMatchMove] = "Move"
T6[:BOX_PictureMatchAdjust] = "Adjust"
T6[:BOX_PictureMatchExit] = "Exit"
T6[:TIP_PictureMatchMove] = "Translate the picture by matching 2 points"
T6[:TIP_PictureMatchAdjust] = "Scale and Rotate the picture by matching 2 points"
T6[:TIP_PictureMatchExit] = "Exit the Matching mode"

#=============================================================================================
#=============================================================================================
# Class TopoShaperTool: main class for the Interactive tool
#=============================================================================================
#=============================================================================================

class TopoShaperTool < Traductor::PaletteSuperTool

#--------------------------------------------------------------
#--------------------------------------------------------------
# Palette Management
#--------------------------------------------------------------
#--------------------------------------------------------------

#--------------------------------------------------
# Callback methods from palette
#--------------------------------------------------

#Notification method from palette for Back and Exec buttons
def notify_from_palette(action, code)
	case action
	when :tip
		compute_tooltip_for_palette code
	when :gray	
		compute_gray_for_palette code
	when :exec
		execute_from_palette code
	end	
end

#Tooltip for Back and Execute buttons
def compute_tooltip_for_palette(code)
	case code
	when :validate
		case @mode
		when :selection
			@mnu_validate_selection
		when :cleansing
			@mnu_validate_cleansing
		when :algo
			@mnu_validate_algo
		end	
	when :back
		case @mode
		when :cleansing
			@tip_rollback_to_selection
		when :algo
			@tip_rollback_to_cleansing
		when :geometry
			@tip_rollback_to_algo
		end	
	when :next_curve
		@tip_next_curve
	when :grid_nx_ny
		sl = @algo.grid_max_dimensions + @algo.grid_max_dimensions_delta.collect { |a| Sketchup.format_length a }
		T6[:TIP_GridLimits, *sl]
	when :grid_lx_ly
		sl = @algo.grid_current_delta.collect { |a| Sketchup.format_length a }
		T6[:TIP_GridLengthEquiv, *sl]
	else
		""
	end
end

#Gray status for Back and Execute buttons
def compute_gray_for_palette(code)
	case code
	when :validate
		!validate_allowed?		
	when :back
		!rollback_allowed?
	when :next_curve
		!validate_current_allowed?
	end	
end

#Execution for Back and Execute buttons
def execute_from_palette(code)
	case code
	when :validate
		execute_validate
	when :back
		rollback_execute
	when :next_curve
		validate_current_execute
	end	
end

#---------------------------------------------------------------------
# Creation of the palette
#---------------------------------------------------------------------

#PALETTE: Separator for the Main and floating palette
def pal_separator ;	@palette.declare_separator ; end

#PALETTE: Initialize the main palette and top level method
def init_palette
	hshpal = { :width_message => 350, :width_message_min => 150, :key_registry => :toposhaper }
	@palette = Traductor::Palette.new hshpal
	notify_proc = self.method 'notify_from_palette'
	@draw_local = self.method "draw_button_opengl"
	@blason_proc = self.method "draw_button_blason"
	@symb_blason = :blason
	@bk_color_tool = "lemonchiffon"
	@info_text1 = ""
	@info_text2 = ""
	@info_message = ""
		
	#Blason Button
	tip = "TopoShaper" + ' ' + T6[:T_STR_DefaultParamDialog]
	hsh = { :blason => true, :draw_proc => @blason_proc, :tooltip => tip }
	@palette.declare_button(@symb_blason, hsh) { MYPLUGIN.invoke_default_parameter_dialog }

	#Step Label
	palette_step_label
	
	#Modifiers for Selection mode
	@palette.set_current_family :selection
	pal_separator
	@selmode.contribute_palette @palette, 'MHE' if @selmode
	
	#Preview mode
	@palette.set_current_family :cleansing, :algo
	palette_preview_mode

	#Option for picture map
	@palette.set_current_family :cleansing
	palette_picture_map
	
	#Option for calculation of terrain
	@palette.set_current_family :algo
	palette_grid
	palette_hilltop

	#Option for generation of terrain
	@palette.set_current_family :geometry
	palette_option_geometry	
	
	#Abort and Exit
	@palette.set_current_family
	pal_separator
	hidden_proc = proc { @mode == :cleansing && @saved_contours }
	hsh = { :hidden_proc => hidden_proc, :draw_proc => :std_abortexit, :main_color => 'red', :frame_color => 'green', 
	        :tooltip => T6[:T_STR_AbortTool] }
	@palette.declare_button(:pal_abort, hsh) { abort_tool }

	#Rollback
	@palette.set_current_family :cleansing, :algo, :geometry
	ssb = :back
	tip_proc = proc { notify_proc.call :tip, ssb }
	hidden_proc = proc { notify_proc.call :gray, ssb }
	hsh = { :tip_proc => tip_proc, :draw_proc => :rollback, :hidden_proc => hidden_proc }
	@palette.declare_button(:pal_back, hsh) { notify_proc.call :exec, ssb }
	
	#Exit tool
	@palette.set_current_family
	hidden_proc = proc { @mode != :geometry && (@mode != :cleansing || !@saved_contours) }
	hsh = { :hidden_proc => hidden_proc, :draw_proc => :std_exit, :tooltip => T6[:T_STR_ExitTool] }
	@palette.declare_button(:pal_exit, hsh) { exit_tool }
		
	#Execute (or Save options for Cleanser-only mode)
	palette_validate unless @action_code == :cleanser
	palette_cleanser_altitude
	palette_cleanser_save

	#Special button for selection	
	@palette.set_current_family :selection
	ssvc = :next_curve
	tip_proc = proc { notify_proc.call :tip, ssvc }
	grayed_proc = proc { notify_proc.call :gray, ssvc }
	hsh = { :tip_proc => tip_proc, :draw_proc => :next_curve, :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_next_curve, hsh) { notify_proc.call :exec, ssvc}
		
	#Additional options
	palette_options_debug
	
	#Creating the floating palettes
	palette_floating_cleansing
	palette_floating_altitude
	palette_floating_picture_match
	palette_floating_algo
	
	#Associating the palette
	set_palette @palette
end

#PALETTE: Buttons for grid dimensions
def palette_options_debug
	return unless MYDEFPARAM[:TPS_OPTION_Debug]
	@palette.set_current_family :algo
	pal_separator
	
	value_proc = proc { @hsh_options_global[:debug_zone] }
	hsh = { :value_proc => value_proc, :draw_proc => @draw_local, :tooltip => T6[:TIP_DebugOption] }
	@palette.declare_button(:pal_debug_zone, hsh) { @hsh_options_global[:debug_zone] = !@hsh_options_global[:debug_zone] }
end

#PALETTE: Buttons for grid dimensions
def palette_step_label
	@palette.set_current_family
	wid = 0
	[:BOX_Mode_selection, :BOX_Mode_cleansing, :BOX_Mode_algo, :BOX_Mode_geometry].each do |symb|
		text = T6[symb]
		w, = G6.text_size text
		wid = w if w > wid
	end
	text_proc = proc { @mode_text }
	tip_proc = proc { @mode_tip }
	hsh = { :passive => true, :width => wid + 20, :height => 32, :draw_proc => @draw_local, :justif => 'MH', :text_proc => text_proc, :tip_proc => tip_proc }
	@palette.declare_button(:pal_step, hsh)
end

#PALETTE: Buttons for grid dimensions
def palette_cleanser_save
	@palette.set_current_family :cleansing

	txt_save_replace = T6[:BOX_SaveReplace].sub(/\s*&\s*/, "\n& ")
	txt_save_copy = T6[:BOX_SaveCopy].sub(/\s*&\s*/, "\n& ")
	w1, = G6.text_size(txt_save_replace)
	w2, = G6.text_size(txt_save_copy)
	w = [w1, w2].max + 70
	hshb = { :width => w, :height => 32, :justif => 'MH', :bk_color => 'plum', :draw_proc => :std_disk }
	
	hidden_proc = proc { @selmode.empty? }
	hsh = { :hidden_proc => hidden_proc, :text => txt_save_replace, :tooltip => T6[:TIP_SaveReplace] }
	@palette.declare_button(:pal_cleanser_update, hshb, hsh) { save_replace_contours }
end

#PALETTE: Buttons for grid dimensions
def palette_cleanser_altitude
	@palette.set_current_family :cleansing

	ltxt = T6[:BOX_AltitudeEdit].split "|"
	w1, = G6.text_size(ltxt[0])
	w2, = G6.text_size(ltxt[1])
	w = [w1, w2].max + 45
	txt = ltxt[0] + "\n" + ltxt[1]
	hshb = { :width => w, :height => 32, :justif => 'MH', :bk_color => 'lightblue', :draw_proc => @draw_local }
	
	hidden_proc = proc { @selmode.empty? }
	value_proc = proc { @cleanser.editing_altitude? }
	hsh = { :value_proc => value_proc, :hidden_proc => hidden_proc, :text => txt, :tooltip => T6[:TIP_AltitudeEdit] }
	@palette.declare_button(:pal_cleanser_altitude, hshb, hsh) { @cleanser.altitude_edition_toggle }
end

#PALETTE: Buttons for grid dimensions
def palette_grid
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_grid_sepa0, hsh
	
	notify_proc = self.method 'notify_from_palette'
	symb_master = :pal_grid
	text = T6[:BOX_Grid_Title]
	wid, = G6.simple_text_size(text)
	wid = [80, wid].max
	tip_proc = proc { notify_proc.call :tip, :grid_nx_ny }
	
	hsh = { :type => 'multi_free', :passive => true, :text => text, :tip_proc => tip_proc,
	        :height => 16, :bk_color => 'lightblue' }
	@palette.declare_button(symb_master, hsh)
	
	tip_proc = proc { notify_proc.call :tip, :grid_lx_ly }
	text_proc = proc { @algo.text_grid_dimension }
	hsh = { :parent => symb_master, :text_proc => text_proc, :width => wid, :tip_proc => tip_proc,
	        :bk_color => 'lightgreen' }
	@palette.declare_button(:pal_grid_nx_ny, hsh) { ask_grid_dimension }		
end

#PALETTE: Buttons for Preview mode
def palette_preview_mode
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_preview_mode_sepa0, hsh

	symb_master = :pal_preview_mode

	hsh = { :type => 'multi_free', :passive => true, :text => T6[:BOX_WorkingView], :bk_color => 'lightblue',
	        :height => 16, :tooltip => T6[:TIP_WorkingView] }
	@palette.declare_button(symb_master, hsh) 

	hshp = { :parent => symb_master, :draw_proc => @draw_local }

	wid = 28	
	value_proc = proc { @mode == :algo && !working_view_active? }
	hsh = { :width => wid, :value_proc => value_proc, :text => "SU", :tooltip => T6[:TIP_PreviewMode_InSitu] }
	@palette.declare_button(:pal_preview_mode_insitu, hshp, hsh) { set_preview_in_situ }	

	hsh = { :parent => symb_master, :passive => true, :draw_proc => :separator_V, :width => 12 }	
	@palette.declare_button :pal_preview_mode_sepa1, hsh
	
	hsh = { :width => wid, :tooltip => T6[:TIP_PreviewMode_Surface] }
	@palette.declare_button(:pal_preview_mode_surface, hshp, hsh) { set_preview_working :surface }	

	hsh = { :width => wid, :tooltip => T6[:TIP_PreviewMode_Map] }
	@palette.declare_button(:pal_preview_mode_map, hshp, hsh) { set_preview_working :map }	

	hsh = { :width => wid, :tooltip => T6[:TIP_PreviewMode_SurfaceMap] }
	@palette.declare_button(:pal_preview_mode_surface_map, hshp, hsh) { set_preview_working :surface_map }	
end

#PALETTE: Buttons for hilltop mode
def palette_hilltop
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_hilltop_sepa0, hsh

	txbox = T6[:BOX_Hilltop]
	w, = G6.simple_text_size txbox
	w = [w, 70].max + 8
	
	symb_master = :pal_hilltop
	
	value_proc = proc { @algo && @algo.option_hilltop? }
	hsh = { :type => 'multi', :radio => 'true', :passive => true, :text => txbox, :bk_color => 'lightblue',
	        :height => 16, :default_value => :auto, :tooltip => T6[:TIP_HilltopMain], :value_proc => value_proc }
	@palette.declare_button(symb_master, hsh) { @algo.option_change_hilltop @palette.button_get_value }

	wid = w * 0.5	
	hshp = { :parent => symb_master, :draw_proc => @draw_local, :width => wid }

	hsh = { :value => :flat, :tooltip => T6[:TIP_HilltopFlatAll] }
	@palette.declare_button(:pal_hilltop_flat, hshp, hsh)

	hsh = { :value => :auto, :tooltip => T6[:TIP_HilltopAutoAll] }
	@palette.declare_button(:pal_hilltop_auto, hshp, hsh)	
end

#PALETTE: Buttons for hilltop mode
def palette_option_geometry
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_geometry_sepa0, hsh

	txbox = T6[:BOX_OptionGeometry]
	wtot, = G6.simple_text_size(txbox)
	wtot += 40
	
	symb_master = :pal_option_geometry
	
	hsh = { :type => 'multi_free', :passive => true, :text => txbox, :bk_color => 'lightblue',
	        :height => 16, :width => wtot, :tooltip => T6[:TIP_OptionGeometry] }
	@palette.declare_button(symb_master, hsh)

	wid = [wtot / 3, 45].max
	hshp = { :parent => symb_master, :draw_proc => @draw_local, :width => wid }

	value_proc = proc { @hsh_options_global[:geometry_wall] }
	hsh = { :tooltip => T6[:TIP_OptionGeometryWall], :value_proc => value_proc }
	@palette.declare_button(:pal_option_geometry_wall, hshp, hsh) { @algo.geometry_option_wall_toggle }

	value_proc = proc { @hsh_options_global[:geometry_contour] }
	hsh = { :tooltip => T6[:TIP_OptionGeometryContour], :value_proc => value_proc }
	@palette.declare_button(:pal_option_geometry_contour, hshp, hsh) { @algo.geometry_option_contour_toggle }

	value_proc = proc { @hsh_options_global[:geometry_map] }
	hsh = { :tooltip => T6[:TIP_OptionGeometryMap], :value_proc => value_proc }
	@palette.declare_button(:pal_option_geometry_map, hshp, hsh) { @algo.geometry_option_map_toggle }
	
	#Label palettes
	palette_contour_map_position
	palette_contour_map_label
end

#PALETTE: options related to the altitude labels
def palette_contour_map_position
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_geometry_label_sepa1, hsh

	txbox = T6[:BOX_MapPosition]
	wtot, = G6.simple_text_size(txbox)
	wtot += 10
	
	symb_master = :pal_map_position
	
	hsh = { :type => 'multi_free', :passive => true, :text => txbox, :bk_color => 'lightblue',
	        :height => 16, :width => wtot, :tooltip => T6[:TIP_MapPosition] }
	@palette.declare_button(symb_master, hsh)

	wid = [wtot / 2, 40].max
	hshp = { :parent => symb_master, :draw_proc => @draw_local, :width => wid }

	value_proc = proc { !registry_info_get[:geometry_map_top] }
	hsh = { :tooltip => T6[:TIP_MapPositionBottom], :value_proc => value_proc }
	@palette.declare_button(:pal_map_position_bottom, hshp, hsh) { @algo.geometry_option_map_position_toggle }

	value_proc = proc { registry_info_get[:geometry_map_top] }
	hsh = { :tooltip => T6[:TIP_MapPositionTop], :value_proc => value_proc }
	@palette.declare_button(:pal_map_position_top, hshp, hsh) { @algo.geometry_option_map_position_toggle }
end

#PALETTE: options related to the altitude labels
def palette_contour_map_label
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_geometry_label_sepa2, hsh

	txbox = T6[:BOX_AltitudeLabel]
	wtot, = G6.simple_text_size(txbox)
	wtot += 10
	
	#Title button
	symb_master = :pal_label	
	value_proc = proc { registry_info_get[:geometry_label] }
	hsh = { :type => 'multi_free', :text => txbox, :bk_color => 'lightblue', :value_proc => value_proc,
	        :height => 16, :tooltip => T6[:TIP_AltitudeLabel], :hi_color => 'yellow' }
	@palette.declare_button(symb_master, hsh) { @algo.geometry_option_label_toggle }

	hshp = { :parent => symb_master }
	
	#Factor for size
	wid = 70
	tip = T6[:TIP_AltitudeLabelFactor]
	prompt = tip
	symb = "#{symb_master}_factor".intern
	hshi = { :vtype => :percent, :vprompt => prompt, :vmin => 0.3, :vmax => 2.0, :vincr => 0.2, :vsprintf => '%d%' }
	get_proc = proc { (@algo) ? @algo.geometry_option_label_size_get : 1.0 }
	set_proc = proc { |val| @algo.geometry_option_label_size_set val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	hsh = { :input => input, :width => wid, :tooltip => tip, :bk_color => 'lightgreen' }
	@palette.declare_button symb, hshp, hsh 	
	
	#Separator
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 16 }	
	@palette.declare_button :pal_geometry_label_sepa4, hshp, hsh

	#No Filtering button
	symb = "#{symb_master}_filter_on".intern
	txbox = T6[:BOX_AltitudeLabelNoFilter]
	w, = G6.simple_text_size(txbox)
	value_proc = proc { !registry_info_get[:geometry_label_filter_on] }
	hsh = { :text => txbox, :bk_color => 'lightblue', :value_proc => value_proc,
	        :width => w+8, :height => 16, :tooltip => T6[:TIP_AltitudeLabelNoFilter], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshp, hsh) { @algo.geometry_option_label_filter_toggle }
	
	#Filtering
	wid = 100
	tip = T6[:TIP_AltitudeLabelFilter]
	prompt = T6[:PROMPT_AltitudeLabelFilter]
	symb = "#{symb_master}_filter".intern
	hshi = { :vtype => :len, :vprompt => prompt }
	get_proc = proc { (@algo) ? @algo.geometry_option_label_filter_get : 1.0 }
	set_proc = proc { |val| @algo.geometry_option_label_filter_set val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	hsh = { :input => input, :width => wid, :tooltip => tip, :bk_color => 'lightgreen' }
	@palette.declare_button symb, hshp, hsh 	
		
end

#PALETTE: Button for validation
def palette_validate
	notify_proc = self.method 'notify_from_palette'

	color = Sketchup::Color.new 197, 247, 214
	ssv = :validate
	tip_proc = proc { notify_proc.call :tip, ssv }
	grayed_proc = proc { notify_proc.call :gray, ssv }
	hshc = { :draw_proc => :valid, :height => 32, :hidden_proc => grayed_proc,
             :bk_color => color	}
	
	#Creating the Validate buttons
	[:selection, :cleansing, :algo].each do |symb|
		t6symb = "BOX_Validate_#{symb}".intern
		tipsymb = "TIP_Validate_#{symb}".intern
		palsymb = "pal_#{t6symb}".intern
		lt = T6[t6symb].split '|'
		text = lt[0].strip
		text += "\n" + lt[1].strip if lt[1]
		w, = G6.text_size(text)
		w += 60
		hsh = { :text => text, :width => w, :tooltip => T6[tipsymb] }
		@palette.set_current_family symb	
		pal_separator
		@palette.declare_button(palsymb, hshc, hsh) { notify_proc.call :exec, ssv }
	end
end

#PALETTE: Notify the main tool about changes from cleanser
def notify_cleanser_ui(code)
	@cleanser.notify_contour_set code
	onMouseMove_zero
end

#PALETTE: Handle picture map
def palette_picture_map
	pal_separator

	title = T6[:BOX_PictureMap]
	w, = G6.simple_text_size title
	wid = w / 3 + 10

	hsh = { :passive => true, :draw_proc => :separator_V, :width => 12, :height => 32 }	
	@palette.declare_button :pal_preview_mode_sepa7, hsh

	symb_master = :pal_picture_map

	hsh = { :type => 'multi_free', :passive => true, :text => T6[:BOX_PictureMap], :bk_color => 'lightblue',
	        :height => 16, :tooltip => T6[:TIP_PictureMap] }
	@palette.declare_button(symb_master, hsh) 

	hshp = { :parent => symb_master, :width => wid, :draw_proc => @draw_local}

	hsh = { :tooltip => T6[:TIP_PictureMapSelect], :draw_proc => :folder }
	@palette.declare_button(:pal_picture_map_select, hshp, hsh) { picture_ask_file }	

	hsh = { :passive => true, :draw_proc => :separator_V, :width => 6 }	
	@palette.declare_button :pal_picture_map_sepa0, hshp, hsh
	
	grayed_proc = proc { !@picture_file }
	value_proc = proc { picture_matching? }
	hsh = { :tooltip => T6[:TIP_PictureMapMatch], :value_proc => value_proc, :grayed_proc => grayed_proc, 
	        :draw_proc => @draw_local }
	@palette.declare_button(:pal_picture_map_match, hshp, hsh) { picture_match }	
	
	hsh = { :passive => true, :draw_proc => :separator_V, :width => 6 }	
	@palette.declare_button :pal_picture_map_sepa1, hshp, hsh
	
	value_proc = proc { picture_visible? }
	hsh = { :tooltip => T6[:TIP_PictureMapToggle], :value_proc => value_proc, :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_picture_map_toggle, hshp, hsh) { picture_toggle }	

end

#---------------------------------------------------------------------
# Creation of the Floating palettes
#---------------------------------------------------------------------

#PALETTE: Floating palette for Cleansing operations
def palette_floating_cleansing
	@palette.set_current_family :cleansing
	wh = 20
	
	#Declare the floating palette
	flpal = :pal_cleanser_floating
	hshfloat = { :floating => flpal, :row => 0, :width => wh, :height => wh }
	hidden_proc = proc { ! (@mode == :cleansing && @cleanser && !@cleanser.editing_altitude? && @cleanser.show_floating_palette?) }
	hsh = { :auto_move => [:up], :hidden_proc => hidden_proc }
	@palette.declare_floating flpal, hsh

	#Buttons for removing / inserting contours
	symb = "#{flpal}_accept".intern
	value_proc = proc { @cleanser && @cleanser.contour_all_included? }
	hsh = { :value_proc => value_proc, :draw_proc => :valid_3, :tooltip => T6[:TIP_ContourAccept], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { notify_cleanser_ui :include }

	symb = "#{flpal}_ignore".intern
	value_proc = proc { @cleanser.contour_all_ignored? }
	hsh = { :value_proc => value_proc, :draw_proc => :cross_NE3, :tooltip => T6[:TIP_ContourIgnore], :frame_color => 'red', :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { notify_cleanser_ui :ignore }
	
	#Separator
	@palette.declare_separator_floating flpal, { :height => wh }
	
	#Buttons for simplify
	symb = "#{flpal}_simplify".intern
	value_proc = proc { @cleanser.contour_all_simplified? }
	hsh = { :value_proc => value_proc, :draw_proc => @draw_local, :tooltip => T6[:MNU_SimplifyContour], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { notify_cleanser_ui :simplify }

	symb = "#{flpal}_simplify_no".intern
	value_proc = proc { @cleanser.contour_all_not_simplified? }
	hsh = { :value_proc => value_proc, :draw_proc => @draw_local, :tooltip => T6[:MNU_UnSimplifyContour], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { notify_cleanser_ui :unsimplify }
	
end

#PALETTE: Floating palette for Altitude Edition
def palette_floating_altitude
	@palette.set_current_family :cleansing
	
	#Parameters for the layout
	nbut_in_row = 3
	hrow = 20
	widmove = 20
	widsense = 28
	widval = 90
	wsepa = 20
	widtot = nbut_in_row * widval + widmove
	widlab = widtot - widval - widsense - wsepa
	
	#Declare the floating palette
	flpal = :pal_cleanser_floating_altitude
	hshfloat = { :floating => flpal, :row => 0, :height => hrow }
	hidden_proc = proc { ! (@mode == :cleansing && @cleanser && @cleanser.editing_altitude? && !@preview_in_situ) }
	hsh = { :title => T6[:TIT_FloatAltitudeEdit], :hidden_proc => hidden_proc }
	@palette.declare_floating flpal, hsh
	
	#Buttons for reference altitude
	tit = T6[:TIT_AltitudeReference]
	tip = T6[:TIP_AltitudeReference]
	prompt = tit + ' (' + T6[:TXT_InCurrentUnits] + ')'
	tipval = "Click to change"
	
	row = 0
	symb = "#{flpal}_sense_up".intern
	value_proc = proc { @cleanser.altitude_button_sense_get == +1 }
	hsh = { :row => row, :value_proc => value_proc, :hi_color => 'yellow', :width => widsense, :tooltip => T6[:TIP_AltitudeSenseUp], :draw_proc => @draw_local }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.altitude_button_sense_click +1 }
	@palette.declare_separator_floating flpal, { :height => wsepa }

	symb = "#{flpal}_ref_title".intern
	value_proc = proc { @cleanser && @cleanser.contour_all_included? }
	hsh = { :row => row, :passive => true, :width => widlab, :text => tit + ' >>', :justif => 'LH', :tooltip => tip }
	@palette.declare_button(symb, hshfloat, hsh)
	
	symb = "#{flpal}_ref_value".intern
	hshi = { :vtype => :len, :vprompt => prompt }
	get_proc = proc { @cleanser.altitude_reference_get }
	set_proc = proc { |val| @cleanser.altitude_reference_set val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	hsh = { :row => row, :bk_color => 'yellow', :input => input, :width => widval, :tooltip => tipval }
	@palette.declare_button symb, hshfloat, hsh 
	
	#Buttons for altitude increment
	tit = T6[:TIT_AltitudeIncrement]
	tip = T6[:TIP_AltitudeIncrement]
	prompt = tit + ' (' + T6[:TXT_InCurrentUnits] + ')'
	
	row = 1
	symb = "#{flpal}_sense_down".intern
	value_proc = proc { @cleanser.altitude_button_sense_get == -1 }
	hsh = { :row => row, :value_proc => value_proc, :hi_color => 'yellow', :width => widsense, :tooltip => T6[:TIP_AltitudeSenseDown], :draw_proc => @draw_local }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.altitude_button_sense_click -1 }
	@palette.declare_separator_floating flpal, { :height => wsepa }

	symb = "#{flpal}_incr_title".intern
	value_proc = proc { @cleanser && @cleanser.contour_all_included? }
	hsh = { :row => row, :passive => true, :width => widlab, :text => tit + ' >>', :justif => 'LH', :tooltip => tip }
	@palette.declare_button(symb, hshfloat, hsh)

	symb = "#{flpal}_incr_value".intern
	hshi = { :vtype => :len, :vprompt => prompt }
	get_proc = proc { @cleanser.altitude_increment_get }
	set_proc = proc { |val| @cleanser.altitude_increment_set val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc }
	hsh = { :row => row, :bk_color => 'powderblue', :input => input, :width => widval, :tooltip => tipval }
	@palette.declare_button symb, hshfloat, hsh 
	
	#Row of altitude buttons
	@tip_current = T6[:TIP_AltitudeCurrentSet]
	row = 2
	symb = "#{flpal}_move_down".intern
	hsh = { :row => row, :width => widmove, :tooltip => T6[:TIP_AltitudeMoveDown], :draw_proc => @draw_local }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.altitude_button_move_click -1 }
	
	for i in 0..nbut_in_row-1
		ibut = nbut_in_row - i
		symb = "#{flpal}_m_#{ibut}".intern
		hshb = { :row => row, :width => widval, :tooltip => @tip_current }
		palette_floating_altitude_button(-ibut, symb, hshfloat, hshb)	
	end
	
	row = 3
	for i in 0..nbut_in_row-1
		symb = "#{flpal}_p_#{i}".intern
		tip = (i == 0) ? T6[:TIP_AltitudeCurrent] : @tip_current
		hshb = { :row => row, :width => widval, :tooltip => tip }
		palette_floating_altitude_button(i, symb, hshfloat, hshb)	
	end
	
	symb = "#{flpal}_move_up".intern
	hsh = { :row => row, :width => widmove, :tooltip => T6[:TIP_AltitudeMoveUp], :draw_proc => @draw_local }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.altitude_button_move_click +1 }
	
end

#PALETTE: Create a button for altitude range
def palette_floating_altitude_button(ibut, symb, hshfloat, hshb)
	text_proc = proc { @cleanser.altitude_button_text_at ibut }
	hsh = { :text_proc => text_proc, :justif => 'MH', :draw_proc => @draw_local }
	@palette.declare_button(symb, hshfloat, hshb, hsh) { @cleanser.altitude_button_exec ibut }
end

#PALETTE: Floating palette for Cleansing operations
def palette_floating_picture_match
	@palette.set_current_family :cleansing
	tx_move = T6[:BOX_PictureMatchMove]
	tx_adjust = T6[:BOX_PictureMatchAdjust]
	tx_exit = T6[:BOX_PictureMatchExit]
	w1, = G6.simple_text_size tx_move
	w2, = G6.simple_text_size tx_adjust
	w3, = G6.simple_text_size tx_exit
	wh = [w1, w2, w3].max + 15
	
	#Declare the floating palette
	flpal = :pal_picture_match_floating
	hshfloat = { :floating => flpal, :row => 0, :width => wh, :height => 20, :justif => "MH" }
	hidden_proc = proc { @mode != :cleansing || !@cleanser.picture_matching? }
	hsh = { :title => T6[:TIT_PictureMatch], :hidden_proc => hidden_proc }
	@palette.declare_floating flpal, hsh

	#Buttons for removing / inserting contours
	symb = "#{flpal}_move".intern
	value_proc = proc { @cleanser && @cleanser.picture_match_step == :move }
	hsh = { :value_proc => value_proc, :text => tx_move, :tooltip => T6[:TIP_PictureMatchMove], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.picture_match_set_step :move }

	symb = "#{flpal}_adjust".intern
	grayed_proc = proc { @cleanser.picture_match_grayed :adjust }
	value_proc = proc { @cleanser && @cleanser.picture_match_step == :adjust }
	hsh = { :value_proc => value_proc, :grayed_proc => grayed_proc, :text => tx_adjust, 
	        :tooltip => T6[:TIP_PictureMatchAdjust], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.picture_match_set_step :adjust }
	
	symb = "#{flpal}_exit".intern
	hsh = { :text => tx_exit, :tooltip => T6[:TIP_PictureMatchExit], :hi_color => 'yellow' }
	@palette.declare_button(symb, hshfloat, hsh) { @cleanser.picture_match_set_step :exit }
end

#PALETTE: Floating palette for Calculation operations (algo)
def palette_floating_algo
	@palette.set_current_family :algo
	wh = 32
	
	#Declare the floating palette
	flpal = :pal_algo_floating
	hshfloat = { :floating => flpal, :row => 0 }
	hidden_proc = proc { @mode != :algo || !@algo || !@algo.show_floating_palette? }
	hsh = { :auto_move => [:up], :hidden_proc => hidden_proc }
	@palette.declare_floating flpal, hsh
	
	#Hilltop management
	symb_master = "#{flpal}_hilltop_title".intern
	
	txbox = T6[:BOX_Hilltop]
	w, = G6.simple_text_size txbox
	w = [w, 70].max + 8
	
	hidden_proc = proc { @mode != :algo || !@algo || !@algo.option_hilltop_possible_on_selected? }
	value_proc = proc { @algo.option_hilltop_value_on_selected }
	hsh = { :type => 'multi', :radio => 'true', :passive => true, :text => txbox, :bk_color => 'lightblue',
	        :height => 16, :default_value => :auto, :tooltip => T6[:TIP_HilltopMain], :value_proc => value_proc,
			:hidden_proc => hidden_proc }
	@palette.declare_button(symb_master, hshfloat, hsh) { @algo.notify_contour_set :hilltop, @palette.button_get_value, @algo.contour_selection }

	wid = w * 0.5	
	hshp = { :parent => symb_master, :draw_proc => @draw_local, :width => wid }

	symb = "#{flpal}_hilltop_flat".intern
	hsh = { :value => :flat, :tooltip => T6[:TIP_HilltopFlat] }
	@palette.declare_button(symb, hshfloat, hshp, hsh)	

	symb = "#{flpal}_hilltop_auto".intern
	hsh = { :value => :auto, :tooltip => T6[:TIP_HilltopAuto] }
	@palette.declare_button(symb, hshfloat, hshp, hsh)	
end

#PALETTE: Drawing the Blason
def draw_button_blason(symb, dx, dy)
	lst_gl = []
	dx2 = dx/2
	dy2 = dy/2
	dym = dy * 3 / 4
	dyb = dym-4
	ptmid = Geom::Point3d.new dx2, dy2
	tr = Geom::Transformation.rotation ptmid, Z_AXIS, 45.degrees
	
	lip = [[[6, 3], [dx2, 3]], [[1, 8], [8, 6], [dx2, 4]], [[1, 14], [7, 11], [12, 8], [dx2, 6]], [[1, 20], [7, 16], [12, 10], [dx2, 9]],
	       [[4, 25], [7, 20], [16, 18], [dx2+5, 13]], [[dx2, dy-3], [dx2+10, 20]]]
	
	lip.each do |ls|
		pts = ls.collect { |a| Geom::Point3d.new *a }
		lst_gl.push [GL_LINE_STRIP, pts, 'blue', 2, '']
	end	
		
	pts = G6.pts_square 22, 6, 4
	lst_gl.push [GL_LINE_LOOP, pts, 'red', 2, '']
	
	lst_gl
end

#--------------------------------------------------------------
# Custom drawing for palette buttons
#--------------------------------------------------------------

#Custom drawing of buttons
def draw_button_opengl(symb, dx, dy, main_color, frame_color, selected, grayed)
	code = symb.to_s
	lst_gl = []
	dx2 = dx / 2
	dy2 = dy / 2
	grayed = @palette.button_is_grayed?(symb)
	color = (grayed) ? 'gray' : frame_color
	
	case code

	#Preview Modes
	when /step/
		rect = G6.pts_round_rectangle(-1, -1, dx+1, dy+1, 6)
		lst_gl.push [GL_POLYGON, rect, 'gold']
		lst_gl.push [GL_LINE_LOOP, rect, 'goldenrod', 2, '']

	when /simplify/
		dec = 2
		pts = [Geom::Point3d.new(dx-dec, dy-dec-1), Geom::Point3d.new(dec, dy2), Geom::Point3d.new(dx-dec, dec+1)]
		lst_gl.push [GL_LINE_STRIP, pts, 'green', 3, '']
		if code =~ /_no\Z/
			pts = [Geom::Point3d.new(dx-dec-3, 1), Geom::Point3d.new(dec, dy)]
			lst_gl.push [GL_LINE_STRIP, pts, 'red', 3, '']
		end
		
	#Preview Modes
	when /preview_mode_(.*)/
		sub_code = $1
		map_only = (sub_code =~ /\Amap/)
		surface_only = (sub_code =~ /surface\Z/)
		if sub_code =~ /map/
			lx = (map_only) ? [0, 0.33, 0.66, 1] : [0.66, 1]
			pts = [[], [], [], []]
			lx.each_with_index do |x, ix|
				[0, 0.5, 1].each_with_index do |y, iy|
					pts[ix][iy] = Geom::Point3d.new dx * x, dy * y, 0
				end	
			end
			for ix in 0..lx.length-2
				for iy in 0..1
					color = ((ix + iy).modulo(2) == 0) ? 'lightyellow' : 'lightgreen'
					rect = [pts[ix][iy], pts[ix+1][iy], pts[ix+1][iy+1], pts[ix][iy+1]]
					lst_gl.push [GL_POLYGON, rect, color]
					lst_gl.push [GL_LINE_LOOP, rect, 'gray', 1, '']
				end
			end	
		end
		if sub_code =~ /surface/
			w = (surface_only) ? dx : dx2
			origin = Geom::Point3d.new(1,0)
			axe = [origin, Geom::Point3d.new(w, 0)]
			lst_gl.push [GL_LINE_STRIP, axe, 'red', 2, '']
			axe = [origin, Geom::Point3d.new(1, dy)]
			lst_gl.push [GL_LINE_STRIP, axe, 'blue', 2, '']
			axe = [origin, Geom::Point3d.new(dx2, dy2)]
			lst_gl.push [GL_LINE_STRIP, axe, 'green', 2, '']
		end
		
		if sub_code =~ /situ/i
			rect = G6.pts_rectangle 0, 0, dx, dy
			lst_gl.push [GL_POLYGON, rect, (selected) ? 'yellow' : 'lightgrey']
			lst_gl.push [GL_LINE_LOOP, rect, 'blue', 1, '']
		end	
	
	#Hilltop handling
	when /hilltop_(.*)/
		pt1 = Geom::Point3d.new(1, 1)
		pt2 = Geom::Point3d.new(dx/4, dy2)
		pt3 = Geom::Point3d.new(dx - dx/4, dy2)
		pt4 = Geom::Point3d.new(dx-1, 1)
		if $1 == 'flat'
			pts = [pt2, pt3]
		else
			ptt0 = Geom::Point3d.new(dx2-dx/4, dy-dy/4)
			ptt1 = Geom::Point3d.new(dx2, dy-1)
			ptt2 = Geom::Point3d.new(dx2+dx/4, dy-dy/4)
			pts = [pt2, ptt0, ptt1, ptt2, pt3]
		end	
		lst_gl.push [GL_LINES, [pt1, pt2, pt3, pt4], 'gray', 2, '']
		lst_gl.push [GL_LINE_STRIP, pts, 'blue', 2, '']
	
	when /option_geometry_wall/i
		lpi = [[dx, dy-8], [dx-5, dy-3], [dx2, dy], [5, dy-1], [1, dy-5]]
		lpti = lpi.collect { |a| Geom::Point3d.new *a }
		pts = [[1, 1], [dx, 1]].collect { |a| Geom::Point3d.new *a } + lpti
		lst_gl.push [GL_POLYGON, pts, 'sandybrown']
		lst_gl.push [GL_LINE_LOOP, pts, 'gray', 1, '']
		pts = []
		lpti.each_with_index { |pt, i| pts.push pt, Geom::Point3d.new(lpti[i].x, 1) }
		lst_gl.push [GL_LINES, pts, 'gray', 1, '']
		
	when /option_geometry_contour/i
		lpi = [[1, 1], [dx/4, dy-2], [dx2, 8], [3*dx/4, dy-2]]
		lst_gl.push [GL_LINE_STRIP, lpi.collect { |a| Geom::Point3d.new *a }, 'blue', 2, '']
		lpi = [[dx/4, 1], [dx2, dy2], [3*dx/4, dy2-3], [dx, dy2+3]]
		lst_gl.push [GL_LINE_STRIP, lpi.collect { |a| Geom::Point3d.new *a }, 'blue', 2, '']
		
	when /option_geometry_map/i
		dx4 = dx / 4
		dy4 = dy / 4
		lpi = [[0, 0], [dx, 0], [dx, dy], [0, dy]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'moccasin']
		lst_gl.push [GL_LINE_LOOP, lpi.collect { |a| Geom::Point3d.new *a }, 'black', 1, '']
		
		lip = [[[1, dy2], [dx4, 1]], [[dx4, dy-1], [dx2, 1]], [[dx2, dy-1], [3*dx4, 1]], [[3*dx4, dy-1], [dx, dy2]]]
		lip.each do |ls|
			pts = ls.collect { |a| Geom::Point3d.new *a }
			lst_gl.push [GL_LINE_STRIP, pts, 'black', 2, '']
		end	
		
	when /debug_zone/i	
		lpi = [[1, 8], [dx/4, dy-2], [dx2, dy2+6], [3*dx/4, dy-2]]
		lst_gl.push [GL_LINE_STRIP, lpi.collect { |a| Geom::Point3d.new *a }, 'red', 2, '']
		lpi = [[dx/4, 1], [dx2, dy2-3], [3*dx/4, dy2-6], [dx, dy2+3]]
		lst_gl.push [GL_LINE_STRIP, lpi.collect { |a| Geom::Point3d.new *a }, 'red', 2, '']
		pts = G6.pts_square dx2, dy2, 3
		lst_gl.push [GL_POLYGON, pts, 'blue']
	
	when /cleanser_altitude/
		len = 16
		lpi = [[1, dy-2], [len, dy-2], [1, 2], [len, 2]]
		lst_gl.push [GL_LINE_STRIP, lpi.collect { |a| Geom::Point3d.new *a }, 'blue', 2, '']
	
	when /move_down/
		dec = 3
		lpi = [[1, 1], [1, dy-1], [dx-1, dy-1], [dx-1, 1]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'palegreen']
		lpi = [[dec, dy2], [dx-dec, dy-dec], [dx-dec, dec]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'gray']
		
	when /move_up/
		dec = 3
		lpi = [[1, 1], [1, dy-1], [dx-1, dy-1], [dx-1, 1]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'palegreen']
		lpi = [[dec, dec], [dec, dy-dec], [dx-dec, dy2]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'gray']
		
	when /sense_down/
		lpi = [[1, dy-1], [dx-1, dy-1], [dx2, 1]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'blue']
		
	when /sense_up/
		lpi = [[1, 1], [dx-1, 1], [dx2, dy-1]]
		lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'blue']

	when /_p_(\d)/, /_m_(\d)/
		lpi = [[1, 1], [1, dy-1], [dx-1, dy-1], [dx-1, 1]]
		if $1 == '0'
			lpi0 = [[0, 0], [0, dy], [dx, dy], [dx, 0]]
			lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'springgreen']
			lst_gl.push [GL_LINE_LOOP, lpi0.collect { |a| Geom::Point3d.new *a }, 'red', 2, '']
		else
			lst_gl.push [GL_POLYGON, lpi.collect { |a| Geom::Point3d.new *a }, 'palegreen']
		end
		
	when /picture_map_toggle/i
		color = (grayed) ? 'gray' : 'blue'
		dx4 = dx / 4
		dy5 = dy / 5
		pts = []
		pts.push Geom::Point3d.new(0, dy2)
		pts.push Geom::Point3d.new(dx4, dy-1)
		pts.push Geom::Point3d.new(dx2, dy)
		pts.push Geom::Point3d.new(3*dx4, dy-1)
		pts.push Geom::Point3d.new(dx, dy2)
		pts.push Geom::Point3d.new(3*dx4, 2)
		pts.push Geom::Point3d.new(dx2, 0)
		pts.push Geom::Point3d.new(dx4, 2)
		lst_gl.push [GL_POLYGON, pts, ((selected) ? 'yellow' : 'lightgrey')] 
		lst_gl.push [GL_LINE_LOOP, pts, color, 2, ''] 
		pts = G6.pts_square dx2, dy2, 2
		lst_gl.push [GL_POLYGON, pts, color] 

	when /picture_map_match/i
		color = 'blue'
		decx = 4
		decy = 2
		lpti = [[0, dy2], [dx2-decx, dy2], [dx2+decx, dy2], [dx, dy2], [dx2, 0], [dx2, dy2-decy], [dx2, dy2+decy], [dx2, dy]]
		pts = lpti.collect { |a| Geom::Point3d.new *a }
		lst_gl.push [GL_LINES, pts, color, 2, ''] 
	
	when /map_position_/i
		color = 'brown'
		if (code =~ /top/) 
			z = dy-2
			dec	= 0
		else	
			z = 2
			dec = 3 
		end	
		lpti = [[1,0], [dx/4, dy2], [dx2, dy2+3], [dx2 + dx/4, dy2-2], [dx-1, 0]]
		pts = lpti.collect { |a| Geom::Point3d.new(a[0], a[1] + dec) }
		lst_gl.push [GL_POLYGON, pts, 'khaki'] 
		lst_gl.push [GL_LINE_LOOP, pts, 'black', 1, ''] 
		
		lpti = [[0,z], [dx, z]]
		pts = lpti.collect { |a| Geom::Point3d.new *a }
		lst_gl.push [GL_LINES, pts, color, 3, ''] 
		
	
	end	#case code
	
	lst_gl
end

end	#class TopoShaperTool

end	#End Module F6_TopoShaper
