# $Id: chattoolbar.tcl 502 2011-12-20 14:28:08Z rejjin $
# Chattoolbar - plugin for Tkabber.
# Written by Renji <webrenji@gmail.com>
# See README for details.

package require msgcat
package require Img

event add <<ChattoolbarState>> <Control-b> <Control-B> <Control-Egrave> <Control-egrave>

namespace eval chattoolbar {
variable user_variable
variable stored_variable
variable iconTable

	::msgcat::mcload [file join [file dirname [info script]] msgs]
	source [file join [file dirname [info script]] icon-table.tcl]
	
	custom::defgroup Plugins [::msgcat::mc "Plugins options."] -group Tkabber	
	custom::defgroup ChatToolbar [::msgcat::mc "ChatToolbar options."] -group Plugins	
	
	custom::defvar user_variable(toolbar_button) 1 \
		[::msgcat::mc "Create button on toolbar."] \
		-group ChatToolbar -type boolean \
		-command [namespace current]::state_toolbar_button
	custom::defvar user_variable(chat_active) 1 \
		[::msgcat::mc "Enable for chats."] \
		-group ChatToolbar -type boolean \
		-command [namespace current]::redraw_all_chats
	custom::defvar user_variable(groupchat_active) 1 \
		[::msgcat::mc "Enable for groupchats."] \
		-group ChatToolbar -type boolean \
		-command [namespace current]::redraw_all_chats
	custom::defvar user_variable(auto_show) 1 \
		[::msgcat::mc "Automatically open the toolbar at the entrance to the room."] \
		-group ChatToolbar -type boolean 
	custom::defvar user_variable(spacing) 1 \
		[::msgcat::mc "Distance between the buttons."] \
		-group ChatToolbar -type integer \
		-command [namespace current]::redraw_all_chats
	
	custom::defvar stored_variable(activate_chats) {} {} \
	-group Hidden -type string 
	custom::defvar stored_variable(sort_index) {} {} \
	-group Hidden -type string 
	custom::defvar stored_variable(button_state) {} {} \
	-group Hidden -type string 
	custom::defvar stored_variable(toolbar_btn_index) -1 {} \
	-group Hidden -type string 	
	
	foreach id $iconTable(id_list) {
	image create photo plugins/chattoolbar/$id \
		-data $iconTable(icon,$id)
	}

	image create photo plugins/chattoolbar/toolbar \
	-data $iconTable(toolbar)
	
	image create photo plugins/chattoolbar/up \
	-data $iconTable(up_arrow)
	image create photo plugins/chattoolbar/down \
	-data $iconTable(down_arrow)
	
	hook::add open_chat_post_hook [namespace current]::setup_toolbar
	hook::add finload_hook [namespace current]::add_toolbar_button
	hook::add finload_hook [namespace current]::add_services_menu
}

proc chattoolbar::add_services_menu {} {
	[.mainframe getmenu services] insert \
		[::msgcat::mc "Plugins"] \
		separator
		
	[.mainframe getmenu services] insert \
		[::msgcat::mc "Plugins"] command \
		-label [::msgcat::mc "ChatToolbar options."] \
		-command [namespace current]::configure_buttons
}
		
proc chattoolbar::setup_toolbar {chatid type} {
variable stored_variable
variable user_variable
variable iconTable

	if {[chat::is_groupchat $chatid] && !$user_variable(groupchat_active)} {
	return
	} elseif {![chat::is_groupchat $chatid] && !$user_variable(chat_active)} {
	return
	}
	set chatwin [chat::chat_win $chatid]
	set input_win [chat::input_win $chatid]
	
	catch {destroy [winfo parent $chatwin].toolbar.bbox}
	catch {destroy [winfo parent $chatwin].toolbar}
	
	set toolFrame [frame [winfo parent $chatwin].toolbar]
	set bbox [ButtonBox $toolFrame.bbox -spacing $user_variable(spacing)]	
	pack $bbox -side left -padx 1m

	foreach id [get_sorted_ids] {
		if {[get_button_state $id]} {
		$bbox add -image plugins/chattoolbar/$id \
		-highlightthickness 1 \
		-takefocus 0 -relief link \
		-bd $::tk_borderwidth -padx 2 \
		-pady 3 -command [list [namespace current]::button_$id $chatid] \
		-helptext $iconTable(text,$id) -justify left
		}
	}
	
	if {$user_variable(auto_show)} {change_state_toolbar $chatid $toolFrame show} 
	
	bind $chatwin <<ChattoolbarState>> \
	[double% [list [namespace current]::change_state_toolbar $chatid $toolFrame]]
	bind $input_win <<ChattoolbarState>> \
	[double% [list [namespace current]::change_state_toolbar $chatid $toolFrame]]
}

proc chattoolbar::change_state_toolbar {chatid toolFrame {type ""}} {
variable stored_variable
	
	set activex [lsearch $stored_variable(activate_chats) $chatid]
	
	if {[string length $type] > 0 && [string equal $type show]} {
		set chatwin [chat::chat_win $chatid]
		pack $toolFrame -side bottom -anchor w -fill x \
			-before [winfo parent $chatwin].csw
		if {$activex < 0} {
		lappend stored_variable(activate_chats) $chatid
		}
		return
	}
	
	if {$activex < 0} {
		set chatwin [chat::chat_win $chatid]
		pack $toolFrame -side bottom -anchor w -fill x \
			-before [winfo parent $chatwin].csw
		lappend stored_variable(activate_chats) $chatid
	} else {
		pack forget $toolFrame
		set stored_variable(activate_chats) [lreplace \
			$stored_variable(activate_chats) $activex $activex]
	}
}

proc chattoolbar::get_sorted_ids {} {
variable stored_variable
variable iconTable
	
	set m [llength $iconTable(id_list)]
	foreach id $iconTable(id_list) {
		set idx [lsearch -index 1 $stored_variable(sort_index) $id]
		if {$idx >= 0} {
			set ind [lindex $stored_variable(sort_index) $idx 0]
			set map($ind) [lindex $stored_variable(sort_index) $idx 1]
		} else { set map([incr m]) $id }
	}
	
	foreach id [lsort -integer [array names map]] {
	lappend result $map($id)
	}
	
	return $result
}

proc chattoolbar::get_sorted_ids_temp {} {
variable temp_variable
variable iconTable
	
	set m [llength $iconTable(id_list)]
	foreach id $iconTable(id_list) {
		set idx [lsearch -index 1 $temp_variable(sort_index) $id]
		if {$idx >= 0} {
			set ind [lindex $temp_variable(sort_index) $idx 0]
			set map($ind) [lindex $temp_variable(sort_index) $idx 1]
		} else { set map([incr m]) $id }
	}
	
	foreach id [lsort -integer [array names map]] {
	lappend result $map($id)
	}
	
	return $result
}

proc chattoolbar::get_button_state {id} {
variable stored_variable

	set idx [lsearch -index 1 $stored_variable(button_state) $id]
	if {$idx >= 0} {
		return [lindex $stored_variable(button_state) $idx 0]
	} else {return 1}
}

proc chattoolbar::state_toolbar_button {args} {
variable user_variable 
	
	switch -- $user_variable(toolbar_button) {
		1 add_toolbar_button 
		0 delete_toolbar_button
	}
}

proc chattoolbar::add_toolbar_button {} {
variable stored_variable

	catch {.mainframe gettoolbar 0} toolbar
	set bbox $toolbar.bbox
	
	if {[winfo exist $toolbar.bbox] && ![ButtonBox::exist $toolbar.bbox $stored_variable(toolbar_btn_index)]} {
		set stored_variable(toolbar_btn_index) [ifacetk::add_toolbar_button \
			plugins/chattoolbar/toolbar \
			[namespace current]::configure_buttons \
			[::msgcat::mc "Configure ChatToolBar"]]
	}
}

proc chattoolbar::delete_toolbar_button {} {
variable stored_variable
	
	catch {.mainframe gettoolbar 0} toolbar
	set bbox $toolbar.bbox
	
	if {[winfo exist $toolbar.bbox] && \
		[ButtonBox::exist $toolbar.bbox $stored_variable(toolbar_btn_index)]} {
			ButtonBox::delete $toolbar.bbox $stored_variable(toolbar_btn_index)
			set toolbar_button(index) -1
	}
}

proc ::ButtonBox::exist {path index} {
    variable $path
    upvar 0  $path data
	
	return [expr {[lsearch -exact $data(buttons) $index] > 0}]	
}

proc ::ButtonBox::delete { path idx } {
    variable $path
    upvar 0  $path data

    set i [lsearch -exact $data(buttons) $idx]
    set data(buttons) [lreplace $data(buttons) $i $i]
    destroy $path.b$idx
}

proc chattoolbar::configure_buttons {} {
variable state
variable stored_variable
variable temp_variable
variable iconTable
variable spacing
variable user_variable

	set w .chattoolbar_manager
	
	if {[winfo exists $w]} return
	
	set temp_variable(sort_index) $stored_variable(sort_index)
	set spacing $user_variable(spacing)
	foreach id $iconTable(id_list) {
	set state($id) [get_button_state $id]
	}
	
	add_win $w -title [::msgcat::mc "Chattoolbar manager"] \
	    -tabtitle [::msgcat::mc "Chattoolbar setting"] \
		-raisecmd [list focus $w]
	
	set scw [ScrolledWindow $w.sw]
	
	set text [text $w.buttonlist -wrap word \
		-background [$w cget -background] \
		-cursor arrow]
		
	set apply [button $w.apply \
		-text [::msgcat::mc "Apply"] \
		-command [namespace current]::apply]
	
	$scw setwidget $text	
	
	redraw_buttons_on_manager
	
	place $scw -in $w -relwidth 1 -relheight 1 \
		-x 0 -y 0 -width -1 -height -40
			
	place $apply -in $w -relx 1 -rely 1 \
		-x -5 -y -2 -anchor se
	
	$text configure -state disabled
}

proc chattoolbar::apply {} {
variable stored_variable
variable temp_variable
variable state
variable spacing
variable user_variable

	set stored_variable(sort_index) $temp_variable(sort_index)
	set user_variable(spacing) $spacing
	
	foreach ob [array names state] {
		set idx [lsearch -index 1 $stored_variable(button_state) $ob]
		if {$idx >= 0} {
		set stored_variable(button_state) [lreplace $stored_variable(button_state) \
			$idx $idx [list $state($ob) $ob]]
		} else {lappend stored_variable(button_state) [list $state($ob) $ob]}
	}
	
	redraw_all_chats
}

proc chattoolbar::redraw_buttons_on_manager { } {
variable iconTable
variable state
variable spacing
variable user_variable

	set text .chattoolbar_manager.buttonlist

	$text configure -state normal
	$text delete 1.0 end

	ButtonBox $text.bbox -spacing $spacing
	label $text.spacing_text -text [::msgcat::mc "Spacing between buttons"]
	spinbox $text.spacing -from 0 -to 10 -width 5 \
		-textvariable [namespace current]::spacing \
		-command [namespace current]::redraw_buttons_on_manager \
		-validate key \
		-vcmd {string is integer %P} 
		
	normalize_sort_temp
	foreach id [get_sorted_ids_temp] {
		set check [checkbutton $text.check_$id \
			-image plugins/chattoolbar/$id \
			-variable [namespace current]::state($id)]
		
		button $text.check_${id}_up -image plugins/chattoolbar/up \
			-command [list [namespace current]::button_move - $id] \
			-relief flat -background [.chattoolbar_manager cget -background]
			
		button $text.check_${id}_down -image plugins/chattoolbar/down \
			-command [list [namespace current]::button_move + $id] \
			-relief flat -background [.chattoolbar_manager cget -background]
		
		$text window create end -window $text.check_${id}_up
		$text window create end -window $text.check_${id}_down
		$text window create end -window $check
		$text insert end \t$iconTable(text,$id)\n
		
		if {$state($id)} {
		$text.bbox add -image plugins/chattoolbar/$id \
			-highlightthickness 1 \
			-takefocus 0 -relief link \
			-bd $::tk_borderwidth -padx 2 \
			-pady 3 \
			-helptext $iconTable(text,$id) \
			-justify left
		}
		
		bindscroll $check $text
	}
	
	$text insert end \n\n
	$text window create end -window $text.bbox
	$text insert end \n
	$text window create end -window $text.spacing_text
	$text window create end -window $text.spacing
	
}

proc chattoolbar::button_move {to id} {
variable temp_variable
		
	set blen [llength $temp_variable(sort_index)]
	
	set idx [lsearch -index 1 $temp_variable(sort_index) $id]
	set idval [lindex $temp_variable(sort_index) $idx]
	lassign $idval sind sid
	
	set lidx [expr $idx $to 1]
	set lidval [lindex $temp_variable(sort_index) $lidx]
	lassign $lidval lsind lsid

	if {$lidx < 0 || $lidx > [expr {$blen - 1}]} return
	
	set temp_variable(sort_index) [lreplace $temp_variable(sort_index) \
		$idx $idx [list $lsind $sid]]
	set temp_variable(sort_index) [lreplace $temp_variable(sort_index) \
		$lidx $lidx [list $sind $lsid]]
	
	redraw_buttons_on_manager
}

proc chattoolbar::normalize_sort_temp {} {
variable temp_variable
	foreach id [get_sorted_ids_temp] {
	lappend temp_list [list [incr ix] $id]
	}
	set temp_variable(sort_index) $temp_list
}

proc chattoolbar::redraw_all_chats {args} {
	foreach chatid [chat::opened] {
	setup_toolbar $chatid {}
	}
}