#!/usr/bin/tclsh
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )

############################################################################
#    Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera     #
#    martin.osmera@gmail.com                                               #
#                                                                          #
#    This program is free software; you can redistribute it and#or modify  #
#    it under the terms of the GNU General Public License as published by  #
#    the Free Software Foundation; either version 2 of the License, or     #
#    (at your option) any later version.                                   #
#                                                                          #
#    This program is distributed in the hope that it will be useful,       #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#    GNU General Public License for more details.                          #
#                                                                          #
#    You should have received a copy of the GNU General Public License     #
#    along with this program; if not, write to the                         #
#    Free Software Foundation, Inc.,                                       #
#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
############################################################################

# >>> File inclusion guard
if { ! [ info exists _CUSTOM_COMMANDS_CONFIG_TCL ] } {
set _CUSTOM_COMMANDS_CONFIG_TCL _
# <<< File inclusion guard

# --------------------------------------------------------------------------
# DESCRIPTION
# Implements custom commands configuration dialog
# --------------------------------------------------------------------------

namespace eval custom_commands {
	variable win			;# ID of toplevel dialog window
	variable dialog_opened	0	;# Bool: True if this dialog is already opened

	# Font for text widgets
	variable cmd_font [font create				\
		-family $::DEFAULT_FIXED_FONT			\
		-size [expr {int(-12 * $::font_size_factor)}]	\
		-weight bold					\
	]

	variable text_0		;# ID of text widget for command 0
	variable text_1		;# ID of text widget for command 1
	variable text_2		;# ID of text widget for command 2

	variable description	;# Array: Command description (-textvariable) (idx: 0..2)
	variable cmfr_dialog	;# Array of Bool: Variable for checkbutton "Confirmation dialog"
	variable results_dialog	;# Array of Bool: Variable for checkbutton "Show results"
	variable ignore_errors	;# Array of Bool: Variable for checkbutton "Ignore errors"
	variable run_in_term	;# Array of Bool: Variable for checkbutton "Ignore errors"

	## Create the dialog
	 # @parm Int tab_number=0 - number of tab to raise
	 # @return void
	proc mkDialog {{tab_number 0}} {
		variable win		;# ID of toplevel dialog window
		variable dialog_opened	;# Bool: True if this dialog is already opened
		variable cmd_font	;# Font for text widgets

		variable text_0		;# ID of text widget for command 0
		variable text_1		;# ID of text widget for command 1
		variable text_2		;# ID of text widget for command 2

		variable description	;# Array: Command description (-textvariable) (idx: 0..2)
		variable cmfr_dialog	;# Array of Bool: Variable for checkbutton "Confirmation dialog"
		variable results_dialog	;# Array of Bool: Variable for checkbutton "Show results"
		variable ignore_errors	;# Array of Bool: Variable for checkbutton "Ignore errors"
		variable run_in_term	;# Array of Bool: Variable for checkbutton "Ignore errors"

		# Destroy the dialog if it's already opened
		if {$dialog_opened} {
			destroy .custom_commands_config_dialog
		}
		set dialog_opened 1

		# Create toplevel window
		set win [toplevel .custom_commands_config_dialog -class {Configuration dialog} -bg ${::COMMON_BG_COLOR}]

		# Create window header
		label $win.header_label			\
			-compound left			\
			-image ::ICONS::22::gear	\
			-text [mc "Edit custom commands"]	\
			-font [font create -size [expr {int(-20 * $::font_size_factor)}]]

		# Create notebook
		set nb [ModernNoteBook $win.nb]

		# Create notebook tabs
		for {set idx 0} {$idx < 3} {incr idx} {
			# Create tab
			set tab [$nb insert end tab_$idx -image ::ICONS::22::gear$idx]			

			# Create "Short description" (entry and label)
			pack [Label $tab.desc_label		\
				-text [mc "Short description"]	\
				-helptext [mc "This string will be used as status bar tip (max. 100 chars)"]
			] -anchor w -padx 5 -pady 5
			pack [ttk::entry $tab.desc_entry						\
				-validate key								\
				-textvariable ::configDialogues::custom_commands::description($idx)	\
				-validatecommand {::configDialogues::custom_commands::desc_validate %P}	\
			] -fill x -padx 5

			## Create options labelframe
			label $tab.labelframe_label -compound left -image ::ICONS::16::configure -text [mc "Options"]
			set frame [ttk::labelframe $tab.labelframe -labelwidget $tab.labelframe_label]
			 # Create checkbutton "Confirmation dialog"
			set button [checkbutton $frame.cmfr_cbutton -anchor w			\
				-text [mc "Confirmation dialog"]				\
				-variable ::configDialogues::custom_commands::cmfr_dialog($idx)	\
			]
			grid $button -sticky w -row 1 -column 1 -padx 5 -pady 2
			DynamicHelp::add $button -text [mc "Invoke dialog to confirm command execution."]
			 # Create checkbutton "Show results"
			set button [checkbutton $frame.results_cbutton					\
				-text [mc "Show results"] -anchor w					\
				-variable ::configDialogues::custom_commands::results_dialog($idx)	\
			]
			grid $button -sticky w -row 2 -column 1 -padx 5 -pady 2
			DynamicHelp::add $button -text [mc "After finish show dialog with results."]
			 # Create checkbutton "Ignore errors"
			set button [checkbutton $frame.ignore_cbutton				\
				-text [mc "Ignore errors"] -anchor w				\
				-variable ::configDialogues::custom_commands::ignore_errors($idx)	\
			]
			grid $button -sticky w -row 1 -column 2 -padx 5 -pady 2
			DynamicHelp::add $button -text [mc "Do not invoke error dialog if the process fails."]
			 # Create checkbutton "Run in terminal"
			set button [checkbutton $frame.run_in_term_button				\
				-text [mc "Run in terminal"] -anchor w					\
				-variable ::configDialogues::custom_commands::run_in_term($idx)	\
			]
			grid $button -sticky w -row 2 -column 2 -padx 5 -pady 2
			DynamicHelp::add $button -text [mc "Run interactively in terminal emulator."]
			if {!$::PROGRAM_AVAILABLE(urxvt)} {
				$button configure -state disabled
			}
			pack $frame -fill x -pady 10 -padx 5

			# Create label "Commands to execute" and help button
			set frame [frame $tab.cmd_label_frame]
			pack [label $frame.label			\
				-text [mc "Bash script to execute."]	\
			] -side left -padx 5
			pack [ttk::button $frame.button					\
				-image ::ICONS::16::help				\
				-style Flat.TButton					\
				-command {::configDialogues::custom_commands::show_help}	\
			] -side right
			DynamicHelp::add $frame.button	\
				-text [mc "Show help"]
			pack $frame -fill x

			# Create text for entering commands
			set frame [frame $tab.text_frame]
			set text [text $frame.text			\
				-background {#FFFFFF}			\
				-width 1 -height 1			\
				-font $cmd_font -undo 1			\
				-yscrollcommand "$frame.scrollbar set"	\
			]
			pack $text -side left -fill both -expand 1
			pack [ttk::scrollbar $frame.scrollbar	\
				-orient vertical		\
				-command "$text yview"		\
			] -side right -fill y
			pack $frame -fill both -expand 1 -padx 5

			# Set NS variable -- text widget reference
			set text_$idx $text

			# Get settins from the program
			if {[regexp {\s*[01]\s+[01]\s+[01]\s+[01]\s*} $::X::custom_command_options($idx)]} {
				set cmfr_dialog($idx)		[lindex $::X::custom_command_options($idx) 0]
				set results_dialog($idx)	[lindex $::X::custom_command_options($idx) 1]
				set ignore_errors($idx)		[lindex $::X::custom_command_options($idx) 2]
				set run_in_term($idx)		[lindex $::X::custom_command_options($idx) 3]
			}

			set description($idx) $::X::custom_command_desc($idx)
			$text insert end $::X::custom_command_cmd($idx)
		}

		# Raise tab
		$nb raise [lindex [$nb pages] $tab_number]

		# Create button frame at the bottom
		set but_frame [frame $win.button_frame]
			# Button "Ok"
		pack [ttk::button $but_frame.but_ok			\
			-text [mc "Ok"]					\
			-compound left					\
			-image ::ICONS::16::ok				\
			-command {::configDialogues::custom_commands::OK}	\
		] -side right -padx 2 -pady 2
			# Button "Cancel"
		pack [ttk::button $but_frame.but_cancel				\
			-text [mc "Cancel"]					\
			-compound left						\
			-image ::ICONS::16::button_cancel			\
			-command {::configDialogues::custom_commands::CANCEL}	\
		] -side right -padx 2 -pady 2

		# Pack frames and notebook
		pack $but_frame -side bottom -fill x -expand 0 -anchor s -padx 10 -pady 5
		pack $win.header_label -side top -pady 6
		pack [$nb get_nb] -side top -fill both -expand 1 -padx 10

		# Finalize dialog creation
		wm iconphoto $win ::ICONS::16::configure
		wm transient $win .
		wm title $win [mc "Edit custom commands - %s" ${::APPNAME}]
		wm minsize $win 460 400
		raise $win
		catch {grab $win}
		wm protocol $win WM_DELETE_WINDOW {
			::configDialogues::custom_commands::CANCEL
		}
		tkwait window $win
	}

	## Show help window
	 # @return void
	proc show_help {} {
		# Destroy previous help window
		if {[winfo exists .custom_commands_help]} {
			destroy .custom_commands_help
			return
		}
		set x [expr {[winfo pointerx .] - 400}]
		set y [winfo pointery .]

		# Create new help window
		set win [toplevel .custom_commands_help -class {Help} -bg ${::COMMON_BG_COLOR}]
		set frame [frame $win.f -bg {#555555} -bd 0 -padx 1 -pady 1]
		wm overrideredirect $win 1

		# Click to close
		bind $win <Button-1> "grab release $win; destroy $win"

		# Create header "-- click to close --"
		pack [label $frame.lbl_header			\
			-text [mc "-- click to close --"]	\
			-bg {#FFFF55} -font $::smallfont	\
			-fg {#000000} -anchor c			\
		] -side top -anchor c -fill x

		# Create text widget
		set text [text $frame.text	\
			-bg {#FFFFCC}		\
			-exportselection 0	\
			-takefocus 0		\
			-cursor left_ptr	\
			-bd 0 -relief flat	\
		]

		pack $frame -fill both -expand 1

		# Create text tags
		$text tag configure tag_bold_small				\
			-font [font create					\
				-weight bold					\
				-size [expr {int(-12 * $::font_size_factor)}]	\
				-family $::DEFAULT_FIXED_FONT			\
			]
		$text tag configure tag_bold_big				\
			-foreground {#0000DD} -underline 1 			\
			-font [font create					\
				-weight bold					\
				-size [expr {int(-14 * $::font_size_factor)}]	\
				-family $::DEFAULT_FIXED_FONT			\
			]

		# Fill in the text widget
		$text insert end [mc "VARIABLES:"]
		$text tag add tag_bold_big {insert linestart} {insert lineend}
		$text insert end "\n  %URI"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tThe full URI of the current file\n"]
		$text insert end "  %URIS"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tList of the URIs of all open documents\n"]
		$text insert end "  %directory"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tProject directory\n"]
		$text insert end "  %filename"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tThe file name of the current document\n"]
		$text insert end "  %basename"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tSame as %filename, but without extension\n"]
		$text insert end "  %mainfile"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tName of project main file\n"]
		$text insert end "  %line"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tNumber of the current line\n"]
		$text insert end "  %column"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tNumber of the current column\n"]
		$text insert end "  %selection"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tThe selected text in the current file\n"]
		$text insert end "  %text"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tThe full text of the current file\n"]
		$text insert end "  %%"
		$text tag add tag_bold_small {insert linestart} {insert lineend}
		$text insert end [mc "\t\tPercent sign\n\n"]
		$text insert end [mc "Variables %line, %column, %selection and %text"]
		foreach start {10 17 26 41} end {15 24 36 46} {
			$text tag add tag_bold_small			\
				[list insert linestart+${start}c]	\
				[list insert linestart+${end}c]
		}
		$text insert end [mc "\nare not available if external editor is used"]

		# Show the text widget
		$text configure -state disabled
		pack $text -side bottom -fill both -expand 1

		# Set window attributes
		wm geometry $win "=420x330+$x+$y"
		wm protocol $win WM_DELETE_WINDOW "
			grab release $win
			destroy $win
			grab .custom_commands_config_dialog"
		wm transient $win .custom_commands_config_dialog
		raise $win
		update
		catch {
			grab -global $win
		}
		tkwait window $win
	}

	## Validate content of entry "Description"
	 # @parm String content - String to validate
	 # @return Bool - result
	proc desc_validate {content} {
		if {[string length $content] > 100} {
			return 0
		} else {
			return 1
		}
	}

	## Change content of configuration variables
	 # @return void
	proc use_settings {} {
		variable description	;# Array: Command description (-textvariable) (idx: 0..2)
		variable cmfr_dialog	;# Array of Bool: Variable for checkbutton "Confirmation dialog"
		variable results_dialog	;# Array of Bool: Variable for checkbutton "Show results"
		variable ignore_errors	;# Array of Bool: Variable for checkbutton "Ignore errors"
		variable run_in_term	;# Array of Bool: Variable for checkbutton "Ignore errors"

		variable text_0		;# ID of text widget for command 0
		variable text_1		;# ID of text widget for command 1
		variable text_2		;# ID of text widget for command 2

		for {set i 0} {$i < 3} {incr i} {
			# Change content of configuration variables
			set ::X::custom_command_options($i)	\
				"$cmfr_dialog($i) $results_dialog($i) $ignore_errors($i) $run_in_term($i)"
			set ::X::custom_command_desc($i) $description($i)
			set ::X::custom_command_cmd($i) [regsub {\n$} [[subst -nocommands "\$text_${i}"] get 1.0 end] {}]

			# Change status tips
			if {[winfo exists .mainIconBar.custom$i]} {
				setStatusTip				\
					-widget .mainIconBar.custom$i	\
					-text [mc "Custom command %s: %s" $i $description($i)]
				::DynamicHelp::add .mainIconBar.custom$i -text [mc "Custom command %s: %s" $i $description($i)]
			}
		}
	}

	## Save configuration to config file
	 # @return void
	proc save_config {} {
		# Save settings
		for {set i 0} {$i < 3} {incr i} {
			::settings setValue "Custom command $i/options"		\
				$::X::custom_command_options($i)
			::settings setValue "Custom command $i/description"	\
				$::X::custom_command_desc($i)
			::settings setValue "Custom command $i/command"		\
				$::X::custom_command_cmd($i)
		}

		# Commit
		::settings saveConfig
	}

	## Load configuratin from config file
	 # @return void
	proc load_config {} {
		for {set i 0} {$i < 3} {incr i} {
			# Options
			set def_options $::X::custom_command_options($i)
			set ::X::custom_command_options($i)	[::settings	\
				getValue "Custom command $i/options"		\
				$::X::custom_command_options($i)]
			if {![regexp {\s*[01]\s+[01]\s+[01]\s+[01]\s*} $::X::custom_command_options($i)]} {
				puts stderr "Invalid custom command options, setting to defaults."
				set ::X::custom_command_options($i) $def_options
			}
			if {!$::PROGRAM_AVAILABLE(urxvt)} {
				set ::X::custom_command_options($i) [lreplace $::X::custom_command_options($i) 3 3 0]
			}
			# Description
			set ::X::custom_command_desc($i)	[::settings	\
				getValue "Custom command $i/description"	\
				$::X::custom_command_desc($i)]
			# Command
			set ::X::custom_command_cmd($i)		[::settings	\
				getValue "Custom command $i/command"		\
				$::X::custom_command_cmd($i)]
		}
	}

	## Take back changes and destroy dialog window
	 # @return void
	proc CANCEL {} {
		variable win		;# ID of dialog toplevel window
		variable dialog_opened	;# Bool: True if this dialog is already opened

		# Get rid of dialog window
		set dialog_opened 0
		grab release $win
		destroy $win
	}

	## Apply changes and destroy dialog window
	 # @return void
	proc OK {} {
		variable win		;# ID of dialog toplevel window

		# Apply new settings
		use_settings		;# Adjust NS variables
		save_config		;# Save new config

		# Get rid of the dialog window
		CANCEL
	}
}

# >>> File inclusion guard
}
# <<< File inclusion guard
