summaryrefslogtreecommitdiff
path: root/lib/configdialogues/shortcuts_config.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/configdialogues/shortcuts_config.tcl')
-rw-r--r--lib/configdialogues/shortcuts_config.tcl1035
1 files changed, 1035 insertions, 0 deletions
diff --git a/lib/configdialogues/shortcuts_config.tcl b/lib/configdialogues/shortcuts_config.tcl
new file mode 100644
index 0000000..612dc6a
--- /dev/null
+++ b/lib/configdialogues/shortcuts_config.tcl
@@ -0,0 +1,1035 @@
+#!/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 _SHORTCUTS_CONFIG_TCL ] } {
+set _SHORTCUTS_CONFIG_TCL _
+# <<< File inclusion guard
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Implements shortcuts configuration dialog
+# --------------------------------------------------------------------------
+
+namespace eval shortcuts {
+ variable dialog_opened 0 ;# Bool: True if this dialog is already opened
+ variable win ;# ID of dialog toplevel window
+
+ variable changed ;# Bool: Settings changed
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+ variable local_DB ;# Array: Local database of shortcuts
+ variable root_hard_cd ;# List of hadrcoded shortcuts (main window only)
+ variable currentNode ;# ID of the currently selected tree node
+ variable search_in_P ;# Bool: search in progress
+ # Empty image
+ variable empty_image [image create bitmap]
+ # Font for entry "Current shortcut"
+ variable current_entry_font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -weight [expr {$::MICROSOFT_WINDOWS ? "normal" : "bold"}] \
+ -size [expr {int(-12 * $::font_size_factor)}] \
+ ]
+ # Normal font for tree widget nodes
+ variable node_font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -weight normal \
+ -size [expr {int(-12 * $::font_size_factor)}] \
+ ]
+ # Bold font for tree widget nodes
+ variable node_font_b [font create \
+ -family {helvetica} \
+ -weight bold \
+ -size [expr {int(-14 * $::font_size_factor)}] \
+ ]
+
+ variable status_label ;# ID of status label
+ variable search_entry ;# ID of entry widget on search panel
+ variable search_clear ;# ID of button "Clear search entry"
+ variable treeWidget ;# ID of the tree widget
+ variable bottom_lf_label ;# ID of label for bottom label frame
+ variable discard_button ;# ID of button "Discard"
+ variable accept_button ;# ID of button "Accept"
+ variable default_entry ;# ID of label containging default key shortcut
+ variable default_button ;# ID of button "Restore default" (bottom label frame)
+ variable clear_button ;# ID of button "Clear"
+ variable current_entry ;# ID of entry "Current shortcut"
+
+ ## Create the dialog
+ # @return void
+ proc mkDialog {} {
+ variable win ;# ID of toplevel dialog window
+ variable dialog_opened ;# Bool: True if this dialog is already opened
+ variable local_DB ;# Array: Local database of shortcuts
+ variable changed ;# Bool: Settings changed
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+ variable search_entry ;# ID of entry widget on search panel
+ variable search_clear ;# ID of button "Clear search entry"
+ variable treeWidget ;# ID of the tree widget
+ variable search_in_P ;# Bool: search in progress
+ variable bottom_lf_label ;# ID of label for bottom label frame
+ variable discard_button ;# ID of button "Discard"
+ variable accept_button ;# ID of button "Accept"
+ variable default_entry ;# ID of label containging default key shortcut
+ variable default_button ;# ID of button "Restore default" (bottom label frame)
+ variable clear_button ;# ID of button "Clear"
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable empty_image ;# Empty image
+ variable current_entry_font ;# Font for entry "Current shortcut"
+ variable currentNode ;# ID of the currently selected tree node
+ variable status_label ;# ID of status label
+ variable root_hard_cd ;# List of hadrcoded shortcuts (main window only)
+ variable node_font ;# Normal font for tree widget nodes
+ variable node_font_b ;# Bold font for tree widget nodes
+
+ # Destroy dialog window if it is already opened
+ if {$dialog_opened} {
+ destroy .shortcuts_config_dialog
+ }
+ set anything_modified 0
+ set dialog_opened 1
+ set currentNode {}
+ set search_in_P 0
+ set changed 0
+
+ # Configure ttk styles
+ ttk::style configure Shortcuts_Default.TLabel -relief sunken -borderwidth 1 -background {#F0F0F0}
+
+ # Get settings from the program
+ getSettings
+
+ # Create list of hard-coded shortcuts related to main window
+ set root_hard_cd {}
+ foreach key ${::HARDCODED_SHORTCUTS} {
+ lappend root_hard_cd [simplify_key_seq $key]
+ }
+
+ # Create toplevel window
+ set win [toplevel .shortcuts_config_dialog -class {Configuration dialog} -bg ${::COMMON_BG_COLOR}]
+
+ # Create window header
+ label $win.header_label \
+ -compound left \
+ -image ::ICONS::32::configure \
+ -text [mc "Configure key shortcuts"] \
+ -font [font create -size [expr {int(-20 * $::font_size_factor)}]]
+
+ # Create header labels for label frames
+ set top_lf_label [label $win.top_lf_label \
+ -text [mc "available items"] \
+ -image ::ICONS::16::view_choose \
+ -compound left \
+ ]
+ set bottom_lf_label [label $win.bottom_lf_label \
+ -text [mc "<Nothing selected>"] \
+ -compound left -height 20 \
+ -image $empty_image \
+ ]
+
+ # Create label frames
+ set top_labelframe [ttk::labelframe $win.top_labelframe \
+ -labelwidget $top_lf_label -padding 7 \
+ ]
+ set bottom_labelframe [ttk::labelframe $win.bottom_labelframe \
+ -labelwidget $bottom_lf_label -padding 7 \
+ ]
+
+ # Create serach panel
+ set search_frame [frame $top_labelframe.search_frame]
+ pack [Label $search_frame.label \
+ -text [mc "Search:"] \
+ -helptext [mc "Enter your search string here"] \
+ ] -side left
+ set search_entry [ttk::entry $search_frame.entry \
+ -validate all \
+ -validatecommand {::configDialogues::shortcuts::search %P} \
+ ]
+ DynamicHelp::add $search_frame.entry \
+ -text [mc "Enter your search string here"]
+ pack $search_entry -side left -fill x -expand 1
+ set search_clear [ttk::button $search_frame.button \
+ -image ::ICONS::16::clear_left \
+ -style Flat.TButton \
+ -command "$search_entry delete 0 end" \
+ -state disabled \
+ ]
+ DynamicHelp::add $search_frame.button \
+ -text [mc "Clear"]
+ pack $search_clear -side right -after $search_entry
+ pack $search_frame -fill x -pady 5
+
+ # Create frame for the tree widget and its scrollbar
+ set tree_frame [frame $top_labelframe.tree_frame]
+ pack $tree_frame -fill both -expand 1
+
+ # Create tree widget showing available items
+ set treeWidget [Tree $tree_frame.tree \
+ -selectfill 1 \
+ -showlines 1 \
+ -linesfill {#888888} \
+ -bg {#FFFFFF} \
+ -selectbackground {#CCCCFF} \
+ -selectforeground {#0000FF} \
+ -highlightthickness 0 \
+ -padx 5 \
+ -deltay 20 \
+ -deltax 20 \
+ -yscrollcommand "$tree_frame.scrollbar set" \
+ -crossopenimage ::ICONS::16::1downarrow \
+ -crosscloseimage ::ICONS::16::1rightarrow \
+ -selectcommand {::configDialogues::shortcuts::item_selected} \
+ ]
+ pack $treeWidget -fill both -expand 1 -side left
+ bind $treeWidget <Button-5> {%W yview scroll +5 units; break}
+ bind $treeWidget <Button-4> {%W yview scroll -5 units; break}
+
+ # Create scrollbar for the tree widget
+ pack [ttk::scrollbar $tree_frame.scrollbar \
+ -command "$treeWidget yview" \
+ -orient vertical \
+ ] -fill y -side left -after $treeWidget
+
+ # Fill in the tree
+ foreach block ${::SHORTCUTS_LIST} {
+ # Determinate category
+ set cat_org [lindex $block 0]
+ set cat "__$cat_org"
+
+ # Adjus list of harcoded shotcuts
+ set hardcoded {}
+ foreach key [lindex $block 2] {
+ lappend hardcoded [simplify_key_seq $key]
+ }
+
+ # Create category node
+ $treeWidget insert end root $cat \
+ -selectable 1 \
+ -data $hardcoded \
+ -text [mc [lindex $block 1]] \
+ -fill {#0000FF} \
+ -font $node_font_b
+
+ ## Create item node
+ set block [lreplace $block 0 2] ;# Item definitions
+ set len [llength $block] ;# Length of data block
+
+ # Iterate over item definitions
+ for {set i 0; set j 1} {$i < $len} {incr i 2; incr j 2} {
+
+ # Local variables
+ set item [lindex $block $i] ;# Item ID
+ set image [lindex $block [list $j 2]] ;# Image ID or {}
+ set text [mc [lindex $block [list $j 3]]];# Item text
+ set txt_len [string length $text] ;# Item text length
+
+ # Adjust text width
+ append text [string repeat "\t" [expr {4 - ($txt_len / 8)}]]
+
+ # Determinate text to show in the node
+ set text_and_key $text
+ append text_and_key [simplify_key_seq $local_DB($cat_org:$item)]
+
+ # Determinate image ID
+ if {$image != {}} {
+ set image "::ICONS::16::$image"
+ } else {
+ set image $empty_image
+ }
+
+ # Adjust key combination
+ set key_seq [regsub {Key(Press|Release)?\-} $local_DB($cat_org:$item) {}]
+
+ # Create node in the tree widget
+ $treeWidget insert end $cat $item \
+ -selectable 1 \
+ -font $node_font \
+ -text $text_and_key \
+ -data [list \
+ $text \
+ [lindex $block [list $j 0]] \
+ $key_seq \
+ ] \
+ -image $image -padx 25
+ }
+ }
+
+ ## Create widgets of bottom label frame
+ # Label and entry "Current"
+ grid [label $bottom_labelframe.current_label \
+ -text [mc "Current shortcut:"] \
+ ] -row 0 -column 0 -sticky w
+ set current_entry [ttk::entry $bottom_labelframe.current_entry \
+ -validatecommand {::configDialogues::shortcuts::cur_entry_val %P} \
+ ]
+ grid $current_entry -row 0 -column 1
+ bind $current_entry <KeyPress> \
+ {::configDialogues::shortcuts::current_entry_key %K; break}
+ bind $current_entry <Control-KeyPress> \
+ {::configDialogues::shortcuts::current_entry_key Ctrl+%K; break}
+ bind $current_entry <Alt-KeyPress> \
+ {::configDialogues::shortcuts::current_entry_key Alt+%K; break}
+ bind $current_entry <Control-Alt-KeyPress> \
+ {::configDialogues::shortcuts::current_entry_key Ctrl+Alt+%K; break}
+ set clear_button [ttk::button $bottom_labelframe.clear_button \
+ -image ::ICONS::16::clear_left \
+ -state disabled \
+ -style Flat.TButton \
+ -command {::configDialogues::shortcuts::clear_current} \
+ ]
+ DynamicHelp::add $bottom_labelframe.clear_button -text [mc "Clear"]
+ grid $clear_button -row 0 -column 2 -sticky w
+
+ # Label and entry "Default"
+ grid [label $bottom_labelframe.default_label \
+ -text [mc "Default:"] \
+ ] -row 1 -column 0 -sticky w
+ set default_entry [ttk::label $bottom_labelframe.default_entry \
+ -style Shortcuts_Default.TLabel \
+ ]
+ grid $default_entry -row 1 -column 1 -sticky we
+ set default_button [ttk::button $bottom_labelframe.default_button \
+ -image ::ICONS::16::up0 \
+ -state disabled \
+ -command {::configDialogues::shortcuts::to_default} \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $bottom_labelframe.default_button -text [mc "Restore default"]
+ grid $default_button -row 1 -column 2 -sticky w
+
+ # Button "Accept"
+ set accept_button [ttk::button $bottom_labelframe.accept_button \
+ -command {::configDialogues::shortcuts::accept_current} \
+ -text [mc "Accept"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -state disabled \
+ ]
+ DynamicHelp::add $bottom_labelframe.accept_button -text [mc "Accept new shortcut"]
+ grid $accept_button -row 0 -column 4 -rowspan 2
+ # Button "Original"
+ set discard_button [ttk::button $bottom_labelframe.discard_button \
+ -command {::configDialogues::shortcuts::discard_current} \
+ -text [mc "Original"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -state disabled \
+ ]
+ DynamicHelp::add $bottom_labelframe.discard_button -text [mc "Discard new shortcut"]
+ grid $discard_button -row 0 -column 5 -rowspan 2
+
+ # Create status label
+ set status_label [label $bottom_labelframe.status_label \
+ -fg {#DD0000} -anchor w -text {} \
+ ]
+ grid $status_label -row 2 -column 0 -columnspan 6 -sticky w
+
+ # Create empty space on column 3
+ grid columnconfigure $bottom_labelframe 3 -minsize 70
+
+
+ ## Button frame at the bottom
+ set but_frame [frame $win.button_frame]
+ # Button "Reset"
+ pack [ttk::button $but_frame.but_default \
+ -text [mc "Defaults"] \
+ -command {::configDialogues::shortcuts::DEFAULTS} \
+ ] -side left
+ DynamicHelp::add $but_frame.but_default -text [mc "Reset all settings to defaults"]
+ # Button "Ok"
+ pack [ttk::button $but_frame.but_ok \
+ -text [mc "Ok"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -command {::configDialogues::shortcuts::OK} \
+ ] -side right -padx 2
+ DynamicHelp::add $but_frame.but_ok -text [mc "Commit new settings"]
+ # Button "Cancel"
+ pack [ttk::button $but_frame.but_cancel \
+ -text [mc "Cancel"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command {::configDialogues::shortcuts::CANCEL} \
+ ] -side right -padx 2
+ DynamicHelp::add $but_frame.but_cancel -text [mc "Take changes back and close dialog"]
+
+ # Pack frames
+ pack $win.header_label -side top -pady 6
+ pack $top_labelframe -side top -fill both -expand 1 -padx 10
+ pack $bottom_labelframe -side top -fill x -padx 10 -pady 10 -after $top_labelframe
+ pack $but_frame -side bottom -fill x -padx 10 -pady 5
+
+ # Set window attributes
+ wm iconphoto $win ::ICONS::16::configure
+ wm transient $win .
+ wm title $win [mc "Configure shortcuts - %s" ${::APPNAME}]
+ wm minsize $win 600 520
+ raise $win
+ catch {grab $win}
+ wm protocol $win WM_DELETE_WINDOW {
+ ::configDialogues::shortcuts::CANCEL
+ }
+ tkwait window $win
+ }
+
+ ## Argument of parameter '-selectcommand' for the tree widget
+ # @parm Widget widget - Source tree widget
+ # @parm List nodes - Selected nodes
+ # @return void
+ proc item_selected {widget nodes} {
+ variable current_entry_font ;# Font for entry "Current shortcut"
+ variable node_font ;# Normal font for tree widget nodes
+ variable search_entry ;# ID of entry widget on search panel
+ variable search_in_P ;# Bool: search in progress
+ variable discard_button ;# ID of button "Discard"
+ variable accept_button ;# ID of button "Accept"
+ variable default_entry ;# ID of label containging default key shortcut
+ variable bottom_lf_label ;# ID of label for bottom label frame
+ variable default_button ;# ID of button "Restore default" (bottom label frame)
+ variable clear_button ;# ID of button "Clear"
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable empty_image ;# Empty image
+ variable status_label ;# ID of status label
+ variable changed ;# Bool: Settings changed
+ variable currentNode ;# ID of the currently selected tree node
+
+ # Empty selection -> disable widgets on the bottom frame and return
+ if {$nodes == {}} {
+ # Save last changed item
+ if {$changed} {
+ current_item_changed
+ }
+
+ # Clear and disable componets of the bottom frame
+ $current_entry delete 0 end
+ cur_entry_val {}
+ $default_entry configure -text {}
+ $status_label configure -text {}
+ $current_entry configure -state disabled
+ $default_button configure -state disabled
+ $accept_button configure -state disabled
+ $discard_button configure -state disabled
+ $bottom_lf_label configure -text [mc "<Nothing selected>"] -image $empty_image
+ return
+ }
+
+ # Only one node can be selected
+ set node [lindex $nodes end]
+ if {[llength $nodes] > 1} {
+ foreach nd [lreplace $nodes end end] {
+ $widget selection remove $nd
+ }
+ return
+ }
+
+ # Clear status label, search entry and ask for saving the last change
+ $status_label configure -text {}
+ if {!$search_in_P} {
+ $search_entry delete 0 end
+ if {$changed} {
+ current_item_changed
+ }
+ }
+
+ # If the selected node is a toplevel one -> open its node
+ if {[regexp {^__} $node]} {
+ $widget toggle $node
+ $widget selection clear
+ return
+ }
+
+ if {$currentNode != {}} {
+ $widget itemconfigure $currentNode -font $node_font
+ }
+ $widget itemconfigure $node -font $current_entry_font
+
+ # Set the current node
+ set currentNode $node
+
+ # Adjust bottom frame
+ set data [$widget itemcget $node -data]
+ $bottom_lf_label configure \
+ -image [$widget itemcget $node -image] \
+ -text [string trimright [lindex $data 0]]
+ $current_entry configure -state normal
+ $current_entry delete 0 end
+ $current_entry insert end [simplify_key_seq [lindex $data 2]]
+ cur_entry_val [simplify_key_seq [lindex $data 2]]
+ $default_entry configure -text [simplify_key_seq [lindex $data 1]]
+ $default_button configure -state normal
+ ena_dis__accept_discard 0
+ }
+
+ ## Binding for X-Key event for entry "Custom shortcut" (see proc. 'mkDialog')
+ # @parm String key_seq - human readable key combination string
+ # @return void
+ proc current_entry_key {key_seq} {
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable status_label ;# ID of status label
+ variable changed ;# Bool: Settings changed
+ variable treeWidget ;# ID of the tree widget
+ variable currentNode ;# ID of the currently selected tree node
+ variable root_hard_cd ;# List of hadrcoded shortcuts (main window only)
+
+ if {$currentNode == {}} {
+ return
+ }
+
+ # Clear entry "Custom shortcut"
+ $current_entry delete 0 end
+ cur_entry_val {}
+
+ # Adjust key combination
+ set lastchar [string index $key_seq end]
+ if {[string index $key_seq end-1] == {+}} {
+ if {[string is lower -strict $lastchar]} {
+ set key_seq [string replace $key_seq \
+ end end [string toupper $lastchar]]
+ } else {
+ set key_seq [string replace $key_seq end end \
+ "Shift+[string toupper $lastchar]"]
+ }
+ }
+
+ # Check for validity of the given shortcut and set flag "changed"
+ set changed 0
+ if {![regexp {^(Ctrl|Alt)\+} $key_seq] && ![regexp {^F\d\d?$} $key_seq]} {
+ $status_label configure -text [mc "Modifier required (Control or Alt)"]
+ } elseif {[lsearch $root_hard_cd $key_seq] != -1} {
+ $status_label configure -text \
+ [mc "This combination is hard-coded in the main window, so it cannot be used"]
+ } elseif {[lsearch [$treeWidget itemcget [$treeWidget parent $currentNode] -data] $key_seq] != -1} {
+ $status_label configure -text \
+ [mc "This combination is hard-coded, so it cannot be used"]
+ } else {
+ set changed 1
+ }
+ if {!$changed} {
+ $current_entry insert end $key_seq
+ cur_entry_val $key_seq
+ ena_dis__accept_discard 0
+ return
+ }
+
+ # Change content of entry "Custom shortcut"
+ $current_entry insert end $key_seq
+ cur_entry_val $key_seq
+
+ # Check if the given combination is not already assigned to something
+ set name [lindex [key_seq_to_name \
+ [extend_key_seq $key_seq] \
+ [$treeWidget parent $currentNode]] 1]
+ if {$name != {} && $name != [string trim [lindex [$treeWidget itemcget $currentNode -data] 0]]} {
+ $status_label configure -text \
+ [mc "The '%s' key combination has already been assigned to \"%s\"." $key_seq $name]
+ } else {
+ $status_label configure -text {}
+ }
+
+ # Enable buttons "Accept" and "Original" (but only if user is not trying to redefine a shortcut with the same key combination)
+ if {$name != [string trim [lindex [$treeWidget itemcget $currentNode -data] 0]]} {
+ ena_dis__accept_discard 1
+ }
+ }
+
+ ## Clear entry "Custom shortcut"
+ # @return void
+ proc clear_current {} {
+ variable changed ;# Bool: Settings changed
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable status_label ;# ID of status label
+
+ # Adjust flag "Anything modified"
+ if {[$current_entry get] != {}} {
+ set anything_modified 1
+ }
+ # Clear the entry widget and status label
+ $current_entry delete 0 end
+ cur_entry_val {}
+ $status_label configure -text {}
+ # Enable buttons "Accept" and "Original"
+ ena_dis__accept_discard 1
+ # Set flag "Changed"
+ set changed 1
+ }
+
+ ## Validate content of entry "Current shortcut"
+ # @parm String content - content of entry "Current shortcut"
+ # @return Bool - always 1
+ proc cur_entry_val {content} {
+ variable clear_button ;# ID of button "Clear"
+
+ # Enable/Disable button "Clear"
+ if {$content == {}} {
+ $clear_button configure -state disabled
+ } else {
+ $clear_button configure -state normal
+ }
+
+ return 1
+ }
+
+ ## Set current shortcut to default
+ # @return void
+ proc to_default {} {
+ variable treeWidget ;# ID of the tree widget
+ variable changed ;# Bool: Settings changed
+ variable currentNode ;# ID of the currently selected tree node
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable default_entry ;# ID of label containging default key shortcut
+ variable status_label ;# ID of status label
+
+ # Se flag "Anything modified"
+ if {[$current_entry get] != [$default_entry cget -text]} {
+ set anything_modified 1
+ }
+
+ # Adjust content of entry "Current shortcut"
+ set key [$default_entry cget -text]
+ $current_entry delete 0 end
+ $current_entry insert 0 $key
+ cur_entry_val $key
+
+ # Check if the new setting is unique
+ set name [lindex [key_seq_to_name \
+ [extend_key_seq $key ] \
+ [$treeWidget parent $currentNode]] 1]
+ if {$name != {}} {
+ $status_label configure -text \
+ [mc "The '%s' key combination has already been assigned to \"%s\"." $key $name]
+ }
+
+ # Enable buttons "Accept" and "Original"
+ ena_dis__accept_discard 1
+ set changed 1
+ }
+
+ ## Accept new key combination fot the currently selected action
+ # @return void
+ proc accept_current {} {
+ variable changed ;# Bool: Settings changed
+ variable treeWidget ;# ID of the tree widget
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable currentNode ;# ID of the currently selected tree node
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+ variable local_DB ;# Local database of shortcuts
+ variable status_label ;# ID of status label
+
+ # Gain details about the current action
+ set data [$treeWidget itemcget $currentNode -data]
+ set parent [$treeWidget parent $currentNode]
+ set category [string replace $parent 0 1]
+ set text_org [lindex $data 0]
+ set default [lindex $data 1]
+ set current [extend_key_seq [$current_entry get]]
+ set text $text_org
+ append text [$current_entry get]
+
+ ## Redefine shortcut for action which have the same shortcut as the current one
+ $treeWidget itemconfigure $currentNode -data {}
+ set defined [key_seq_to_name $current $parent]
+ # Redefine
+ if {$defined != {}} {
+ $status_label configure -text \
+ [mc "Removing key combination for action \"%s\"" [lindex $defined 1]]
+ set defined [lindex $defined 0]
+ set cat [string replace [$treeWidget parent $defined] 0 1]
+ set local_DB($cat:$defined) {}
+ set dt [$treeWidget itemcget $defined -data]
+ set txt [lindex $dt 0]
+ set dt [lindex $dt 1]
+ $treeWidget itemconfigure $defined \
+ -text $txt \
+ -data [list $txt $dt {}]
+ # Keep
+ } else {
+ $status_label configure -text {}
+ }
+
+ # Adjust local database and the tree widget
+ set local_DB($category:$currentNode) $current
+ $treeWidget itemconfigure $currentNode \
+ -text $text \
+ -data [list $text_org $default $current]
+
+ # Adjust modifed flags and disable buttons "Accept" and "Original"
+ set changed 0
+ set anything_modified 1
+ ena_dis__accept_discard 0
+ }
+
+ ## Discard new key combination fot the currently selected action
+ # @return void
+ proc discard_current {} {
+ variable changed ;# Bool: Settings changed
+ variable treeWidget ;# ID of the tree widget
+ variable current_entry ;# ID of entry "Current shortcut"
+ variable status_label ;# ID of status label
+ variable currentNode ;# ID of the currently selected tree node
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+
+ # Restore previous content of entry "Current shortcut"
+ $current_entry delete 0 end
+ $current_entry insert end [simplify_key_seq \
+ [lindex [$treeWidget itemcget $currentNode -data] 2]]
+ cur_entry_val [$current_entry get]
+
+ # Clear status label
+ $status_label configure -text {}
+
+ # Disable buttons "Accept" and "Original"
+ ena_dis__accept_discard 0
+ set changed 0
+ }
+
+ ## Ask user about saving the last change and conditionly save it
+ # @return void
+ proc current_item_changed {} {
+ variable changed ;# Bool: Settings changed
+ variable currentNode ;# ID of the currently selected tree node
+ variable win ;# ID of toplevel dialog window
+
+ set changed 0
+ if {[tk_messageBox \
+ -type yesno \
+ -parent $win \
+ -icon question \
+ -title [mc "Item changed"] \
+ -message [mc "The previous item was modified. Do you want to save it ?"] \
+ ] != {yes}
+ } then {
+ return
+ }
+
+ accept_current
+ }
+
+ ## Translate key combination acceptable by Tk to "human readable" representation
+ # @parm String key_seq - Human readable representation of a key combination
+ # @return String - Key combination acceptable by Tk
+ proc extend_key_seq {key_seq} {
+ if {$key_seq == {}} {
+ return {}
+ }
+
+ regsub -all {\+} $key_seq {-} key_seq
+ regsub {Ctrl\-} $key_seq {Control-} key_seq
+ set last_char [string index $key_seq end]
+ if {![string compare {Shift-} [string range $key_seq {end-6} {end-1}]]} {
+ set last_char [string toupper $last_char]
+ set key_seq [string range $key_seq 0 {end-7}]
+ append key_seq $last_char
+ } elseif {[string index $key_seq {end-1}] == {-}} {
+ set key_seq [string replace $key_seq end end [string tolower $last_char]]
+ }
+
+ return $key_seq
+ }
+
+ ## Find name of action specified by the given key combination
+ # @parm String key_seq - Key combination acceptable by Tk
+ # @parm String parent_node - Parent node (category)
+ # @return String - Action name or {}
+ proc key_seq_to_name {key_seq parent_node} {
+ variable treeWidget ;# ID of the tree widget
+
+ if {$key_seq == {}} {
+ return {}
+ }
+
+ # Search the tree widget
+ foreach node [$treeWidget nodes $parent_node] {
+ if {![string compare $key_seq \
+ [lindex [$treeWidget itemcget $node -data] 2]]} \
+ {
+ return [list $node \
+ [string trimright \
+ [lindex [$treeWidget itemcget $node -data] 0]]]
+ }
+ }
+
+ return {}
+ }
+
+ ## Enable/Disable buttons "Discard" and "Accept"
+ # @parm Bool ena_dis - Enable/Disable (1 == enable; 0 == disable)
+ # @return void
+ proc ena_dis__accept_discard {ena_dis} {
+ variable discard_button ;# ID of button "Discard"
+ variable accept_button ;# ID of button "Accept"
+
+ if {$ena_dis} {
+ $discard_button configure -state normal
+ $accept_button configure -state normal
+ } else {
+ $discard_button configure -state disabled
+ $accept_button configure -state disabled
+ }
+ }
+
+ ## Search the given string in the tree widget
+ # @parm String string - string to find
+ # @return Bool - always 1
+ proc search {string} {
+ variable search_entry ;# ID of entry widget on search panel
+ variable search_clear ;# ID of button "Clear search entry"
+ variable treeWidget ;# ID of the tree widget
+ variable search_in_P ;# Bool: search in progress
+ variable changed ;# Bool: Settings changed
+
+ # Empty input string
+ if {$string == {}} {
+ $search_clear configure -state disabled
+ $search_entry configure -style TEntry
+ return 1
+ }
+ $search_clear configure -state normal
+
+ # String to lowercase
+ set string [string tolower $string]
+
+ # Search all nodes
+ foreach top [$treeWidget nodes root] {
+ foreach node [$treeWidget nodes $top] {
+ set text [$treeWidget itemcget $node -text]
+ set text [string tolower $text]
+
+ # String found
+ if {[string first $string $text] != -1} {
+ # Select the node
+ set search_in_P 1
+ $treeWidget opentree [$treeWidget parent $node]
+ $treeWidget selection set $node
+ $treeWidget see $node
+
+ # Adjust entry widget and return
+ set search_in_P 0
+ $search_entry configure -style StringFound.TEntry
+ return 1
+ }
+ }
+ }
+
+ # String not found
+ $search_entry configure -style StringNotFound.TEntry
+ return 1
+ }
+
+ ## Retrieve settings related to this dialog from the program
+ # @return void
+ proc getSettings {} {
+ variable local_DB ;# Local database of shortcuts
+
+ foreach key [array names ::SHORTCUTS_DB] {
+ set local_DB($key) $::SHORTCUTS_DB($key)
+ }
+ }
+
+ ## Change content of configuration variables
+ # @return void
+ proc use_settings {} {
+ variable local_DB ;# Local database of shortcuts
+
+ foreach key [array names local_DB] {
+ set ::SHORTCUTS_DB($key) $local_DB($key)
+ }
+ }
+
+ ## Adjust application to fit new settings
+ # @return Bool - result
+ proc apply_settings {} {
+ # Adjust main window
+ shortcuts_reevaluate
+ mainmenu_redraw
+
+ # Adjust projects
+ foreach project ${::X::openedProjects} {
+
+ # Adjust editors
+ foreach editor [$project cget -editors] {
+ $editor shortcuts_reevaluate
+ $editor makePopupMenu
+ }
+
+ # Adjust right panel
+ $project rightPanel_makePopupMenu
+ $project rightPanel_watch_shortcuts_reevaluate
+ # Adjust to do list
+ $project TodoProc_makePopupMenu
+ $project TodoProc_shortcuts_reevaluate
+ # Adjust messages text
+ $project messages_text_makePopupMenu
+ $project messages_text_shortcuts_reevaluate
+ # Adjust filelist
+ $project filelist_makePopupMenu
+ $project filelist_fsb_makePopupMenu
+ }
+
+ # Restore previous state of menu items (enabled / disabled)
+ ::X::disaena_menu_toolbar_for_current_project
+ }
+
+ ## Save configuration to config file
+ # @return void
+ proc save_config {} {
+ variable local_DB ;# Local database of shortcuts
+
+ foreach key [array names local_DB] {
+ ::settings setValue "Shortcuts/$key" $local_DB($key)
+ }
+
+ # Commit
+ ::settings saveConfig
+ }
+
+ ## Load configuratin from config file
+ # @return void
+ proc load_config {} {
+ array unset ::SHORTCUTS_DB
+ foreach block ${::SHORTCUTS_LIST} {
+ set category [lindex $block 0] ;# Shortcut category (eg. 'edit')
+ set block [lreplace $block 0 2] ;# Item definitions
+ set len [llength $block] ;# Length of data block
+
+ # Iterate over data block and redefine local database
+ for {set i 0; set j 1} {$i < $len} {incr i 2; incr j 2} {
+ set key [lindex $block $i] ;# Item name
+
+ set ::SHORTCUTS_DB($category:$key) \
+ [::settings getValue "Shortcuts/$category:$key" \
+ [lindex $block [list $j 0]]]
+ }
+ }
+ }
+
+ ## Destroy the dialog
+ # @return void
+ proc CANCEL {} {
+ variable win ;# ID of toplevel dialog window
+ variable local_DB ;# Local database of shortcuts
+ variable dialog_opened ;# Bool: True if this dialog is already opened
+ variable root_hard_cd ;# List of hadrcoded shortcuts (main window only)
+
+ # Discard local database of shortcuts
+ array unset local_DB
+ unset root_hard_cd
+
+ # Destroy dialog window
+ set dialog_opened 0
+ grab release $win
+ destroy $win
+ }
+
+ ## Use settings and destroy the dialog
+ # @return void
+ proc OK {} {
+ variable win ;# ID of toplevel dialog window
+ variable changed ;# Bool: Settings changed
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+
+ # Save last changed item
+ if {$changed} {
+ current_item_changed
+ }
+
+ # Use and save settings
+ if {$anything_modified} {
+ use_settings
+ apply_settings
+ save_config
+ }
+
+ # Destroy the dialog window
+ CANCEL
+ }
+
+ ## Restrore defaults
+ # @return void
+ proc DEFAULTS {} {
+ variable local_DB ;# Local database of shortcuts
+ variable treeWidget ;# ID of the tree widget
+ variable win ;# ID of toplevel dialog window
+ variable changed ;# Bool: Settings changed
+ variable anything_modified ;# Bool: Settings changed (stay set to 1 even after APPLY)
+
+ # Ask user
+ if {[tk_messageBox \
+ -parent $win \
+ -type yesno \
+ -title [mc "Confirmation required"] \
+ -icon question \
+ -message [mc "This will discard all shortcut settings and replace them with defaults. Are you sure by that ?"]\
+ ] != {yes}
+ } then {
+ return
+ }
+
+ # Adjust flags
+ set changed 0 ;# Last item modified --> NO
+ set anything_modified 1 ;# Any item modified --> YES
+
+ # Reset local database of shortcuts
+ array unset local_DB
+ foreach block ${::SHORTCUTS_LIST} {
+ set category [lindex $block 0] ;# Shortcut category (eg. 'edit')
+ set block [lreplace $block 0 2] ;# Item definitions
+ set len [llength $block] ;# Length of data block
+
+ # Redefine local database
+ for {set i 0; set j 1} {$i < $len} {incr i 2; incr j 2} {
+ set key [lindex $block $i]
+ set local_DB($category:$key) [lindex $block [list $j 0]]
+ }
+ }
+
+ ## Refresh content of the tree widget
+ $treeWidget selection clear
+ # Iterate over toplevel items
+ foreach top [$treeWidget nodes root] {
+ set cat [string replace $top 0 1] ;# Shortcut category (eg. 'edit')
+
+ # Iterate over lowlevel items
+ foreach node [$treeWidget nodes $top] {
+ # Long key sequence (for Tk)
+ set key_seq [regsub {Key(Press|Release)?\-} $local_DB($cat:$node) {}]
+
+ # Determinate new item data
+ set data [$treeWidget itemcget $node -data]
+ lset data 2 $key_seq
+
+ # Determinate item text
+ set text_and_key [lindex $data 0]
+ append text_and_key [simplify_key_seq $key_seq]
+
+ # Adjust item
+ $treeWidget itemconfigure $node \
+ -data $data \
+ -text $text_and_key
+ }
+ }
+ }
+}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard