#
# $Header: /home/rockware/cvs-main/operator/tcl/opDialogs.tcl,v 1.36 1995/03/14 21:52:49 erez Exp $
# Written by: Erez Strauss (C) All Rights Reserved 1994, 1995.
#
# 13. Dialogs - Most of them.
#
# All the dialogs should be derived from the base OpDialog class.
#
#              .appGrpNewItem - Choose item type.
#              .appGrpConfirmDeleteItem
#              .appGrpConfirmExec
#              .appGrpSelectFirst - Info, See .fileSelectFirst
#
# opDialogConfirmQuit  .confirmQuit
#
# opDialogCangeMode    .fileChangeMode
# opDialogCangeOwner   .fileChangeOwner
#                      .fileUpdateInfo - Owner Entry, and CheckButtons for the modes.
#                           
# opDialogFileCopy     .fileCopy
#                      .fileCopyEntries - The sam as the above but with two
#                           Entries with the source and the target.
#                      .fileRemove
# opDialogDirCreate    .fileMakeDirectory
# opDialogFileRename   .fileMove
# opDialogFileRun      .fileRun - The same as copy.
# opDialogFileFind     .fileFind - 
#                      .filePrint
#                      .fileSelectFirst - Info, Select a File before activating an action.
#
# opDialogGlobals      .globals
# opDialogPrint        .print
#                      .helpSubject
#                      .xtermConfirmQuit
#
# The Standard buttons are 'OK Apply Cancel Help'
#
# First the OpDialog class.
itcl_class OpDialog {
    inherit OpTopLevel
    
    constructor config {
        OpTopLevel::constructor
        # Create the message widget and arrange for it to be centered in the
        # work space

        message $work_space.msg -justify center \
            -font -Adobe-times-medium-r-normal--*-180* -text $message \
            -aspect 350
        ::pack $work_space.msg -side right -expand yes -padx 2 -pady 2
        if {$i_icon != {}} {
            set bm @[opNameToFile $i_icon bitmap]
            if {$bm == {@}} {set bm $i_icon} ;# enable direct bitmap name
            label $work_space.i_icon -bitmap $bm -relief raised
            ::pack $work_space.i_icon -side right
        }
        off   ;# Don't display the dialog box on creation.
    }
    destructor {
        OpTopLevel::destructor
    }
    method config config {}
    method on config {
        set old_focus [focus]
        $work_space.msg config -text [format $message $src $trg]
        if {$default != {}} {$this.buttons config -default $default}
        if {$center} {
            update idletasks
            set x [expr [winfo screenwidth $this]/2 - [winfo reqwidth $this]/2 \
                       - [winfo vrootx [winfo parent $this]]]
            set y [expr [winfo screenheight $this]/2 - [winfo reqheight $this]/2 \
                       - [winfo vrooty [winfo parent $this]]]
            wm geom $this +$x+$y
        }
        wm deiconify $this
        # raise - cause inconvinent popup.
        if {$focus != {}} {
            focus $this.$focus
        } {
            focus $this
        }
        if {$grab != {}} {
            tkwait visibility $this
            if {$grab == "global"} {
                grab set -global $this
            } {
                grab set $this
            }
        }
        if $wait {
            global OPDialogs
            set OPDialogs($this) 1
            tkwait variable OPDialogs($this)
        }
    }
    method off config {
        set src {}
        set trg {}
        set update {}
        wm withdraw $this
        if {$old_focus != {}} {
            catch {focus $old_focus}   ;# The old window might not exists any more.
        }
        grab release $this
        global OPDialogs
        if [info exists OPDialogs($this)]   "set OPDialogs($this) 0"
    }
    method what_src {} {return $src}
    method what_trg {} {return $trg}
    method what_command {} {return $command}
    method invoke config {return [eval [format $command $src $trg]]}
    # ------------------------------------------------------------------------
    # METHOD do_update
    #  update all the objects that the action by this dialog changed them.
    # ------------------------------------------------------------------------
    method do_update {} {
        foreach o $update {
            $o update
        }
        off
    }
    public message {} { ;# The message to display.
        if {$after_constructor} {
            $work_space.msg configure -text $message
        }
    }
    public i_icon {} {}
    public state off {} ;# on / of
    public command {} {}
    public data {} {}
    public src {} {} ;# for the different dialogs, Soure variable
    public trg {} {} ;# for the different dialogs, Target variable
    public update {} {} ;# list of opbject that should be updated, see do_update
    public grab {} {} ;# {} local global
    public focus {} {} ;# widget that should get the focus by the on method
    public center 0 {} ;# Should we put the window in the center of the screen ?
    public wait 0 {} ;# should the on method wait until an action is taken ?
    public default {} {} ;# if != {} the default button.
    protected old_focus {}
}

# Each Dialog will be an instance of the OpDialog
# Here at last we create the instances.

OpDialog .welcomeMessage \
    -name {Operator Welcome message} -title {Welcome} \
    -message { Welcome to Operator.
The Operator is a files and Applications manager
} -buttons {
        {OK . {THIS off} {} {} {}}
        {Quit . {exit} {} {} {Quit from Operator}}
}

# files dialogs

OpDialog .fileMakeDirectory \
    -name {Make Directory} -title {Make Directory} \
    -message {Do you really want to Create Directory ?} \
    -pack_option 1 -grab local -i_icon questhead \
    -buttons {
        {Create . {exec mkdir [.fileMakeDirectory.dname.entry get] ; THIS do_update ; .fileMakeDirectory.dname.entry delete 0 end} {} {Create new directory} {Create new directory}}
        {Cancel . {THIS off ; .fileMakeDirectory.dname.entry delete 0 end} {} {Cancel the Remove opration} {Cancel the Remove opration window}}
        {Help . {opHelp create_directory} {} {More helpful information} {More helpful information}}
    } -focus buttons -center 1
.fileMakeDirectory.buttons config -default 1 -padx 6 -pady 6 -relief groove -borderwidth 2
opLabeledEntry .fileMakeDirectory.dname {Directory name} {} 20
pack .fileMakeDirectory.dname

# To Activate a dialog box the program should call something like this:
# .fileRemove on -data {FileName} 

# Remove - src - the file to remove.
# Update the rm command to 'mv src $OPTrashDir'
OpDialog .fileRemove \
    -name {Remove File} -title {Remove File} \
    -message {Do you really want to remove the file '%1$s' ?} \
    -pack_option 1 -grab local -i_icon questhead \
    -buttons {
        {{Remove !} . {global OPInfo ; exec mv [THIS what_src] $OPInfo(user_trash_dir) ; THIS do_update} {} {Remove the file} {Remove (erase) the file}}
        {Cancel . {THIS off} {} {Cancel the Remove opration} {Cancel the Remove opration window}}
        {Help . {opHelp remove_file} {} {more helpful information} {more helpful information}}
    } -focus buttons -center 1
.fileRemove.buttons config -default 1 -padx 6 -pady 6 -relief groove -borderwidth 2

OpDialog .fileCopy \
    -name {Copy File} -title {Copy File} \
    -message {Do you really want to copy/move %1$s into %2$s ?} \
    -pack_option 1 -grab local -i_icon questhead \
    -buttons {
        {Copy . {exec cp [THIS what_src] [THIS what_trg] ; THIS do_update} {} {Copy the file.} {Copy the file.}}
        {Move . {exec mv [THIS what_src] [THIS what_trg] ; THIS do_update} {} {Move the file to the other directory.} {Move the file to the other directory.}}
        {Cancel . {THIS off} {} {Cancel the copy opration} {Cancel the copy opration window}}
        {Help . {opHelp copy_file} {} {more helpful information} {more helpful information}}
    } -focus buttons -center 1
.fileCopy.buttons config -default 0 -padx 6 -pady 6 -relief groove -borderwidth 2

OpDialog .dirSelectForDisplay -name {Select Directory or File} \
    -title {Select Directory or File} \
    -message {Please select directory for displaying} \
    -pack_option 1 -i_icon info -buttons {
        {Cancel . {THIS off} {} {} {}}
    } -focus buttons -grab local
.dirSelectForDisplay.buttons config -default 0 -padx 6 -pady 6 -relief groove -borderwidth 2

# commad
OpDialog .fileSelect -name {Select File} \
    -title {Select File} \
    -message {Please select directory for displaying} \
    -pack_option 1 -i_icon questhead -buttons {
        {OK . {THIS invoke -src [.fileSelect.info.filename.entry get]; THIS off} {} {} {}}
        {Cancel . {THIS off} {} {} {}}
    } -focus buttons
.fileSelect.buttons config -default 0 -padx 4 -pady 4 -relief groove -borderwidth 2
opLabeledEntry .fileSelect.info.filename {File Name} {} 20
pack .fileSelect.info.filename -before .fileSelect.info.msg -side bottom -expand off
bind .fileSelect.info.filename.entry <Return> {.fileSelect invoke -src [%W get] ; .fileSelect off}
blt_drag&drop target .fileSelect handler \
    file_name "
    global DragDrop
    .fileSelect.info.filename.entry delete 0 end
    .fileSelect.info.filename.entry insert 0 \$DragDrop(file_name)
    .fileSelect.info.filename.entry icursor \[string length \$DragDrop(file_name)]
    tk_entrySeeCaret .fileSelect.info.filename.entry
    "


OpDialog .fileSelectFirst -name {Select File before action} \
    -title {Select File before action} \
    -message {Before you select file operation you should select a file !} \
    -pack_option 1 -i_icon info -buttons {
        {OK . {THIS off} {} {} {}}
    } -focus buttons -grab local
.fileSelectFirst.buttons config -default 0 -padx 4 -pady 4 -relief groove -borderwidth 2

OpDialog .fileEmptyDisplay -name {No files found (match filtering)} \
    -title {No Files found or matched the filtering criteria} \
    -message {The directory display is empty, because there are no files matching the filtering criteria, or the directory is really empty} \
    -pack_option 1 -i_icon info -buttons {
        {OK . {THIS off} {} {} {}}
    } -focus buttons -grab local
.fileEmptyDisplay.buttons config -default 0 -padx 4 -pady 4 -relief groove -borderwidth 2

#
# Operator Dialogs.

# opDialogConfirmQuit  .confirmQuit
# *** What is the difference between 'exit' and 'destroy .' ??
OpDialog .confirmQuit -name {Quit ?} -title {Quit ?} -i_icon questhead \
    -message {Are you sure you want to Quit from Operator ?} \
    -pack_option 1 -buttons {
        {Quit . {exit} {} {Quit Operator} {Quit Operator}}
        {Cancel . {THIS off} {} {Cancel the Quit Operation} {Cancel the Quit Operation}}
    } -focus buttons -grab global -center 1
.confirmQuit.buttons config -default 0 -padx 6 -pady 6 -relief groove -borderwidth 2

# XTerm Confirm Quit
# The src is the name of the OpXTerm instance.
OpDialog .xtermConfirmQuit -name {XTerm Quit ?} -title {XTerm Quit ?} \
    -message {Are you sure you want to end the XTerm session ?} \
    -pack_option 1 -i_icon questhead -buttons {
        {OK . {[THIS what_src] delete ; THIS off} {} {End XTerm session} {End XTerm session}}
        {Cancel . {THIS off} {} {Don't end the XTerm session} {Don't end the XTerm session}}
    } -focus buttons -grab global -center 1 -wait 1
.xtermConfirmQuit.buttons config -default 0 -padx 6 -pady 6 -relief groove -borderwidth 2

#

OpDialog .appGrpNewItem -name {New Application / Group} -title {New Application / Group} \
    -message {Enter new item name and press button} \
    -pack_option 1 -buttons {
        {Application . {[OpAppGroupApp [string tolower [THIS what_src]/[.appGrpNewItem.name.entry get]]] win_edit [THIS what_trg]; THIS off} {} {New Application} {New Application}}
        {{App Group} . {[OpAppGroupGrp [string tolower [THIS what_src]/[.appGrpNewItem.name.entry get]]] win_edit [THIS what_trg]; THIS off} {} {New Applications Group} {New Applications Group}}
        {Cancel . {THIS off} {} {Quit the creation of new item} {Cancel the creation of new applications groups item}}
    } -focus buttons -i_icon questhead
.appGrpNewItem.buttons config -padx 4 -pady 4 -relief groove -borderwidth 2
opLabeledEntry .appGrpNewItem.name Name {} 20
opBalloonHelp .appGrpNewItem {Name should be one word in lower case}

OpDialog .appGrpConfirmDeleteItem -name {Are you sure you want to delete Item} \
    -title {Delete Item} \
    -message {Are you sure you want to delete Item '%1$s' ?} \
    -pack_option 1 -i_icon questhead -buttons {
        {OK . {[THIS what_src] remove ; THIS do_update} {} {Delete Item} {Delete Item}}
        {Cancel . {THIS off} {} {Quit the deletion of new item} {Cancel the deletion of item}}
    } -focus buttons
.appGrpConfirmDeleteItem.buttons config -default 1 -padx 4 -pady 4 -relief groove -borderwidth 2

OpDialog .appGrpConfirmExec -name {Application execution confirmation} \
    -title {Execute Application} \
    -message {Are you sure you want to execute '%1$s' ?} \
    -pack_option 1 -i_icon questhead -buttons {
        {OK . {[THIS what_trg] dorun ; THIS off} {} {Execute Application} {Execute Application}}
        {Cancel . {THIS off} {} {Quit the Execution} {Cancel the Execution}}
    } -focus buttons
.appGrpConfirmExec.buttons config -default 1 -padx 4 -pady 4 -relief groove -borderwidth 2

OpDialog .appGrpSelectFirst -name {Select First} \
    -title {Select First} \
    -message {Before you select item operation you should select an item} \
    -pack_option 1 -i_icon info -buttons {
        {OK . {THIS off} {} {} {}}
    } -focus buttons -grab local
.appGrpSelectFirst.buttons config -default 0 -padx 4 -pady 4 -relief groove -borderwidth 2

OpDialog .appGrpGroupNotEmpty -name {Applications group not empty} \
    -title {Applications group not empty} \
    -message {The selected applications group is not empty.
Please delete first the applications inside this group. Only then remove the group.} \
    -pack_option 1 -i_icon info -buttons {
        {OK . {THIS off} {} {} {}}
    } -focus buttons -grab local
.appGrpSelectFirst.buttons config -default 0 -padx 4 -pady 4 -relief groove -borderwidth 2

OpDialog .helpMessage -name {Help Information} -title {Help Information} \
    -pack_option 1 -i_icon info -buttons {
        {OK . {THIS off} {} {Close Help Message} {}}
        {Print . {puts [lindex [THIS.info.msg config -text] 4]} {} {Print Message (using lpr).} {Print Message (using lpr).}}
        {Index . {} {} {No implemented yet} {Not implemented yet}}
    } -focus buttons -center 1 -wait 1
.helpMessage.buttons config -default 0 -padx 6 -pady 6 -relief groove -borderwidth 2
.helpMessage.info.msg config -justify left
opLabeledEntry .helpMessage.info.search {Help Subject} {} 20
pack .helpMessage.info.search -before .helpMessage.info.msg -side bottom -expand off
bind .helpMessage.info.search.entry <Return> {+opHelp [.helpMessage.info.search.entry get]}
mm_MenuAttach .helpMessage  help_index
mm_MenuAttach .helpMessage.info.search.entry  help_index
mm_MenuAttach .helpMessage.info.msg  help_index
mm_MenuAttach .helpMessage.buttons  help_index

# Each Dialog class will have one object that will be used through all the
# application for the specific dialog, named .xxxYyy , where xxx and yyy are
# the last parts of the of the class name.
#
# opDialogRun
# options: activate a new xterm, io redirect (with default), options,
# Add to a list of last run commands (in case it deffer from the last run).
#
proc opDialogRun { file } {
    if [llength $file]<=0 return
    set w .dialogrun
    set n "Execute File (Command)"
    catch {destroy $w}
    toplevel $w -relief sunken
    set old_focus [focus]
    wm title $w $n
    wm iconname $w $n
    # title setting.
    frame $w.title -relief flat -borderwidth 0
    pack $w.title -side top -fill x
    label $w.title.n -text $n -relief raised -borderwidth 1
    pack $w.title.n -side top -fill x -expand on
    # command entries creation.
    frame $w.info -relief flat -border 2
    pack $w.info -side top -fill both -expand on
    label $w.info.l -text "Command to execute"
    pack $w.info.l -side left
    entry $w.info.command -width 40 -relief sunken
    $w.info.command insert 0 $file
    pack  $w.info.command -side right
    bind $w.info.command <Key-Return> "
    exec \[$w.info.command get]
    destroy $w
    focus $old_focus"
    bind $w <Key-Escape> {destroy $w}
    bind Entry <Home> {%W icursor 0}
    bind Entry <End>  {%W icursor [string length [%W get]]}
    bind Entry <Enter>  {focus %W}
    # Buttons creation.
    frame $w.b -relief sunken -borderwidth 1
    pack $w.b -side bottom -fill x -expand on -ipadx 5 -ipady 5
    button $w.b.ok -text Execute -padx 10 -pady 5 -command "
    exec \[$w.info.command get]
    destroy $w
    focus $old_focus"
    pack  $w.b.ok -side left -expand yes
    # button $w.b.add -text "Add" -padx 10 -pady 5 -command "destroy $w"
    # pack  $w.b.add -side right -expand yes
    button $w.b.cancel -text Cancel -padx 10 -pady 5 -command "destroy $w"
    pack  $w.b.cancel -side right -expand yes
    focus $w.info.command
}
# Entries menues
# each list entry is a list of two elements
# the first is the Label of the entry, The second is a name of a variable that
# should be used to hold the value.
#
proc opEntriesMenu { w t l {blist {}} } {
    catch {destroy $w}
    OpTopLevel $w -title $t -iconname $t -name $t -buttons $blist
    set d [$w work_space]
    # globals names.
    set n [llength $l]
    set glb_list {}
    set v_list {}
    foreach e $l {
        lappend glb_list [lindex $e 1]
        append v_list " \$[lindex $e 1]"
    }
    eval global $glb_list
    # Entries creation.
    set i 0
    foreach e $l {
        frame $d.$i
        pack  $d.$i -side top -pady 2 -anchor e
        label $d.$i.label -text [lindex $e 0] -anchor e
        entry $d.$i.entry -width 30 -relief sunken \
            -textvariable [lindex $e 1]
        pack  $d.$i.entry $d.$i.label -side right
        incr i
    }
    bind Entry <Home> {%W icursor 0}
    bind Entry <End>  {%W icursor [string length [%W get]]}
    # Buttons creation.
    # *** The buttons will be created by TopLevel.
    frame $w.b -relief sunken -borderwidth 2
    pack $w.b -side bottom -fill x -ipadx 5 -ipady 5
    button $w.b.print -text Print -command "puts \"$v_list\"" -padx 10 -pady 5
    pack  $w.b.print -side left -expand on
    for {set i 0} {$i < [llength $blist]} {incr i} {
        set b [lindex $blist $i]
        button $w.b.$i -text [lindex $b 0] -command \
            "set swd \[pwd] ; cd [lindex $b 1] ; [lindex $b 2] ; cd \$swd" \
            -bitmap [lindex $b 3] -padx 10 -pady 5
        pack $w.b.$i -side left -expand on
        opActiveHelpBind $w.b.$i [lindex $b 4]
    }
}
# The mkDialog procedure below was pirated from the widget demo.  It
# was not written fresh for this benchmark.

# Create a dialog box.  Takes three or more arguments.  The first is
# the name of the window to use for the dialog box.  The second is a set
# of arguments for use in creating the message of the dialog box.  The
# third and following arguments consist of two-element lists, each
# describing one button.  The first element gives the text to be displayed
# in the button, the second gives the command to be invoked when the
# button is invoked.

proc mkDialog {w msgArgs args} {
    catch {destroy $w}
    toplevel $w -class Dialog
    set oldFocus [focus]

    # Create two frames in the main window. The top frame will hold the
    # message and the bottom one will hold the buttons.  Arrange them
    # one above the other, with any extra vertical space split between
    # them.

    frame $w.top -relief raised -border 1
    frame $w.bot -relief raised -border 1
    pack $w.top $w.bot -side top -fill both -expand yes

    # Create the message widget and arrange for it to be centered in the
    # top frame.

    eval message $w.top.msg -justify center \
        -font -Adobe-times-medium-r-normal--*-180* $msgArgs
    pack $w.top.msg -side top -expand yes -padx 2 -pady 2

    # Create as many buttons as needed and arrange them from left to right
    # in the bottom frame.  Embed the left button in an additional sunken
    # frame to indicate that it is the default button, and arrange for that
    # button to be invoked as the default action for clicks and returns in
    # the dialog.

    if {[llength $args] > 0} {
        set arg [lindex $args 0]
        frame $w.bot.0 -relief sunken -border 1
        pack $w.bot.0 -side left -expand yes -padx 10 -pady 10
        button $w.bot.0.button -text [lindex $arg 0] \
            -command "[lindex $arg 1]; destroy $w; focus $oldFocus"
        pack $w.bot.0.button -expand yes -padx 6 -pady 6
        bind $w.top <Enter> "$w.bot.0.button activate"
        bind $w.top.msg <Enter> "$w.bot.0.button activate"
        bind $w.bot <Enter> "$w.bot.0.button activate"
        bind $w.top <Leave> "$w.bot.0.button deactivate"
        bind $w.top.msg <Leave> "$w.bot.0.button deactivate"
        bind $w.bot <Leave> "$w.bot.0.button deactivate"
        bind $w <1> "$w.bot.0.button config -relief sunken"
        bind $w <ButtonRelease-1> \
            "[lindex $arg 1]; $w.bot.0.button deactivate; destroy $w; \
                focus $oldFocus"
        bind $w <Return> "[lindex $arg 1]; destroy $w; focus $oldFocus"
        focus $w

        set i 1
        foreach arg [lrange $args 1 end] {
            button $w.bot.$i -text [lindex $arg 0] \
                -command "[lindex $arg 1]; destroy $w; focus $oldFocus"
            pack $w.bot.$i -side left -expand yes -padx 10
            incr i
        }
    }
    wm geometry $w +300+350
}

proc opDialogGlobals {} {
    set g [lsort [info globals]]
    foreach v $g {
        if [catch {global $v ; array size $v}] {lappend gv $v}
    }
    foreach v $gv {
        lappend x "\"$v: \" $v"
    }
    opEntriesMenu .var "Global Variables" $x
}
# End of opDialogs.tcl.
