#
# $Header: /home/rockware/cvs-main/operator/tcl/opDirDisplay.tcl,v 1.30 1995/03/16 12:43:20 erez Exp $
# Written by: Erez Strauss (C) All Rights Reserved 1994, 1995.
#
#
# The OpDirDisplay class is derived from the OpTopLevel iclass and
# is used as a base class for all the classes that display directories
# in different forms.
# The current implemented display forms are:
#  OpDirView - Display the directory as two list; directories, files.
#  OpDirTree - Display the directory tree as a graphic tree in canvas.
#  OpDirIcon - Display the directory as Icons in canvas. (not yet implemented).
#

itcl_class OpDirDisplay {
    inherit OpTopLevel

    constructor {directory config} {
        set dir $directory
        set swd [pwd]
        cd $dir
        set dir [pwd]
        cd $swd

        OpTopLevel::constructor \
            -buttons $buttons \
            -title "[virtual what_label] of $dir" \
            -name "[virtual what_label] of $dir" \
            -iconname "[file tail $dir] [virtual what_label]"

        # -buttons $dird_buttons

        frame $work_space.f
        opLabeledEntry $work_space.f.in In {} 8
        opLabeledEntry $work_space.f.out Out {} 8
        opLabeledEntry $work_space.dir Directory OPDirDisplay($this,directory) 32
        ::pack $work_space.f.in -side left
        ::pack $work_space.f.out -side right
        # Set the startup values for the entries.
        bind $work_space.f.in.entry  <Return> "$this config -regexp_in \[$work_space.f.in.entry get]"
        bind $work_space.f.out.entry <Return> "$this config -regexp_out \[$work_space.f.out.entry get]"
        bind $work_space.dir.entry <Return> "$this move_to_dir \[glob \[$work_space.dir.entry get]]"
        global OPDirDisplay OPDirNewWin
        set OPDirDisplay($this,filter) $disp_filter_flag
        set OPDirDisplay($this,dir_disp) $disp_dir_flag
        set OPDirDisplay($this,directory) $dir
        set OPDirDisplay(new_win) $open_new_win
        .control add [$this what_label] [file tail $dir] "$this raise"
        set dir2obj([virtual info class],$dir) $this

        # blt_drag&drop source $work_space config \
            -button 3 \
            -packagecmd "$this dd_pkg" \
            -send all \
            -sitecmd "$this dd_valid" \
            -tokenanchor nw \
            -selftarget true

        # blt_drag&drop source $work_space handler \
            file_name "$this dd_send_file"

        blt_drag&drop source $work_space handler \
            file_name "$this dd_send_file"

        blt_drag&drop target $this handler \
            file_name "$this dd_recv_file"

        filter_disp
    }
    destructor {
        global OPDirDisplay
        catch {unset OPDirDisplay($this,filter)}
        catch {unset OPDirDisplay($this,dir_disp)}
        catch {unset OPDirDisplay($this,directory)}
        unset dir2obj([virtual info class],$dir)
        .control remove [$this what_label] [file tail $dir]
        OpTopLevel::destructor
    }
    method config config {}

    method update config {
        if $in_update return
        set in_update 1
        virtual disp_start
        set swd [pwd]
        cd $dir
        set fd [::open |$pipe_cmd r]
        cd $swd
        while {[gets $fd entry] > 0} {
            if [filter $entry] {
                virtual disp_entry $entry
            }
        }
        close $fd
        virtual disp_end
        tk_entrySeeCaret $work_space.dir.entry
        set in_update 0
    }

    # methods that will be overloaded / defined in sub classes.
    # method disp_start {} {}      - called when update starts it's work.
    # method disp_end {} {}        - called at the end of update work.
    # method disp_entry entry {}   - called for each line read from fd.
    # method filter entry {}       - filter the entries, 1 display, 0 ignore.
    # method command {}            - return a string with the command to run.

    method what_dir {} {return $dir}

    method filter entry {
        set r 1
        if {$regexp_in != {}} {
            catch {if ![regexp $regexp_in $entry] {set r 0}}
        }
        if {$regexp_out != {}} {
            catch {if [regexp $regexp_out $entry] {set r 0}}
        }
        return $r
    }
    method filter_disp {} {
        if $disp_dir_flag {
            ::pack $work_space.dir -fill x -side bottom
        } {
            ::pack forget $work_space.dir
        }
        if $disp_filter_flag {
            ::pack $work_space.f -fill x -side bottom
        } {
            ::pack forget $work_space.f
        }
    }
    method move_to_dir {directory config} {
        set swd [pwd]
        cd $directory
        set directory [pwd]
        cd $swd

        if [::info exists dir2obj([virtual info class],$directory)] {
            $dir2obj([virtual info class],$directory) raise
            return
        }
        unset dir2obj([virtual info class],$dir)
        set dir2obj([virtual info class],$directory) $this

        .control label_update [$this what_label] [file tail $dir] [file tail $directory]

        set dir $directory

        global OPDirDisplay
        set OPDirDisplay($this,directory) $dir

        $this config \
            -title "[virtual what_label] of $dir" \
            -iconname "$dir [virtual what_label]" \
            -name "[virtual what_label] of $dir"

        update
    }

    method dd_valid {state token} {
        if $state {
            # $token.value config -bitmap @[opNameToFile thumb_up bitmap]
            $token.value config -bitmap @[opNameToFile tick bitmap]
            # set bg [lindex [$token.value config -bg] 4]
            # set fg [lindex [$token.value config -fg] 4]
            # $token.value config -bg $fg
            # $token.value config -fg $bg
        } {
            $token.value config -bitmap @[opNameToFile noenter_dot bitmap]
            # set no entry sign.
        }
    }

    method dd_send_file {interp ddwin data} {
        send $interp "
        global DragDrop
        set DragDrop(file_name) {$data}
        "
        send $interp "blt_drag&drop target $ddwin handle file_name"
    }

    method dd_recv_file {} {
        global DragDrop
        puts "opDialogFileCopy $DragDrop(file_name) [what_dir]"
        set d [file dirname $DragDrop(file_name)] ;# source directory
        # uobj - those objects that display the directory.
        set uobj $this
        if [::info exists dir2obj(OpDirView,$d)] {if {$dir2obj(OpDirView,$d) != $this} {append uobj " $dir2obj(OpDirView,$d)"}}
        if [::info exists dir2obj(OpDirTree,$d)] {if {$dir2obj(OpDirTree,$d) != $this} {append uobj " $dir2obj(OpDirTree,$d)"}}
        if [::info exists dir2obj(OpDirIcons,$d)] {if {$dir2obj(OpDirIcons,$d) != $this} {append uobj " $dir2obj(OpDirIcons,$d)"}}
        set d $dir
        if [::info exists dir2obj(OpDirView,$d)] {if {$dir2obj(OpDirView,$d) != $this} {append uobj " $dir2obj(OpDirView,$d)"}}
        if [::info exists dir2obj(OpDirTree,$d)] {if {$dir2obj(OpDirTree,$d) != $this} {append uobj " $dir2obj(OpDirTree,$d)"}}
        if [::info exists dir2obj(OpDirIcons,$d)] {if {$dir2obj(OpDirIcons,$d) != $this} {append uobj " $dir2obj(OpDirIcons,$d)"}}
        # lsort -unique uobj
        .fileCopy on -src $DragDrop(file_name) -trg [what_dir] \
            -update $uobj
    }

    # show_one
    # if there is a selection, then open the selection directory.
    # if there is no window from the given iclassi, then popup a dialog
    # with the question which directory.
    # else show one of the windows from the given iclass.
    proc show_one {class} {
        # set class [virtual info class] - how can the proc know in what class it operates ?
        if {"[selection own]" == {}} {
            set o [itcl_info objects -class $class]
            if {$o == {}} {
                .fileSelect on -message "Please enter directory name for the new Directory $class" -command "if {{%1\$s}=={}} {$class :: open ~} {$class :: open %1\$s}"
            } {
                set o [lindex $o 0]
                $o raise
            }
        } {
            $class :: open [opSelectionGet]
        }
    }

    proc set_new_win nvalue {
        set open_new_win $nvalue
    }
    # the command we run in the directory to get the entries.
    public pipe_cmd {} {if $after_constructor update}

    # regexp filter those that match are displayed.
    public regexp_in {} {if $after_constructor update}
    # regexp filter those that match are >not< displayed.
    public regexp_out {} {if $after_constructor update}
    public disp_filter_flag 1 {if $after_constructor filter_disp}
    public disp_dir_flag 1 {if $after_constructor filter_disp}

    # Directory that we work on.
    protected dir {}
    protected in_update 0 ;# Is the object in the middle of updating process ?

    protected dird_menus {
        {dird_file {
            {command -label Rescan -command {THIS update} -underline 0}
            {command -label Minimize -command {THIS iconify} -underline 0}
            {command -label {Directory Tree} -command {OpDirTree :: open [THIS what_dir]} -underline 0}
            {command -label Xterm -command {after 10 {OpXTerm :: new -dir [THIS what_dir]}} -underline 0}
            {command -label Edit -command {opFileEdit [opSelectionGet]} -underline 0}
            {label -label {Update List Cmd} -underline 0 -command {opEntriesMenu .cmdupdate Update {{{List Command:} {}}} {{OK . {destroy .cmdupdate}}}}}
            {label -label Diff -underline 0 -command {opViewDiff [opSelectionGet]}}
            {label -label Compile -underline 2 -command {opDialogCompile [opSelectionGet]}}
            {separator}
            {label -label Find -underline 2 -command {opDialogFindFile [opSelectionGet]}}
            {label -label Print -underline 0 -command {opDialogPrint [opSelectionGet]}}
            {command -label Quit -command {THIS delete} -underline 0}}
        }
        {dird_edit {
            {label -label New     -underline 0 -command {} }
            {command -label Open    -underline 0 -command {opFileActivate [opSelectionGet]}}
            {command -label Run     -underline 0 -command {opDialogRun [opSelectionGet]}}
            {label -label View    -underline 0 -command {opFileView [opSelectionGet]}}
            {label -label Copy    -underline 0 -command {opDialogCopy [opSelectionGet]}}
            {label -label Rename  -underline 1 -command {opDialogRename [opSelectionGet]}}
            {command -label Remove  -underline 2 -command {if {[selection own] != {}} {.fileRemove on -src [opSelectionGet] -update THIS} {.fileSelectFirst on}}}
            {command -label MkDir   -underline 0 -command {.fileMakeDirectory.dname.entry insert 0 [THIS what_dir] ; .fileMakeDirectory on -src [THIS what_dir] -update THIS}}
            {label -label {Change Mode} -underline 4 -command {opDialogCangeMode}}}
        }
        {dird_opt {
            {checkbutton -label {Show Filter} -onvalue 1 -offvalue 0 -variable OPDirDisplay(THIS,filter) -command {global OPDirDisplat ; THIS config -disp_filter_flag $OPDirDisplay(THIS,filter)}}
            {checkbutton -label {New Win} -onvalue 1 -offvalue 0 -variable OPDirDisplay(new_win) -command {global OPDirDisplay ; [THIS info class] :: set_new_win $OPDirDisplay(new_win)}}
            {command -label {Move up ..} -under 0 -command {THIS move_to_dir [THIS what_dir]/..}}
            {command -label Variables -under 0 -command command}
            {command -label Test -under 0 -command command}}
        }
        {dird_view_opt {
            {checkbutton -label Directories -onvalue 1 -offvalue 0 -variable OPDirViewInfo(w,dirs) -command {opDirViewPack w}}
            {checkbutton -label Files -onvalue 1 -offvalue 0 -variable OPDirViewInfo(w,files) -command {opDirViewPack w}}}
        }
    }
    protected dird_buttons {
        {Rescan . {THIS update} {} {Rescan Directory} {Reread directory}}
        {Tree   . {OpDirTree :: open [THIS what_dir]} {} {Open Tree view of the $dir directory} {Open Tree View window of current directory}}
        {XTerm . {after 5 {OpXTerm :: new -dir [THIS what_dir]}}
            {} {Open Xterm} {Create xterm windows at the current directory}}
    }
    common dird_menubar {{File 0 dird_file} {Edit 0 dird_edit} {Option 0 dird_opt} {Help 0 tl_help right}}
    common open_new_win 0 ; # open new window for each dirctory,
    # 0 change the current directory of the already opened window.
    common dir2obj
}
# End of opDirDisplay.tcl.
