# 
#f mode.tcl - procedures for mode management (navigation, menus,...)
#f 
#f     TOUT CELA EST A REFONDRE !!!
#f 

package provide stead 2.0

## stead:modeAskBox -- prompt user for mode
# 
proc stead:modeAskBox {} {
    set prompt_result [te:prompt -text "Editing Mode:"]
    if {$prompt_result != {}} then {
        stead:modeApply	$prompt_result
    } 
} 

## te:mode:sort_command - sort command for mark_lis
# 
proc te:mode:sort_command {a b} {
    set result [string compare [lindex $a 0]  [lindex $b 0]]
    return $result
} 

## te:mode:set_struct -- construit et remplit le menu de navigation
# 
# 
proc te:mode:set_struct {{name navig} {w .main.t}} {
  
    global stead
    global EDITPREFS
    global TE_MODE_SEARCH_STRING   MODE_MARK_LIST   mark_list
  
  
    stead:log [te:mode:toupper $stead(mode)] "Building Structure of Documen ..." 
    update
    if [info exists MODE_MARK_LIST] {
        foreach m $MODE_MARK_LIST {
            $w mark unset $m
        }
    } 
     
    te:mode:create_navig_window $name
    
    if {[string length [info proc te:mode:rescan_hook]]} {
        te:mode:rescan_hook
    }
    
    set num 1
    set indice 1.0
    set mark_list {}
    while {1} {
        update
        set text [$w get $indice end]
        
        if {[regexp $TE_MODE_SEARCH_STRING $text intitule]} then {
            regexp -indices $TE_MODE_SEARCH_STRING $text ind
            
            
            # Construction du label à afficher dans la liste de navigation 
            # à partir de la chaine extraite par la parterne régulière
            # 
            # Principe :
            # La proc te:mode:navig_label_hook, si elle existe elle doit 
            # retourner la chaine à afficher dans la liste de navigation 
            # à partir de la chaine extraite par la patterne régulière.
            # En l'absence d'une telle procédure, on affiche la première 
            # sous-patterne délimitée par une parenthese
            # 
            if { [string length [info proc te:mode:navig_label_hook]] } {
                set label [te:mode:navig_label_hook $intitule]
            } else {
                # Si aucune sous patterne parenthésée n'est définie :
                # on assure un label en prenant la chaine complete
                set label $intitule
                regexp $TE_MODE_SEARCH_STRING $w intitule label
            }
            
            
            # verrue ajoutée par diam le 30/08/00 car le menu navig etait 
            # illisible
            # 
            set intitule [string trim $intitule]
            set label [string trim $label]
            # report -v  intitule label
           
            set indice [$w index "$indice + [lindex $ind 1] chars"]
            lappend mark_list [list $label $indice $intitule]
            incr num
        } else {
            break
        }
    } 
    
    # Tri de la liste de navigation : par défaut, aucun tri : 
    # les éléements sont affichés dans l'ordre d'apparition dans le
    # fichier édité
    # Mais une procédure te:mode:navig_sort_hook (à définir dans le mode)
    # peut trier la liste par ordre alphabétique (par exemple)
    
    if {[string length [info proc te:mode:navig_sort_hook]]} {
        set mark_list [te:mode:navig_sort_hook $mark_list]        
    }
    
    for {set i 1} {$i < $num} {incr i} {
        update
        # marquage du fichier
        set label  [lindex [lindex $mark_list [expr {$i-1}]] 0]
        set indice [lindex [lindex $mark_list [expr {$i-1}]] 1]
        $w mark set mode_mark$i $indice
        lappend MODE_MARK_LIST "mode_mark$i"
        
        # Modif diam le 07/02/03 (correction bug car chevauchement des 
        # boutons si la fonte trop grande)
        # 
        # set buttonHeight 20
        set buttonHeight [expr {1.5*[lindex $::EDITPREFS(textfont) 1]}]
        
        button .$name.frame.canvas.button$i \
                -text $label \
                -command [list te:mode:cmd:go_to_mark mode_mark$i] \
                -relief flat \
                -borderwidth 0 \
                -pady 0 \
                -font $EDITPREFS(textfont)
        
        .$name.frame.canvas create window 1 [expr {$i*$buttonHeight}] \
                -anchor w \
                -window .$name.frame.canvas.button$i
                
      
    }
    
    set title "Building Structure of [string totitle $stead(mode)] Document"
    stead:log -title $title "Done" 
    return
}

## te:mode:cmd:go_to_mark - selectionne la ligne correspondant a la   
# marque                                                              
# 
proc te:mode:cmd:go_to_mark {m {w .main.t}} {

    $w mark set insert $m
    catch {$w tag remove sel sel.first sel.last}    
    $w tag add sel "$m linestart" "$m lineend"
    $w yview -pickplace insert
    xtext_updateFocusIn $w
  
}


## te:mode:create_navig_window -- cree la fenetre de navigation
# 
# Faire disparaitre la globale "te_mode_nb_buttons" en utilisant la commande
# [xtcl_uid] prévue pour cela , mais ATTENTION il faut modifier sérieusement 
# la procédure "te:mode:add_button" qui l'utilise dans des calculs
# 
proc te:mode:create_navig_window { {name navig} } {

    global stead
    global TE_MODE_NAVIG_RESET_TEXT
    global TE_MODE_NAVIG_SHOW_TEXT
    
    set state withdrawn
    if {[winfo exists .$name]} {
        set state [wm state .$name]
        destroy .$name
    }
    
    if {![info exists TE_MODE_NAVIG_RESET_TEXT]} {
        set TE_MODE_NAVIG_RESET_TEXT "Rescan"
    }
      
    toplevel .$name
  
    wm title .$name \
        "[file tail $stead(file)]: $stead(mode) $TE_MODE_NAVIG_SHOW_TEXT"
    
    frame .$name.frame
    
    scrollbar .$name.frame.scroll \
            -command ".$name.frame.canvas yview" \
            -relief raised
    
    # Modid diam le 12/12/02
    set yscrollincrement [expr {2*[lindex $::EDITPREFS(textfont) 1]}]
    canvas .$name.frame.canvas \
              -yscrollcommand ".$name.frame.scroll set" \
              -scrollregion {0 0 0 2000} \
              -relief raised \
              -confine true \
              -yscrollincrement $yscrollincrement
    # # canvas .$name.frame.canvas \
    # #           -yscrollcommand ".$name.frame.scroll set" \
    # #           -scrollregion {0 0 0 2000} \
    # #           -relief raised \
    # #           -confine true \
    # #           -yscrollincrement 20
    
    frame .$name.buttons 
    
    # # # button .$name.buttons.reset \
    # # #         -relief raised \
    # # #         -text $TE_MODE_NAVIG_RESET_TEXT \
    # # #         -command "te:mode:rescan_hook; te:mode:set_struct $name"
    button .$name.buttons.reset \
            -relief raised \
            -text $TE_MODE_NAVIG_RESET_TEXT \
            -command [list te:mode:set_struct $name]
  
    # En test : si pas trop lent (pour tres gros fichier latex ou tcl
    # avec beaucoup de proc,
    # alors c'est plus propre de réexaminer le fichier à chaque appel
    # du bouton "Navig"
    # 
    # button .$name.buttons.done \
    #         -relief raised \
    #         -text "Done" \
    #         -command "wm withdraw .$name"
    button .$name.buttons.done \
            -relief raised \
            -text "Done" \
            -command "destroy .$name"
    
  
    .$name.frame.canvas configure -height 500 -width 500
  
    bind .$name.frame.canvas <2> {%W scan mark %x %y ; set fcanvas_x0 %x}
    bind .$name.frame.canvas <B2-Motion> {%W scan dragto $fcanvas_x0 %y}
  
    pack .$name.buttons.reset .$name.buttons.done \
            -in .$name.buttons -fill x -side right
    
    pack append .$name.frame \
        .$name.frame.scroll    {left frame center filly} \
        .$name.frame.canvas    {top frame center fillx filly}
  
    pack .$name.frame .$name.buttons -in .$name -side top -fill x
    
    if {$state=="withdrawn"} {
        wm withdraw .$name
    } elseif {$state == "iconic"} {
        wm iconify .$name
    } else {
        xtk_placeWindow .$name
    }
}

## te:mode:set:navig_window - cree ou affiche la fenetre navig
# 
proc te:mode:set:navig_window { {name navig} } {
    if ![winfo exists .$name] {
        te:mode:set_struct $name
    }
    xtk_placeWindow .$name
}


## te:mode:toupper - OBSOLETE = voir [string totitle ...]
# 
# 
proc te:mode:toupper {mode} {
    return [string totitle $mode]
}


## te:mode:make_menu - create a mode menu named name OBSOLETE (à éclater)
# 
# A eclater dans les fichiers de mode
# 
proc te:mode:make_menu {name} {

    # EXEMPLE POUR L'ECLATEMENT :
    # 
    # global stead
    # 
    # set menubutton  .menu.$stead(mode)
    # set m           .menu.$stead(mode).m
    # 
    # if {[winfo exists $menubutton]} {
    #     destroy $menubutton
    # }
    # # Création d'un bouton de menu (ce qu'on voit)
    # menubutton $menubutton \
    #         -text [string totitle $stead(mode)] \
    #         -menu .menu.$stead(mode).m
    #         
    # # On positionne ce bouton
    # pack append .menu $menubutton left
    # 
    # # Création d'un menu (ce qui ce déroule quand on clique sur 
    # # le menubutton)
    # set m [menu $m]
  
    
    
    if [winfo exists .menu.$name] {
        destroy .menu.$name
    }
  
    menubutton .menu.$name \
            -text [te:mode:toupper $name] \
            -menu .menu.$name.m
  
    set m [menu .menu.$name.m]
  
    pack append .menu .menu.$name left
    
    return $m
}

## te:mode:destroy_menu - destroy the mode menu DEPRECATED (diam le 26/11/02)
# 
proc te:mode:destroy_menu {name} {
    catch {destroy .menu.$name}
}  

## te:mode:make_navig_menu - cree le menu de navigation
# 
proc te:mode:make_navig_menu {} {
    global stead
    global TE_MODE_SEARCH_STRING TE_MODE_NAVIG_SHOW_TEXT
    
    if [info exists TE_MODE_NAVIG_SHOW_TEXT] {
         set name $TE_MODE_NAVIG_SHOW_TEXT
    } else {
         set name "navig"
    }
    
    if [winfo exists .menu.navig] {
         destroy .menu.navig
    }
    
    if [info exists TE_MODE_SEARCH_STRING] {

        # Essai diam le 07/08/02
        # button .menu.navig \
        #             -text [te:mode:toupper $name] \
        #             -command "te:mode:set:navig_window $name"
    
        button .menu.navig \
                    -text [te:mode:toupper $name] \
                    -padx 0 \
                    -pady 0 \
                    -command "te:mode:set:navig_window $name"
        
        
        pack append .menu .menu.navig right
    } 
} 

## te:mode:add_edit_commands - ajoute les commandes d'edition des fichier modes
# 
# - du fichier systeme $stead(mode)-main.tcl dans $stead(install)/lib/modes
# - du fichier utilisateur $stead(mode)-main.tcl dans $stead(userlib)
# - du fichier utilisateur $stead(mode)-user.tcl dan  $stead(userlib)
# 
proc te:mode:add_edit_commands {mode} {

    global stead
    set mode $stead(mode)
    
    if {![winfo exists .menu.$mode.m]} {
        return
    }
    .menu.$mode.m add separator
        
    .menu.$mode.m add command \
            -label "Edit (Show) System \"$stead(mode)-main.tcl\" File" \
            -command {
                stead -readonly 1 \
                    [file join $stead(install) lib modes $stead(mode)-main.tcl]
            }
            
    .menu.$mode.m add command \
            -label "Edit User \"$mode-main.tcl\" File" \
            -command {
                te:create_dir $stead(userlib)
                stead [file join $stead(userlib) $stead(mode)-main.tcl]
            }
                    
    .menu.$mode.m add command \
            -label "Edit \"$mode-user.tcl\" File" \
            -command {
                te:create_dir $stead(userlib)
                stead [file join $stead(userlib) $stead(mode)-user.tcl]
            }
                    
    .menu.$mode.m add command \
            -label "Apply [string totitle \$stead(mode)] Config Changes" \
            -command {stead:modeApply $stead(mode)}
}
#./
