=begin
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
# Copyright © 2009-2015 Fredo6 - Designed and written as of April 2009 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			:   RoundCorner_Tool.rb
# Original Date	:   30 April 2009 - version 2.0
# Description	:   Sketchup Tool for RoundCorner
#-------------------------------------------------------------------------------------------------------------------------------------------------
#*************************************************************************************************
=end

module F6_RoundCorner

T6[:BOX_NumSeg] = "# Seg."
T6[:TIP_Numseg] = "Number of segments for the rounding (VCB: number + s)"
T6[:PROMPT_NumSeg] = "Number of Segments for Rounding"
T6[:TIP_Offset] = "Offset value by reference to orthogonal faces (VCB: length in current units)"
T6[:PROMPT_Offset] = "Offset value"
T6[:BOX_Pivot] = "Pivot"

T6[:BANDEAU_selection] = "EDGE SELECTION"
T6[:BANDEAU_TIP_selection] = "Options for the selection of Edges"
T6[:BANDEAU_parameters] = "ROUNDING PARAMETERS"
T6[:BANDEAU_TIP_parameters] = "Parameters to configure the Rounding"
T6[:BANDEAU_edge_prop] = "EDGE PROPERTIES"
T6[:BANDEAU_TIP_edge_prop] = "Properties for generated edges"
T6[:BANDEAU_process] = "GEOMETRY GENERATION"
T6[:BANDEAU_TIP_process] = "Creation and Modification of the Geometry"

T6[:TIP_NumberEdges] = "Number of Selected Edges"
T6[:TIP_NumberCorners] = "Number of Corners"
T6[:MNU_EdgePropFilter] = "Filter on Edge selection"
T6[:MNU_EdgePropFilter2] = "Edge Prop. Filter"
T6[:MNU_EdgePropBorder] = "Borders"
T6[:TIP_EdgePropBorder] = "Edge Properties for created Borders"
T6[:MNU_EdgePropCorner] = "Corners"
T6[:TIP_EdgePropCorner] = "Edge Properties for outer edges of Corners"
T6[:MNU_EdgePropRound] = "Inner Edges"
T6[:TIP_EdgePropRound] = "Edge Properties for created round edges and corners"
T6[:BOX_ApplyChange] = "APPLY|CHANGE"
T6[:TIP_ApplyChange] = "Recompute the roundings after a change of parameters"
T6[:BOX_ApplyGenerate] = "GENERATE|GEOMETRY"
T6[:TIP_ApplyGenerate] = "Generate the geometry"

#Contextual menus
T6[:MNU_Execute] = "Calculate Round Corners"
T6[:MNU_ApplyChange] = "Recalculate Round Corners"
T6[:MNU_EnterClick] = "Enter or click in empty space"
T6[:MNU_Exit] = "Exit Tool (Click in empty space)"
T6[:MNU_UnselectAll] = "Clear all (ESC)"
T6[:MNU_Rounding] = "Super rounding at corner (round corners only)"
T6[:MNU_StrictOffset] = "Respect strict offset as far as possible"
T6[:MNU_Offset] = "Offset"
T6[:MNU_AllParam] = "Dialog box for all parameters"

#Text for Dilaog box
T6[:DLG_All_Title] = "Round Corner parameters"
T6[:DLG_All_Offset] = "Offset (reference orthogonal planes)"
T6[:DLG_All_Numseg] = "Number of segments for the rounding"
T6[:DLG_All_GoldenAxis] = "Main direction for pivot edges"
T6[:DLG_All_StrictOffset] = "Respect Strict Offset"
T6[:DLG_All_SuperRounding] = "Super Rounding of corners"

#Tooltip message
T6[:TIP_Computing] = "COMPUTING"
T6[:TIP_Interrupt] = "Click anywhere or Escape to interrupt the operation"
T6[:TIP_Aborted] = "ABORTED by user"
T6[:TIP_Time] = "Time: %1 second"
T6[:TIP_Count] = "Edges: %1 - Corners: %2"

T6[:TIP_InvalidBest] = "Invalid (Group or Component)"
T6[:TIP_Invalid] = "Invalid"
T6[:TIP_WrongNbFaces] = "Not 2 faces"
T6[:TIP_WrongCoplanar] = "Coplanar edge"
T6[:TIP_WrongFilter] = "Property filter"

T6[:TIP_Execute] = "Click to Execute"
T6[:TIP_Modify] = "Click to Modify"
T6[:TIP_Exit] = "Click to Exit"
T6[:TIP_Select_Edge] = "Select Edge"
T6[:TIP_UnSelect_Edge] = "Unselect Edge"
T6[:TIP_Select_Vertex] = "Select All edges at Vertex"
T6[:TIP_UnSelect_Vertex] = "Unselect All edges at Vertex"
T6[:TIP_Select_Face] = "Select All edges of Face"
T6[:TIP_UnSelect_Face] = "Unselect All edges of Face"
T6[:TIP_Axis] = "Main direction for pivot edges (use Arrows to change)"
T6[:TIP_SaveLetter] = "Save Current Parameters as %1"
T6[:TIP_LetterInfo] = "Offset = %1 - Nb Seg = %2"
T6[:TIP_LetterVoid] = "Restore Parameters for %1"

# Strings for the application
T6[:MSG_Main] = "Click on Edges, Vertex, Faces to add / remove edges (See Palette and contextual menu for options)"
T6[:MSG_Abort] = "Do you want to abort operation?"
T6[:MSG_AbortLeave] = "Do you want to finish operation before leaving the tool?"
T6[:MSG_ErrorFound] = "An Error was found when processing geometry\nCorner at fault is highlighted in the model"
T6[:MSG_SomeErrors] = "Some corners cannot be processed"
T6[:MSG_Collision] = "There are at least %1 overlaps - Please consider Reducing the Offset"
T6[:MSG_ConfirmGeneration] = "Do you confirm the Generation?"
T6[:LABEL_Wait] = "WAIT"
T6[:LABEL_Finishing] = "Finishing"

#--------------------------------------------------------------------------------------------------------------
# Top Calling functions: create the classes and launch the tools
#--------------------------------------------------------------------------------------------------------------			 				   

#Actual launching of menus	
def F6_RoundCorner.action__mapping(action_code)
	case action_code
	when :round
		F6_RoundCorner.launch :round
	when :sharp
		F6_RoundCorner.launch(:sharp, { :sharp => true })
	when :bevel
		F6_RoundCorner.launch(:bevel, { :profile_type => ['C', 1] })
	end		
end

def F6_RoundCorner.launch(*hargs)
	Sketchup.active_model.select_tool RoundCornerTool.new(*hargs)
end

#---------------------------------------------------------------------------------------------------------------------------
# Class RoundCornerTool: implement the interactive tool	
#---------------------------------------------------------------------------------------------------------------------------

class RoundCornerTool < Traductor::PaletteSuperTool

#INIT: Initialization and creation of the tool
def initialize(tool_type, *hargs)
	@tool_type = tool_type
	
	@model = Sketchup.active_model
	@selection = @model.selection
	@view = @model.active_view
	@ip = Sketchup::InputPoint.new
	@ph = @view.pick_helper	
	
	#Loading default parameters
	proc = self.method "notify_from_defparam"
	MYDEFPARAM.add_notify_proc(proc, true)

	#Initializing the cursor, texts and Function keys
	init_cursors
	init_text
	init_fkey
	
	#Titles and tooltips
	stit = "RDC_#{@tool_type.to_s.upcase}_Menu"
	@title_tool = T6[stit.intern]
	@label = T6[:MNU_Offset]
	@time_calculation = nil
	
	#Initialization of default parameters
	@edge_prop_filter_default = MYDEFPARAM[:DEFAULT_Flag_EdgePropFilter]
	@edge_prop_border_default = MYDEFPARAM[:DEFAULT_Flag_EdgePropBorder]
	@edge_prop_corner_default = MYDEFPARAM[:DEFAULT_Flag_EdgePropCorner]
	@edge_prop_round_default = MYDEFPARAM[:DEFAULT_Flag_EdgePropRound]
	@color_edges = MYDEFPARAM[:DEFAULT_Color_Edges]
	@color_borders = MYDEFPARAM[:DEFAULT_Color_Borders]
	
	#Computing the letters displays
	nletter = MYDEFPARAM[:DEFAULT_NumberLetter]
	@persist_letters = []
	letter = 'A'
	for i in 0..nletter-1
		@persist_letters.push letter
		letter = letter.next
	end	
		
	#Initializating the Selection mode
	hsh = {}
	hsh["modifier"] = @modifier if @modifier
	hsh["anglemax"] = @anglemax if @anglemax
	@selmode = Traductor::SelMode.new hsh
	
	#Restablishing previous parameters for selection
	param_load
	
	@aperture = MYDEFPARAM[Traductor::SelMode.default_symb_aperture(:RDC_)]
	@aperture = nil if @aperture && @aperture < 5
	
	#Initializing the Algorithm class
	cursor_proc = proc { onSetCursor }
	hsh = { :cursor_proc => cursor_proc }
	@algo = RoundCornerAlgo.new(tool_type, hsh, *hargs)
	@algo.define_end_generation_proc { |status| end_calculation status }
	
	#Initializing the VCB
	vcb_init
	
	#Initializing the Zoom Manager
	@zoom_void = G6::ZoomVoid.new
	
	#Initializing the Key manager
	@keyman = Traductor::KeyManager.new() { |event, key, view| key_manage(event, key, view) }
	
	#Creating the palette manager and texts
	palette_init
end

#INIT: Initialize the cursors
def init_cursors
	@id_cursor_pick_none = MYPLUGIN.create_cursor "None", 0, 0	
	@id_cursor_pick_invalid = MYPLUGIN.create_cursor "Invalid", 0, 0	
	
	@id_cursor_pick_vertex_PN = MYPLUGIN.create_cursor "Cursor_Picker_Vertex_P_N", 0, 0	
	@id_cursor_pick_vertex_PA = MYPLUGIN.create_cursor "Cursor_Picker_Vertex_P_A", 0, 0	
	@id_cursor_pick_vertex_PC = MYPLUGIN.create_cursor "Cursor_Picker_Vertex_P_C", 0, 0	
	@id_cursor_pick_vertex_PF = MYPLUGIN.create_cursor "Cursor_Picker_Vertex_P_F", 0, 0	
	@id_cursor_pick_vertex = MYPLUGIN.create_cursor "Arrow_Vertex", 0, 0	
	
	@id_cursor_pick_edge = MYPLUGIN.create_cursor "Arrow_Edge", 0, 0	
	@id_cursor_pick_face = MYPLUGIN.create_cursor "Arrow_Face", 0, 0	
	@id_cursor_arrow_exit = MYPLUGIN.create_cursor "Arrow_Exit", 0, 0	
	@id_cursor_validate = MYPLUGIN.create_cursor "Validate", 0, 0	
	@id_cursor_hourglass_green = Traductor.create_cursor "Cursor_hourGlass_Green", 16, 16	
	@id_cursor_hourglass_blue = Traductor.create_cursor "Cursor_hourGlass_Blue", 16, 16	
	@id_cursor_hourglass_red = Traductor.create_cursor "Cursor_hourGlass_Red", 16, 16	
end

#INIT: Initializing texts
def init_text
	@mnu_execute = T6[:MNU_Execute] + ' (' + T6[:MNU_EnterClick] + ')'
	@mnu_apply_change = T6[:MNU_ApplyChange] + ' (' + T6[:MNU_EnterClick] + ')'
	@mnu_exit = T6[:MNU_Exit]
	@mnu_unselect_all = T6[:MNU_UnselectAll]
	@mnu_edge_prop_filter = T6[:MNU_EdgePropFilter]
	@mnu_strict_offset = T6[:MNU_StrictOffset]
	@mnu_rounding = T6[:MNU_Rounding]
	@mnu_offset = T6[:MNU_Offset]
	
	@mnu_all_param = T6[:MNU_AllParam]
	
	@msg_main = T6[:MSG_Main]
	@msg_some_errors = T6[:MSG_SomeErrors]
	
	@tip_computing = T6[:TIP_Computing]
	@tip_invalid = T6[:TIP_Invalid]
	@tip_invalid_best = T6[:TIP_InvalidBest]
	@tip_wrong_nb_faces = T6[:TIP_WrongNbFaces]
	@tip_wrong_coplanar = T6[:TIP_WrongCoplanar]
	@tip_wrong_filter = T6[:TIP_WrongFilter]
	
	@tip_execute = T6[:TIP_Execute]
	@tip_modify = T6[:TIP_Modify]
	@tip_exit = T6[:TIP_Exit]
	@tip_select_edge = T6[:TIP_Select_Edge]
	@tip_unselect_edge = T6[:TIP_UnSelect_Edge]
	@tip_select_face = T6[:TIP_Select_Face]
	@tip_unselect_face = T6[:TIP_UnSelect_Face]
	@tip_select_vertex = T6[:TIP_Select_Vertex]
	@tip_unselect_vertex = T6[:TIP_UnSelect_Vertex]
	@tip_offset = T6[:TIP_Offset]
	@tip_numseg = T6[:TIP_Numseg]
	@tip_axis = T6[:TIP_Axis]
	@tip_interrupt = T6[:TIP_Interrupt]
	@msg_collision = T6[:MSG_Collision]
end

#INIT: Creating the Function Key Options
def init_fkey
	key = MYDEFPARAM[:DEFAULT_Key_StrictOffset]
	@fkey_strict_offset = Traductor::FKeyOption.new(T6[:MNU_StrictOffset], key) { @algo.parameters_toggle :strict_offset }
	key = MYDEFPARAM[:DEFAULT_Key_Rounding]
	@fkey_rounding = Traductor::FKeyOption.new(T6[:MNU_Rounding], key) { @algo.parameters_toggle :mode_rounding }
end

#INIT: Computing the letters displays
def init_letter
	nletter = MYDEFPARAM[:DEFAULT_NumberLetter]
	@persist_letters = []
	letter = 'A'
	for i in 0..nletter-1
		@persist_letters.push letter
		letter = letter.next
	end	
end

#INIT: Notification when default parameters are changed
def notify_from_defparam(key, val)
	case key.to_s
	when /color/i
		@algo.init_colors
		@algo.refresh_for_view
		refresh_viewport
	when /letter/i
		init_letter
		refresh_viewport
	end
end

#--------------------------------------------------------------
# PARAM: Persistence of parameters
#--------------------------------------------------------------

#PARAM: Load the parameters for selection from registry
def param_load
	@dico = "Fredo6_RoundCorner"
	@dico_selection = "ParamSelection"
	sparam = Traductor::Default.read @dico, @dico_selection
	hsh = eval(sparam) rescue {}
	hsh = {} unless hsh
	
	#Transferring the new parameters
	@anglemax = hsh[:anglemax]
	@anglemax = 30 unless @anglemax
	@selmode.set_anglemax @anglemax
	@modifier = hsh[:modifier]
	@modifier = 'F' unless @modifier
	@selmode.set_modifier @modifier
end

#PARAM: Save the parameters for selection to registry
def param_save
	hsh = {}
	hsh[:modifier] = @selmode.get_modifier
	hsh[:anglemax] = @selmode.get_anglemax
	sparam = hsh.inspect.gsub('"', "'")
	Traductor::Default.store @dico, @dico_selection, sparam
end

#--------------------------------------------------------------
# Tool Events
#--------------------------------------------------------------

#activation of the tool
def activate
	LibFredo6.register_ruby 'RoundCorner' if defined?(LibFredo6.register_ruby)
	
	#initialization
	@pk_vertex = nil
	@pk_edge = nil
	@pk_face = nil
	
	#Analyze the selection
	@algo.analyze_selection @selection
	@selection.clear
	
	refresh_viewport
end

#Deactivation of the tool
def deactivate(view)
	#@algo.robot_interrupt?(false)
	
	#Saving the parameters for selection and for algo
	@algo.parameters_save
	param_save
	
	#Unselect all
	@algo.unselect_all
	@x = nil
	vcb_clean
	view.invalidate
	true
end

#Cancel event
def onCancel(flag, view)
	#Interrupting geometry construction if running
	return if @algo.robot_interrupt?

	#Cancel current scaling operation if any
	case flag
	when 0	#Press Escape
		#Stopping the processing or unselecting all edges
		return if @algo.robot_interrupt?
		@algo.unselect_all
		onMouseMove_zero
		
	when 1	#Reactivate the same tool
	
	else	#True Undo - Managing rollback
		return if @algo.robot_interrupt?
		UI.start_timer(0.1) { @algo.rollback ; refresh_viewport }
	end		
end

#Setting the proper cursor
def onSetCursor
	if @algo && @algo.hourglass?
		case @algo.hourglass?
		when :red
			ic = @id_cursor_hourglass_red
		when :blue
			ic = @id_cursor_hourglass_blue
		else
			ic = @id_cursor_hourglass_green
		end	
		return UI::set_cursor(ic)
	end	
	ic = @palette.onSetCursor
	return (ic != 0) if ic
	if @invalid_pick
		cursor = @id_cursor_pick_invalid
	elsif @pk_vertex
		cursor = @id_cursor_pick_vertex
	elsif @pk_edge
		cursor = @id_cursor_pick_edge
	elsif @pk_face
		cursor = @id_cursor_pick_face
	elsif @best_picked
		cursor = @id_cursor_pick_invalid
	elsif @algo.get_nb_edges > 0 || @algo.apply_change_visible?
		cursor = @id_cursor_validate
	else
		cursor = @id_cursor_arrow_exit
	end	
	UI::set_cursor cursor
end

#--------------------------------------------------------------
# MENU: Message Management
#--------------------------------------------------------------

#MENU: Contextual menu
def getMenu(menu)
	#Menu Execute or Exit
	if @algo.get_nb_edges > 0 || @algo.apply_change_visible?
		txt = (@algo.apply_change_visible?) ? @mnu_apply_change : @mnu_execute
		menu.add_item(txt) { execute_action }
		menu.add_separator
	end
	menu.add_item(@mnu_exit) { exit_tool }
	menu.add_item(@mnu_unselect_all) { unselect_all }

	#Dialog box for all parameters
	menu.add_separator
	menu.add_item(@mnu_all_param + " (#{T6[:T_KEY_TAB]})") { @algo.ask_all_param }
	
	#Modifiers
	@selmode.contribution_menu(menu)
	
	#Filter of edges
	menu.add_separator
	menu.add_item(@mnu_edge_prop_filter + " : #{G6.edge_filter_text(@algo.parameters_get(:edge_prop_filter))}") { ask_prop_filter }
	
	#Function key menus
	@fkey_strict_offset.create_menu_flag menu, @algo.parameters_get(:strict_offset), true
	unless @tool_type == :bevel
		@fkey_rounding.create_menu_flag menu, @algo.parameters_get(:mode_rounding), true		
	end
	
end

#dialog box for Edge property filter
def ask_prop_filter
	result = G6.ask_edge_prop_filter T6[:MNU_EdgePropFilter], @algo.parameters_get(:edge_prop_filter)
	return unless result
	@algo.parameters_modify(:edge_prop_filter, result)
	refresh_viewport
end

#Restart from scratch
def unselect_all
	@algo.unselect_all
end

#--------------------------------------------------------------
# MESSAGE: Message Management
#--------------------------------------------------------------

#MESSAGE: Toplevel method for maning messages
def show_message
	show_palette_message
	show_status_bar
end

#MESSAGE: Manage the display of the status bar and VCB
def show_status_bar
	return if @algo.hourglass?
	
	#VCB display
	len = Sketchup.format_length @algo.parameters_get(:offset)
	nb = @algo.parameters_get(:numseg)
	if @tool_type == :bevel
		svalue = (len) ? "#{len}" : ""
	else
		svalue = (len) ? "#{len} , #{nb}s" : ""
	end	
	label = @label
	
	#status message
	stext = @title_tool + ': ' + @msg_main
	
	Sketchup::set_status_text stext
	Sketchup::set_status_text label, SB_VCB_LABEL
	Sketchup::set_status_text svalue, SB_VCB_VALUE	
end

#MESSAGE: Compute the message to display in the palette bar
def show_palette_message
	#Overlaps
	if @algo.get_collision_number > 0
		tooltip = @msg_collision.sub("%1", @algo.get_collision_number.to_s)
		mode = 'pink'
		@palette.set_message tooltip, mode
		return
	end
	
	#Mouse if either in the palette or out of the viewport
	if @mouseOut
		@palette.set_message nil
		return
	elsif @mouse_in_palette
		@palette.set_message @palette.get_main_tooltip, 'aliceblue'
		return
	end	
	
	mode = 'white'
	if @algo.hourglass?
		tooltip = @tip_computing
		mode = 'I'
		tooltip = @tip_interrupt
		mode = 'W'
	elsif @invalid_pick
		tooltip = invalid_reason @pk_edge
	elsif @pk_vertex
		tooltip = (@algo.entity_selected?(@pk_vertex)) ? @tip_unselect_vertex : @tip_select_vertex
	elsif @pk_edge
		tooltip = (@algo.entity_selected?(@pk_edge)) ? @tip_unselect_edge : @tip_select_edge
	elsif @pk_face
		tooltip = (@algo.entity_selected?(@pk_face)) ? @tip_unselect_face : @tip_select_face
	elsif @best_picked
		tooltip = @tip_invalid_best
	elsif @algo.get_nb_edges > 0 
		tooltip = @tip_execute
		mode = 'lightgreen'
	elsif @algo.apply_change_visible?
		tooltip = @tip_modify
		mode = 'thistle'
	else
		tooltip = @tip_exit
		mode = 'palegreen'
	end	
	@view.tooltip = tooltip
	if @time_calculation && !@algo.apply_change_visible?
		if !@time_calculation
			mode = 'E'
			tooltip = T6[:TIP_Aborted]
		else
			tooltip = T6[:TIP_Time, sprintf("%4.2f", @time_calculation)]
			mode = 'W'
		end	
	end	
	@palette.set_message tooltip, mode
end

#MESSAGE: Calculate the reason for edge invalid
def invalid_reason(edge)
	case @algo.invalid_reason(edge)
	when '2'
		reason = @tip_wrong_nb_faces + ": #{edge.faces.length}"
	when 'P'
		reason = @tip_wrong_coplanar
	when 'F'
		reason = @tip_wrong_filter
	else
		reason = ""
	end
	tooltip = @tip_invalid
	tooltip += " (#{reason})" if reason != ''
	tooltip
end

#--------------------------------------------------------------
# VIEWPORT: View Management
#--------------------------------------------------------------

#VIEWPORT: Refresh the viewport
def refresh_viewport
	onSetCursor
	show_message
	@view.invalidate
end

#VIEWPORT: Mouse leaves the viewport
def onMouseLeave(view)
	@mouseOut = true
	view.invalidate
end

#VIEWPORT: Mouse enters the viewport
def onMouseEnter(view)
	@mouseOut = false
	view.invalidate
end
	
#VIEWPORT: Before Zooming or changing view
def suspend(view)
	@keyman.reset
	@zoom_void.suspend(view, @xmove, @ymove)
end

#VIEWPORT: After changing view
def resume(view)
	@zoom_void.resume(view)
	refresh_viewport
end

#--------------------------------------------------------------
# KEYBOARD: Keyboard Management
#--------------------------------------------------------------

#KEYBOARD: Manage key events
def key_manage(event, key, view)

	case event
	
	#SHIFT key
	when :shift_down
		
	when :shift_toggle
		
	when :shift_up
		
	#CTRL key	
	when :ctrl_down	
		#@copy_mode_at_down = @copy_mode
		#copy_toggle
	when :ctrl_up
		#copy_set @copy_mode_at_down
	when :ctrl_other_up
		#copy_set @copy_mode_at_down
	
	#ALT key
	when :alt_down

	when :alt_up	
		
	#Arrows	
	when :arrow_down	

	when :arrow_up	
		check_key_golden_axis(key)
		
	#Function_key
	when :function_up
		check_function_key(key)
		
	#Backspace	
	when :backspace

	#TAB	
	when :tab
		@algo.ask_all_param
		
	when :other_up
		#return unless check_function_key(key)
		
	else
		return
	end
	#refresh_viewport
end

#KEYBOARD: Handle key down events
def onKeyDown(key0, rpt, flags, view)
	#Stopping the processing if running
	return if @algo.robot_interrupt?
	
	key = Traductor.check_key key0, flags, false
	
	#Keys for selection modifiers
	return view.invalidate if @selmode.onKeyDown(key, rpt, flags, view)
	
	ret_val = @keyman.onKeyDown(key0, rpt, flags, view)
	@view.invalidate
	ret_val
end

#KEYBOARD: Handle key up events
def onKeyUp(key0, rpt, flags, view)
	key = Traductor.check_key key0, flags, true
	
	return view.invalidate if @selmode.onKeyUp(key, rpt, flags, view)
	
	ret_val = @keyman.onKeyUp(key0, rpt, flags, view)
	@view.invalidate
	ret_val	
end

#KEYBOARD: Enter / Return pressed
def onReturn(view)
	return if @algo.robot_interrupt?
	execute_action
end

#KEYBOARD: Check arrow key for setting Golden axis
def check_key_golden_axis(key)
	axis = nil
	case key
	when VK_RIGHT
		axis = 'X'
	when VK_LEFT
		axis = 'Y'
	when VK_UP
		axis = 'Z'
	when VK_DOWN
		axis = MYDEFPARAM[:DEFAULT_Flag_Axis]
	else
		return false
	end
	@algo.parameters_modify :pivot_axis, axis	
	@view.invalidate
	true
end

#KEYBOARD: Function Keys
def check_function_key(key)
	lskey = []
	lskey.push @fkey_strict_offset
	lskey.push @fkey_rounding unless @tool_type == :bevel
	lskey.each do |fk|
		return true if fk.test_key(key)
	end	
	false
end

#--------------------------------------------------------------
# CLICK: Mouse Buttons Management
#--------------------------------------------------------------

#CLICK: Left Mouse Button DOWN pressed
def onLButtonDown(flags, x, y, view)
	#Interrupting geometry construction if running
	return if @algo.robot_interrupt?
	
	if @palette.onLButtonDown(flags, x, y, view)
		refresh_viewport
		return
	end
	
	@button_down = true
	@x_down = x
	@y_down = y
	entity_picked = [@pk_vertex, @pk_edge, @pk_face].find { |e| e }
	if entity_picked
		add_remove_entity @selmode.entity_picked_from_mode(entity_picked)
	elsif !@invalid_pick && !@best_picked
		execute_action
	end	
	refresh_viewport
end

#CLICK: Left Mouse Button UP pressed
def onLButtonUp(flags, x, y, view)
	if @palette.onLButtonUp(flags, x, y, view)
		refresh_viewport
	end	
end

#CLICK: Double Click
def onLButtonDoubleClick(flags, x, y, view)
	check_entity_picked flags, x, y, view
	entity_picked = [@pk_vertex, @pk_edge, @pk_face].find { |e| e }
	if entity_picked
		entity_picked = (@pk_vertex) ? @pk_vertex.edges[0].all_connected : entity_picked.all_connected
		add_remove_entity entity_picked
	end	
	refresh_viewport
end

#--------------------------------------------------------------
# TOP: Top Execution control
#--------------------------------------------------------------

#TOP: Add or remove entity from selection
def add_remove_entity(lentity)
	@algo.add_remove_entity lentity
	if @algo.get_error_vertex.length > 0
		@palette.set_message @msg_some_errors, 'E'
	else
		#@palette.set_message
	end

end

#TOP: Execute the Rouding Edge operation
def execute_action
	if @algo.get_nb_edges > 0 || @algo.apply_change_visible?
		@no_mark = true
		refresh_viewport
		if @algo.robot_top_execute == :error
			refresh_viewport
		end	
	else
		exit_tool
	end	
end

#TOP: Notification of end of calculation
def end_calculation(time)
	@time_calculation = time
	@time_end = Time.now.to_f
	@palette.set_message
	@no_mark = false
	onMouseMove_zero
end

#TOP: Exit the tool
def exit_tool
	@model.select_tool nil
end

#TOP: Exit the tool
def abort_tool
	Sketchup.undo
	@model.select_tool nil
end

#--------------------------------------------------------------
# MOVE: Move methods
#--------------------------------------------------------------

#MOVE: Mouse Move methods
def onMouseMove_zero ; onMouseMove(0, @xmove, @ymove, @view) if @xmove ; end
def onMouseMove(flags, x, y, view)
	#Store position
	@xmove = x
	@ymove = y
	@flags = flags
	
	#Mouse in palette
	if super
		@mouse_in_palette = true
		refresh_viewport
		return	
	end
	@mouse_in_palette = false
 
	#Synchronize draw and move
	return if @moving
	
	#Selection mode
	@selmode.onMouseMove(flags, x, y, view)
		
	#Picking elements
	check_entity_picked flags, x, y, view
	
	@moving = true
	refresh_viewport
end
	
#MOVE: Determine which element is picked at mouse with check if valid
def check_entity_picked(flags, x, y, view)
	#ph.do_pick x, y
	(@aperture) ? @ph.do_pick(x, y, @aperture) : @ph.do_pick(x, y)
	
	@pk_vertex = @pk_edge = @pk_face = nil
	@invalid_pick = false

	@best_picked = @ph.best_picked
	if @best_picked 
		#Component or Group
		return if @best_picked.class == Sketchup::Group || @best_picked.class == Sketchup::ComponentInstance
			
		#Axes: ignore
		bclass = @best_picked.class
		if bclass != Sketchup::Face && bclass != Sketchup::Edge
			@best_picked = nil
			return
		end	
		
		#Natural geometry		
		@ip.pick view, x, y	
		@pk_vertex = @ip.vertex
		@pk_edge = @ip.edge
		@pk_face = @ip.face
		check_pick_valid
		if @best_picked && !@invalid_pick && (@time_end == nil || (Time.now.to_f - @time_end) > 2.0)
			@time_calculation = nil
			@time_end = nil
		end	
	end
end
	
#MOVE: Check if the entity picked is valid	
def check_pick_valid
	entity = [@pk_vertex, @pk_edge, @pk_face].find { |e| e }
	if entity
		entity2 = @selmode.entity_with_draw_hidden entity
		if entity2 != entity
			entity = @pk_face = entity2
			@pk_vertex = @pk_edge = nil
		end	
		ledge = @selmode.entity_picked_from_mode(entity)
		ledge = (ledge) ? ledge.find_all { |e| @algo.accept_edge?(e) } : []
		@invalid_pick = ((ledge.length == 0) ? true : false)
	else
		@invalid_pick = false
	end	
end
	
#--------------------------------------------------------------
# DRAW: Drawing methods
#--------------------------------------------------------------
	
#DRAW: Drawing method for the Tool
def draw(view)
	#Drawing the mark for modifier
	@selmode.draw_mark(view, @xmove, @ymove) unless @no_mark

	#Drawing all lines
	@algo.get_all_lines_to_draw.each do |ll|
		draw_lines_with_offset view, ll[0], ll[1], ll[2], ll[3]
	end	

	#Vertex in error
	@algo.get_error_vertex.each do |key, v|
		view.draw_points v.position, 10, 2, 'red'
	end	
	
	#Collisions
	draw_collisions view
	
	#Flag for fluidity
	@moving = false
	
	#drawing the palette
	super
end

#DRAW: Draw all selected edges
def draw_lines_with_offset(view, lpt, color, width, stipple)
	return if lpt.length == 0
	lpt = lpt.collect { |pt| G6.small_offset view, pt }
	view.line_width = width
	view.line_stipple = stipple
	view.drawing_color = color
	view.draw GL_LINES, lpt
end

#DRAW: Draw the collision points
def draw_collisions(view)
	#Intersection points
	pts_collision = @algo.get_collision_pt
	return if pts_collision.empty?
	
	view.line_width = 1
	view.line_stipple = ''
	pts_collision.each do |pt|
		pt2d = view.screen_coords pt
		pts = G6.pts_square pt2d.x, pt2d.y, 4
		view.drawing_color = 'orange'
		view.draw2d GL_QUADS, pts
		view.drawing_color = 'red'
		view.draw2d GL_LINE_LOOP, pts
	end
end

#---------------------------------------------------------------------------------------------
# VCB: VCB Management
#---------------------------------------------------------------------------------------------

#VCB: Standard method to accept text in the VCB: Offset distance and nb of segment
def onUserText(text, view)     
	action_from_VCB if @vcb.process(text, @palette)
end

#VCB: Enable or disable the VCB
def enableVCB?
	true
end

#VCB: Initialize VCB
def vcb_init
	@vcb = Traductor::VCB.new
	@vcb.declare_input_format :anglemax, "a"	#angle max
	@vcb.declare_input_format :offset, "l"		#offset
	@vcb.declare_input_format :numseg, "i__s"	#numseg
end

#VCB: Execute actions from the VCB inputs	
def action_from_VCB
	#Getting the values
	anglemax = offset = numseg = nil
	@vcb.each_result do |symb, val, suffix|
		case symb
		when :anglemax
			anglemax = val
		when :offset
			offset = val
		when :numseg
			numseg = val
		end
	end
	
	#Offset
	if offset 
		if offset <= 0
			UI.beep
		else
			@algo.parameters_modify :offset, offset
		end
	end
	
	#Number of segments
	if numseg
		if @tool_type == :bevel || numseg <= 0 || numseg > F6_RoundCorner.max_seg
			UI.beep
		else
			@algo.parameters_modify :numseg, numseg
		end
	end	

	#Angle max
	if anglemax
		if anglemax < 0
			UI.beep
		else
			@selmode.set_anglemax anglemax
		end		
	end
	
	#Refreshing the viewport
	refresh_viewport
end	
	
#VCB: Clean the VCB and status bar area
def vcb_clean
	Sketchup::set_status_text ''
	Sketchup::set_status_text '', SB_VCB_LABEL
	Sketchup::set_status_text '', SB_VCB_VALUE	
end

#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# PALETTE: Palette Management	
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------

#PALETTE: Declare a separator in the main palette
def pal_separator ; @palette.declare_separator ; end
def pal_sepa_bandeau ; @palette.no_bandeau ; @palette.declare_separator ; end

#PALETTE: Initialize the palette
def palette_init
	#Colors
	@color_pal_tit = 'lightblue'
	@color_pal_hi = 'lightgreen'
	@color_pal_edge_prop = 'khaki'
	@color_pal_edge_filter = 'moccasin'
	
	#Initialization
	hshpal = { :width_message => 0, :width_message_min => 150, :key_registry => :roundcorner }
	@palette = Traductor::Palette.new hshpal
	set_palette @palette
	@draw_local = self.method "draw_button_opengl"
	@blason_proc = self.method "draw_button_blason"
	@symb_blason = :blason
		
	#Blason Button
	tip = @title_tool + ' - ' + T6[:T_STR_DefaultParamDialog]
	hsh = { :blason => true, :draw_proc => @blason_proc, :tooltip => tip }
	@palette.declare_button(@symb_blason, hsh) { MYPLUGIN.invoke_default_parameter_dialog }

	#Count of edges and corners and options for Selection
	pal_sepa_bandeau
	palette_bandeau(:selection, T6[:BANDEAU_selection], T6[:BANDEAU_TIP_selection], @color_pal_edge_filter, 'orange')
	palette_edge_corner_count
	palette_selection
	
	#Buttons for Parameters for Rounding
	pal_sepa_bandeau
	palette_bandeau(:parameters, T6[:BANDEAU_parameters], T6[:BANDEAU_TIP_parameters], @color_pal_tit, 'blue')
	palette_parameters
	
	#Buttons for edge property	
	pal_sepa_bandeau
	palette_bandeau(:edge_prop, T6[:BANDEAU_edge_prop], T6[:BANDEAU_TIP_edge_prop], @color_pal_edge_prop, 'burlywood')
	palette_geometry
	
	#Button for execution
	pal_sepa_bandeau
	bk_col_proc = proc { @algo.apply_change_visible? ? 'thistle' : ((@algo.apply_generate_enabled?) ? 'lightgreen' : 'lightgrey') }
	bd_col_proc = proc { @algo.apply_change_visible? ? 'plum' : ((@algo.apply_generate_enabled?) ? 'green' : 'gray') }
	palette_bandeau(:process, T6[:BANDEAU_process], T6[:BANDEAU_TIP_process], bk_col_proc, bd_col_proc)
	palette_process
end

def palette_process
	#Execute and Apply Change
	palette_apply_change
	
	#Rollback
	grayed_proc = proc { !@algo.rollback_enabled? }
	hsh = { :grayed_proc => grayed_proc, :tooltip_proc => T6[:T_STR_UndoCtrlZ], :draw_proc => :rollback }
	@palette.declare_button(:pal_rollback, hsh) { @algo.undo_rollback }
	
	#Abort
	pal_separator
	grayed_proc = proc { !@algo.rollback_enabled? }
	hsh = { :grayed_proc => grayed_proc, :draw_proc => :std_abortexit, :main_color => 'red', :frame_color => 'green', 
	        :tooltip => T6[:T_STR_AbortTool] }
	@palette.declare_button(:pal_abort, hsh) { abort_tool }

	#Exit
	@palette.declare_separator
	hsh = { :tooltip => @mnu_exit, :draw_proc => :std_exit }
	@palette.declare_button(:pal_exit, hsh) { exit_tool }
end

#PALETTE: Bandeau for Selection
def palette_bandeau(symb, text, tip, bk_color, bd_color=nil)
	bd_color = [bd_color, 1] if bd_color && !bd_color.class == Proc
	hsh = { :passive => true, :text => text, :tooltip => tip, 
	        :bk_color => bk_color, :border_color => bd_color }
	@palette.declare_bandeau("bandeau_#{symb}".intern, hsh)
end

#PALETTE: Pick a Stencil in model
def palette_apply_change
	text1 = T6[:BOX_ApplyChange].sub(/\|/, "\n")
	w1, = G6.text_size(text1)
	text2 = T6[:BOX_ApplyGenerate].sub(/\|/, "\n")
	w2, = G6.text_size(text2)
	w = [w1, w2].max + 10
	h = 32
	
	#Apply Change button
	hidden_proc = proc { !@algo.apply_change_visible? }
	grayed_proc = proc { !@algo.parameter_changed? }
	tip = "#{T6[:TIP_ApplyChange]} [#{T6[:T_KEY_Enter]}]"
	hsh = { :hidden_proc => hidden_proc, :tooltip => tip, :text => text1, :height => h, :width => w,
		    :bk_color => 'thistle', :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_apply_change, hsh) { execute_action }
	
	#Apply Generate button
	hidden_proc = proc { @algo.apply_change_visible? }
	grayed_proc = proc { !@algo.apply_generate_enabled? }
	tip = "#{T6[:TIP_ApplyGenerate]} [#{T6[:T_KEY_Enter]}]"
	hsh = { :hidden_proc => hidden_proc, :tooltip => tip, :text => text2, :height => h, :width => w,
		    :bk_color => 'lightgreen', :grayed_proc => grayed_proc }
	@palette.declare_button(:pal_apply_generate, hsh) { execute_action }	
end

#PALETTE: Buttons for counters of edges and corners
def palette_edge_corner_count
	tip_nb_edges = T6[:TIP_NumberEdges]
	tip_nb_corners = T6[:TIP_NumberCorners]
	lcolor = 'tan'
	vcolor = 'tan'
	
	hshc = { :width => 16, :height => 16, :passive => true, :draw_proc => @draw_local, :bk_color => lcolor }
	hsh = { :tooltip => tip_nb_edges, :rank => 1  }
	@palette.declare_button(:pal_nb_edges_title, hshc, hsh)
	hsh = { :tooltip => tip_nb_corners  }
	@palette.declare_button(:pal_nb_corners_title, hshc, hsh)

	hshc = { :width => 24, :height => 16, :passive => true, :bk_color => vcolor }
	text_proc = proc { @algo.get_nb_edges.to_s }
	hsh = { :tooltip => tip_nb_edges, :text_proc => text_proc, :rank => 1  }
	@palette.declare_button(:pal_nb_edges_value, hshc, hsh)
	text_proc = proc { @algo.get_nb_corners.to_s }
	hsh = { :tooltip => tip_nb_corners, :text_proc => text_proc }
	@palette.declare_button(:pal_nb_corners_value, hshc, hsh)
end

#PALETTE: Buttons related to Selection
def palette_selection
	pal_separator
	
	#Unselect All
	hsh = { :tooltip => @mnu_unselect_all, :draw_proc => :cross_NE3, :main_color => 'red' }
	@palette.declare_button(:pal_unselect_all, hsh) { unselect_all }
	
	#Modifiers for Selection mode	
	@selmode.contribute_palette @palette

	#Edge filters
	@palette.declare_separator
	proc = proc { @algo.parameters_get :edge_prop_filter }
	ttip = T6[:MNU_EdgePropFilter] + "\n" + G6.edge_filter_text(@edge_prop_filter_default)
	hsh = { :value_proc => proc, :text => T6[:MNU_EdgePropFilter2], :tooltip => ttip, :bk_color => 'moccasin',
	        :main_color => 'blue', :default_value => @edge_prop_filter_default }
	@palette.declare_edge_prop(:pal_filter, nil, hsh) { @algo.parameters_modify :edge_prop_filter, @palette.button_get_value(:pal_filter) }
end

#PALETTE: Buttons for edge properties of generated edges
def palette_geometry
	#Border properties
	bk_color = @color_pal_edge_prop
	value_proc = proc { @algo.parameters_get :prop_border }
	ttip = T6[:TIP_EdgePropBorder] + "\n" + G6.edge_filter_text(@edge_prop_border_default)
	hsh = { :value_proc => value_proc, :text => T6[:MNU_EdgePropBorder], :tooltip => ttip, :bk_color => bk_color,
	        :main_color => 'blue', :edge_prop => 'SM', :default_value => @edge_prop_border_default}
	@palette.declare_edge_prop(:pal_prop_border, nil, hsh) { @algo.parameters_modify :prop_border, @palette.button_get_value(:pal_prop_border) }
	@palette.declare_separator

	#Corner properties
	pal_separator
	value_proc = proc { @algo.parameters_get :prop_corner }
	ttip = T6[:TIP_EdgePropCorner] + "\n" + G6.edge_filter_text(@edge_prop_corner_default)
	hsh = { :value_proc => value_proc, :text => T6[:MNU_EdgePropCorner], :tooltip => ttip, :bk_color => bk_color,
	        :main_color => 'blue', :edge_prop => 'SM', :default_value => @edge_prop_corner_default}
	@palette.declare_edge_prop(:pal_prop_corner, nil, hsh) { @algo.parameters_modify :prop_corner, @palette.button_get_value(:pal_prop_corner) }
	@palette.declare_separator

	#Round Edges properties
	unless @tool_type == :bevel
		pal_separator
		value_proc = proc { @algo.parameters_get :prop_round }
		ttip = T6[:TIP_EdgePropRound] + "\n" + G6.edge_filter_text(@edge_prop_round_default)
		hsh = { :value_proc => value_proc, :text => T6[:MNU_EdgePropRound], :tooltip => ttip, :bk_color => bk_color,
				:main_color => 'blue', :edge_prop => 'SMH', :default_value => @edge_prop_round_default }
		@palette.declare_edge_prop(:pal_prop_round, nil, hsh) { @algo.parameters_modify :prop_round, @palette.button_get_value(:pal_prop_round) }
	end	
end

#PALETTE: Buttons for edge properties of generated edges
def palette_parameters
	#Sign for Parameters
	pal_separator
	
	#Letter param save and restore
	@palette.declare_separator if @persist_letters.length > 0
	#@persist_letters.each do |letter|
	letter = 'A'
	for i in 0..F6_RoundCorner.letter_max-1
		palette_letter_button(letter, i)
		letter = letter.next
	end
	
	#Parameter buttons
	palette_offset
	palette_number_segments
	
	#Strict offset
	@palette.declare_separator
	proc = proc { @algo.parameters_get :strict_offset }
	tip = "#{@mnu_strict_offset} [#{@fkey_strict_offset.fkey}]"
	hsh = { :main_color => 'green', :draw_scale => 0.6 }
	hshb = { :value_proc => proc, :draw_proc => @draw_local, :tooltip => tip }
	@palette.declare_button(:pal_strict_offset, hsh, hshb) { @algo.parameters_toggle :strict_offset }	

	#Rounding option
	unless @tool_type == :bevel
		proc = proc { @algo.parameters_get :mode_rounding }
		hsh = { :main_color => 'green', :draw_scale => 0.6 }
		tip = "#{@mnu_rounding} [#{@fkey_rounding.fkey}]"
		hshb = { :value_proc => proc, :draw_proc => @draw_local, :tooltip => tip }
		@palette.declare_button(:pal_rounding, hsh, hshb) { @algo.parameters_toggle :mode_rounding }	
	end
	
	#Axis for pivot
	@palette.declare_separator
	palette_golden_axis
end

#PALETTE: Draw the button for golden axis
def palette_golden_axis
	symb_master = :pal_golden_axis	
	
	#Creating the title button
	hgt = 16
	hsh = { :type => 'multi_free', :passive => true, :text => T6[:BOX_Pivot], :tooltip => @tip_axis, :height => hgt,
			:bk_color => @color_pal_tit }
	@palette.declare_button(symb_master, hsh)
		
	#Creating the buttons
	hshp = { :parent => symb_master, :height => hgt, :width => 20, :hi_color => 'white', :draw_proc => @draw_local}
	
	dexproc = proc { { "Vec" => @algo.parameters_get_golden_axis } }
	hsh = { :tooltip => @mnu_axis, :draw_proc => :std_axis, :tooltip => @tip_axis, :passive => true,
			:draw_refresh => true, :draw_extra_proc => dexproc }
	@palette.declare_button("#{symb_master}__show", hshp, hsh) 

	value_proc = proc { @algo.parameters_get(:pivot_axis) == 'X' }
	hsh = { :text => 'X', :tooltip => @tip_plane_x, :bk_color => 'tomato', :value_proc => value_proc  }
	@palette.declare_button("#{symb_master}__x".intern, hshp, hsh) { @algo.parameters_modify(:pivot_axis, 'X') }

	value_proc = proc { @algo.parameters_get(:pivot_axis) == 'Y' }
	hsh = { :text => 'Y', :tooltip => @tip_plane_y, :bk_color => 'limegreen', :value_proc => value_proc  }
	@palette.declare_button("#{symb_master}__y".intern, hshp, hsh) { @algo.parameters_modify(:pivot_axis, 'Y') }

	value_proc = proc { @algo.parameters_get(:pivot_axis) == 'Z' }
	hsh = { :text => 'Z', :tooltip => @tip_plane_z, :bk_color => 'skyblue', :value_proc => value_proc  }
	@palette.declare_button("#{symb_master}__z".intern, hshp, hsh) { @algo.parameters_modify(:pivot_axis, 'Z') }	
end

#PALETTE: Button for a letter	
def palette_letter_button(letter, i)
	pal_set = ('pal_set_' + letter).intern
	hidden_proc = proc { !@persist_letters[i] }
	grayed_proc = proc { !@algo.parameters_letter_available?(letter) }
	tip_proc = proc { @algo.parameters_tip_from_letter(letter) }
	hsh = { :height => 16, :width => 16, :rank => 1, :text => letter, :grayed_proc => grayed_proc, 
			:tip_proc => tip_proc, :bk_color => 'gold', :hidden_proc => hidden_proc }
	@palette.declare_button(pal_set, hsh) { @algo.parameters_letter_restore letter }
	
	pal_save = ('pal_save_' + letter).intern
	hsh = { :height => 16, :width => 16, :draw_proc => :std_disk, :main_color => 'yellow', 
			:tooltip => T6[:TIP_SaveLetter, letter], :hidden_proc => hidden_proc  }
	@palette.declare_button(pal_save, hsh) { @algo.parameters_letter_save letter }		
end	
	
#PALETTE: Button for offset
def palette_offset
	pal_separator

	#Title button
	title = T6[:T_TXT_Offset]
	wid, = G6.simple_text_size(title)
	wid = [70, wid].max
	tip = T6[:TIP_Offset]
	prompt = T6[:PROMPT_Offset]

	hsh_dim = { :height => 16, :width => wid }
	hsht = { :passive => true, :text => title, :bk_color => @color_pal_tit, :tooltip => tip, :rank => 1 }
	@palette.declare_button :pal_offset_title, hsh_dim, hsht
	
	#Input field
	hshi = { :vtype => :len, :vprompt => prompt }
	get_proc = proc { @algo.parameters_get :offset }
	set_proc = proc { |val| @algo.parameters_modify :offset, val }
	show_proc = proc { |val| Sketchup.format_length val }
	input = Traductor::InputField.new hshi, { :get_proc => get_proc, :set_proc => set_proc, :show_proc => show_proc }
	
	hsh = { :bk_color => @color_pal_hi, :input => input, :tooltip => tip }
	@palette.declare_button :pal_offset_value, hsh_dim, hsh 
end

#PALETTE: Buttons for the number of Segments
def palette_number_segments
	return if @tool_type == :bevel
	
	pal_separator

	#Title button
	title = T6[:BOX_NumSeg]
	wid, = G6.simple_text_size(title)
	wid = [60, wid].max
	tip = @tip_numseg
	prompt = T6[:PROMPT_NumSeg]

	hsh_dim = { :height => 16, :width => wid }
	hsht = { :passive => true, :text => title, :bk_color => @color_pal_tit, :tooltip => tip, :rank => 1 }
	@palette.declare_button :pal_numseg_title, hsh_dim, hsht
	
	#Input field
	hshi = { :vtype => :integer, :vprompt => prompt, :vmin => 1, :vmax => 24, :vincr => 2 }
	get_proc = proc { @algo.parameters_get :numseg }
	set_proc = proc { |val| @algo.parameters_modify :numseg, val }
	show_proc = proc { |val| "#{val}s" }
	hsh = { :get_proc => get_proc, :set_proc => set_proc, :show_proc => show_proc }
	input = Traductor::InputField.new hshi, hsh
	
	hsh = { :bk_color => @color_pal_hi, :input => input, :tooltip => tip }
	@palette.declare_button :pal_numseg_value, hsh_dim, hsh 
end

#PALETTE: Drawing the Blason
def draw_button_blason(symb, dx, dy)
	lst_gl = []
	dx2 = dx/2
	dy2 = dy/2
	dx4 = dx/4
	dy4 = dy/4
	
	frcolor = 'gray'
	size = dx2
	decx = 6
	dect = 6
	decb = 8
	
	#Main triangle
	pvt = Geom::Point3d.new dx2, dy-dect
	pvl = Geom::Point3d.new decx, decb
	pvr = Geom::Point3d.new dx-decx, decb
	
	#Specific part for each tool
	case @tool_type
	when :bevel
		frcolor = 'olivedrab'
		triangle = [pvt, pvl, pvr]
		lst_gl.push [GL_LINE_LOOP, triangle, frcolor, 3, '']		
	when :sharp
		frcolor = 'skyblue'
		ptmid = Geom::Point3d.new dx2, dy2
		pts = [pvt, ptmid, pvl, ptmid, pvr, ptmid]
		lst_gl.push [GL_LINES, pts, frcolor, 3, '']
	else
		dec = 2
		frcolor = 'orange'
		ptb1 = Geom::Point3d.new dx2, pvl.y-dec
		ptml = Geom.linear_combination 0.75, pvt, 0.25, pvl
		ptl1 = Geom::Point3d.new ptml.x - dec, ptml.y + dec
		ptml = Geom.linear_combination 0.25, pvt, 0.75, pvl
		ptl2 = Geom::Point3d.new ptml.x - dec, ptml.y + dec
		
		ptml = Geom.linear_combination 0.75, pvl, 0.25, pvr
		ptb1 = Geom::Point3d.new ptml.x, ptml.y - dec
		ptml = Geom.linear_combination 0.25, pvl, 0.75, pvr
		ptb2 = Geom::Point3d.new ptml.x, ptml.y - dec
		
		ptml = Geom.linear_combination 0.75, pvr, 0.25, pvt
		ptr1 = Geom::Point3d.new ptml.x + dec, ptml.y + dec
		ptml = Geom.linear_combination 0.25, pvr, 0.75, pvt
		ptr2 = Geom::Point3d.new ptml.x + dec, ptml.y + dec
		
		pts = [pvt, ptl1, ptl2, pvl, ptb1, ptb2, pvr, ptr1, ptr2]
		lst_gl.push [GL_LINE_LOOP, pts, frcolor, 3, '']
	end

	#Borders
	len = 5
	lines = []
	lines.push pvl, pvl.offset(Y_AXIS, -len)
	lines.push pvl, pvl.offset(X_AXIS.reverse + Y_AXIS, len)
	lines.push pvr, pvr.offset(Y_AXIS, -len)
	lines.push pvr, pvr.offset(X_AXIS + Y_AXIS, len)
	lines.push pvt, pvt.offset(X_AXIS.reverse + Y_AXIS, len)
	lines.push pvt, pvt.offset(X_AXIS + Y_AXIS, len)
	lst_gl.push [GL_LINES, lines, 'gray', 1, '']	
	
	lst_gl
end

#PALETTE: Custom drawing of buttons
def draw_button_opengl(symb, dx, dy)
	code = symb.to_s
	lst_gl = []
	dx2 = dx / 2
	dy2 = dy / 2
	
	case code
	
	#Edges count
	when /nb_edges/i
		dec = 2
		lpti = [[1, 1+dec], [dx-1, dy-1-dec]]
		pts = lpti.collect { |a| Geom::Point3d.new(*a) }
		lst_gl.push [GL_LINE_STRIP, pts, 'green', 5, '']		
		lst_gl.push [GL_LINE_STRIP, pts, 'red', 2, '']		
	
	#Corners count
	when /nb_corners/i
		pivot = [1, dy2+4]
		lpti = [[1, 1], pivot, pivot, [dx+3, dy-1], pivot, [dx-1, 1]]
		pts = lpti.collect { |a| Geom::Point3d.new(*a) }
		tri = [pts[0], pts[1], pts.last, pts.last, pts[1], pts[3]]
		lst_gl.push [GL_TRIANGLES, tri, 'moccasin']			
		lst_gl.push [GL_LINES, pts, 'green', 5, '']
		lst_gl.push [GL_LINES, pts, 'red', 2, '']
	
	#Strict Offset
	when /pal_strict_offset/i
		pts = []
		pts.push Geom::Point3d.new(dx2, 2, 0)
		pts.push Geom::Point3d.new(dx2, dy-2, 0)
		lst_gl.push [GL_LINE_STRIP, pts + [pts[0]], @color_edges, 2]
		pts = []
		pts.push Geom::Point3d.new(dx2-7, 2, 0)
		pts.push Geom::Point3d.new(dx2-7, dy-2, 0)
		lst_gl.push [GL_LINE_STRIP, pts + [pts[0]], @color_borders, 2]
		pts = []
		pts.push Geom::Point3d.new(dx2+7, 2, 0)
		pts.push Geom::Point3d.new(dx2+7, dy-2, 0)
		lst_gl.push [GL_LINE_STRIP, pts + [pts[0]], @color_borders, 2]

	#Rounding option	
	when /pal_rounding/i
		pts = []
		pts.push Geom::Point3d.new(2, dy-2, 0)
		pts.push Geom::Point3d.new(2, 2, 0)
		pts.push Geom::Point3d.new(dx-2, 2, 0)
		lst_gl.push [GL_LINE_STRIP, pts, @color_edges, 2, '']
		pts = []
		n = 7
		angle = Math::PI * 0.5 / n
		r = dx * 0.6
		cx = dx - 2
		cy = dy - 2
		for i in 0..n
			pts.push Geom::Point3d.new(cx - Math.sin(angle * i) * r, cy - Math.cos(angle * i) * r, 0)
		end	
		lst_gl.push [GL_LINE_STRIP, pts, @color_borders, 2, '']
		
	end
	
	lst_gl
end

end	#class RoundCornerTool
	
end	#End Module F6_RoundCorner
