#*******************************************************************************
# E.S.O. - VLT project
#
# "@(#) $Id: rtdq4.tcl,v 1.14+ 1999/03/25 10:45:51 vltsccm Exp $"
#
# who       when      what
# --------  --------  ----------------------------------------------
# pbiereic  22/03/99  created

itk::usual rtdq4App {}

class rtdq4App {
    inherit TopLevelWidget

    constructor {args} {
        eval itk_initialize $args
    }

    # this method is called from the base class (TopLevelWidget) after all
    # the options have been evaluated

    method init {} {
        global ::env

        setXdefaults
        wm title $w_ "Rtd - Real-Time Image Display, version [rtd_version]"
        
        # set rtd camera if not set on command line, default to environment var
        if {"$itk_option(-camera)" == ""} {
            if {[info exists env(RTD_CAMERA)]} {
                config -camera $env(RTD_CAMERA)
            } else {
                config -camera RTDSIMULATOR
            }
        }
	wm geometry $w_ 800x750

	# make the layout
        add_menubar
        make_short_help
	make_frames
	make_mainf
	make_ctrl

        [$itk_component(img0) component trans] fill_mag_menu $magwin_
	for {set i 0} {$i < 4} {incr i} {
	    $itk_component(img$i) config -zoomwin $itk_component(zoom)
	}
	select_image 1
	after idle "$this load_images"
    }

    # add the menubar at the top of the window

    method add_menubar {} {
        # menu bar
        TopLevelWidget::add_menubar

        # File menu
        set m [add_menubutton File]

        add_menuitem $m cascade "Open" \
		{Open and display a (FITS) image file} \
		-menu [menu $m.open]
	
        for {set i 0} {$i < 4} {incr i} {
            $m.open add command -label "Image [expr $i+1]..." \
                    -command [code $this open $i]
	}
	    
        $m add separator

        add_menuitem $m command Exit \
            {Exit the application} \
            -command "destroy .; exit"
        
        # View menu
        set m [add_menubutton View]
        add_menuitem $m command "Panning frames..." \
            {Display pan windows for each image} \
            -command [code $this make_panf]
	
        add_menuitem $m command "Colors..." \
            {Display a window for manipulating the image colormap} \
            -command [code $this set_colors]

        add_menuitem $m command "Cut Levels..." \
            {Display a window for manipulating the image cut levels} \
            -command [code $this cut_level_dialog]

        add_menuitem $m cascade "Magnification" \
            {Set the magnification factor of the image display} \
            -menu [menu $m.mag]
	set magwin_ $m.mag
        $m add separator

        # Real-time menu
        set m [add_menubutton "Real-time"]

        add_menuitem $m command "Attach Camera" \
            {Attach the real-time camera - start receiving images} \
            -command [code $this attach_camera]

        add_menuitem $m command "Detach Camera" \
            {Detach the real-time camera - stop receiving images} \
            -command [code $this detach_camera]
    }
    
    # add the short help window and add some help texts for the menu buttons

    method make_short_help {} {
        TopLevelWidget::make_short_help
        add_short_help $itk_component(menubar).file \
            {File menu: load, save, print, clear image, new window, exit application}

        add_short_help $itk_component(menubar).view \
            {View menu: manipulate colors, cut levels, pixel info}

        add_short_help $itk_component(menubar).real-time \
            {Real-time menu: real-time display commands. rapid frame}
    }

    # make control panel

    method make_ctrl {} {
	itk_component add zoom {
	    rtdq4Zoom $itk_component(mctlf).zoom \
		-target_image $itk_component(img0) \
		-borderwidth 3 \
		-relief groove
	}
	pack $itk_component(zoom) -side top

	itk_component add x {
	    util::LabelValue $itk_component(mctlf).x \
		-text "X:" \
		-labelfont $itk_option(-labelfont) \
		-valuefont $itk_option(-valuefont) \
		-labelwidth $itk_option(-labelwidth) \
		-valuewidth $itk_option(-valuewidth) \
		-relief groove \
		-anchor e
	}
	itk_component add y {
	    util::LabelValue $itk_component(mctlf).y \
		-text "Y:" \
		-labelfont $itk_option(-labelfont) \
		-valuefont $itk_option(-valuefont) \
		-labelwidth $itk_option(-labelwidth) \
		-valuewidth $itk_option(-valuewidth) \
		-relief groove \
		-anchor e
	} 
	
	itk_component add value {
	    util::LabelValue $itk_component(mctlf).value \
		-text "Value:" \
		-labelfont $itk_option(-labelfont) \
		-valuefont $itk_option(-valuefont) \
		-labelwidth 6 \
		-valuewidth $itk_option(-valuewidth) \
		-relief groove \
		-anchor e
	}
	pack $itk_component(x) -side top -fill x -anchor w
	pack $itk_component(y) -side top -fill x -anchor w
	pack $itk_component(value) -side top -fill x -anchor w

	add_short_help $itk_component(x) {X image coordinates at mouse pointer}
	add_short_help $itk_component(y) {Y image coordinates at mouse pointer}
	add_short_help $itk_component(value) {Raw image value at X,Y coordinates}

	# label menu for "current image selection"
	itk_component add currimg {
	    util::LabelMenu $itk_component(mctlf).currimg \
                       -text "Image\#:" \
                       -relief groove \
                       -labelfont $itk_option(-labelfont) \
                       -valuefont $itk_option(-valuefont) \
                       -labelwidth 6 \
                       -valuewidth 3 \
                       -anchor e
	}
	foreach el "1 2 3 4 All" {
	    $itk_component(currimg) add -label $el -command "$this select_image $el"
	}
	pack $itk_component(currimg) -side top -fill x

	# low and high cut
	itk_component add low {
	    LabelEntry $itk_component(mctlf).low \
		-text "Low:" \
		-command [code $this set_cut_levels] \
		-labelfont $itk_option(-labelfont) \
		-valuefont $itk_option(-valuefont) \
		-labelwidth $itk_option(-labelwidth) \
		-valuewidth $itk_option(-valuewidth) \
		-anchor e \
		-relief sunken \
		-validate real
	} {
	    keep -state
	}
	pack $itk_component(low) -side top -fill x

	itk_component add high {
	    LabelEntry $itk_component(mctlf).high \
		-text "High:" \
		-command [code $this set_cut_levels] \
		-labelfont $itk_option(-labelfont) \
		-valuefont $itk_option(-valuefont) \
		-labelwidth $itk_option(-labelwidth) \
		-valuewidth $itk_option(-valuewidth) \
		-anchor e \
		-relief sunken \
		-validate real
	}  {
	    keep -state
	}
	pack $itk_component(high) -side top -fill x

	itk_component add autocut {
	    button $itk_component(mctlf).autocut \
		-text "Auto Set Cut Levels" \
		-font $itk_option(-labelfont) \
		-command [code $this auto_set_cut_levels]       
	}
	pack $itk_component(autocut) -side top -fill x
	add_short_help $itk_component(autocut) {Set the image cut levels using median filtering}
    }

    # select an image and update control panel widgets

    method select_image {imgnr} {
	global ::currimg
	set currimg $imgnr
	if [catch {expr $imgnr -1}] {
	    if [winfo exists $w_.cut] {
		set low [[$w_.cut component lowcut] get]
		set high [[$w_.cut component highcut] get]
		[$itk_component(img0) get_image] cut $low $high
		$itk_component(low) config -value $low
		$itk_component(high) config -value $high
		updateValues
	    }
	} else {
	    set n [expr $imgnr -1]
	    lassign [[$itk_component(img$n) get_image] cut] low high
	    $itk_component(low) config -value $low
	    $itk_component(high) config -value $high
	}
    }

    # set the cut levels automatically using median filtering...
    
    method auto_set_cut_levels {} {
	global ::currimg
	set n $currimg
	if [catch {expr $currimg -1}] {
	    set n "1 2 3 4"
	}
	foreach el $n {
	    busy {[$itk_component(img[expr $el -1]) get_image] autocut}
	}
	select_image $currimg
    }

    # display a dialog for selecting objects in the image and displaying information
    # about the selected area of the image

    method pick_dialog {{command ""}} {
        utilReUseWidget rtd::RtdImagePick $w_.pick \
            -target_image $itk_component(img0) \
            -shorthelpwin $this
        $w_.pick pick_object
    }

    # make image and control frames

    method make_frames {} {
	# add container frames
	itk_component add mimgf {frame $w_.mimgf}   ; # main image frame
	itk_component add mctlf {frame $w_.mctlf}   ; # main control frame
	pack $itk_component(mctlf) -fill y -expand 0 -side left
	pack $itk_component(mimgf) -fill both -expand 1 -side left
    }

    # make frames for Rtd images

    method make_mainf {} {
	itk_component add upf {frame $itk_component(mimgf).upf}
	itk_component add lowf {frame $itk_component(mimgf).lowf}
	itk_component add colf {frame $itk_component(mimgf).colf}
	itk_component add hbar {
	    frame $itk_component(mimgf).hbar \
		-height $itk_option(-barWidth) -borderwidth 2 -relief raised
	}
	pack $itk_component(upf) $itk_component(hbar) $itk_component(lowf) \
	    -fill both -expand 1
	pack $itk_component(hbar) -fill x -expand 0
	pack $itk_component(colf) -fill both -expand 0 -side bottom

	# add 4 Rtd images in frames
	itk_component add img0 {rtdq4Image $itk_component(upf).img0}
	itk_component add img1 {rtdq4Image $itk_component(upf).img1}
	itk_component add img2 {rtdq4Image $itk_component(lowf).img2}
	itk_component add img3 {rtdq4Image $itk_component(lowf).img3}

	# add horizontal bars beween images
	itk_component add uhbar {
	    frame $itk_component(upf).uhbar \
		-width $itk_option(-barWidth) -borderwidth 2 -relief raised
	}
	itk_component add lhbar {
	    frame $itk_component(lowf).lhbar \
		-width $itk_option(-barWidth) -borderwidth 2 -relief raised
	}

	# add a generated image to display the colors in the colormap
        itk_component add colorramp {rtd::RtdImageColorRamp $itk_component(colf).colorramp -height 12}
	
	# remove frames for scrollbars created by RtdImage
	for {set i 0} {$i < 4} {incr i} {
	    destroy [$itk_component(img$i) component vscrollf]
	    destroy [$itk_component(img$i) component hscrollf]
	}

	pack $itk_component(img0) $itk_component(uhbar) $itk_component(img1) \
	    -side left -fill both -expand 1
	pack $itk_component(img2) $itk_component(lhbar) $itk_component(img3) \
	    -side left -fill both -expand 1
	pack $itk_component(colorramp) -fill both -expand 1
	pack $itk_component(uhbar) $itk_component(lhbar) -fill y -expand 0

	# change default option for new image command
	for {set i 0} {$i < 4} {incr i} {
	    [$itk_component(img$i) get_image] config -newimagecmd "$this new_image $i"
	}

	# store image widget names in globals for RtdImageTrans, RtdImageZoomView...
	global ::imageq4
	for {set i 0} {$i < 4} {incr i} {
	    set imageq4($i) $itk_component(img$i)
	}
    }

    # create pan window for all 4 Rtd frames

    method make_panf {} {
	if [popup $w_.pan] { return }
	# create a toplevel widget
	set w [TopLevelWidget $w_.pan -transient 1 -withdraw 1]
	wm resizable $w 0 0

	# add container frames
	itk_component add pupf {frame $w.pupf}
	itk_component add plowf {frame $w.plowf}
	itk_component add pctlf {frame $w.pctlf}
	pack $itk_component(pupf) $itk_component(plowf) -fill both -expand 1
	pack $itk_component(pctlf) -fill both -expand 1 -side bottom
	
	# add 4 pan widgets in frames
	set opt "-width $itk_option(-panWidth) -height $itk_option(-panHeight) -borderwidth 1"
	eval itk_component add panImg0 {"RtdImagePan $itk_component(pupf).panImg0 \
                  -target_image $itk_component(img0) $opt"}
	eval itk_component add panImg1 \
	    {"RtdImagePan $itk_component(pupf).panImg1 -target_image $itk_component(img1) $opt"}
	eval itk_component add panImg2 \
	    {"RtdImagePan $itk_component(plowf).panImg2 -target_image $itk_component(img2) $opt"}
	eval itk_component add panImg3 \
	    {"RtdImagePan $itk_component(plowf).panImg3 -target_image $itk_component(img3) $opt"}

	
	# remove frames for scrollbars created by RtdImage
	for {set i 0} {$i < 4} {incr i} {
	    destroy [[$itk_component(panImg$i) component image] component vscrollf]
	    destroy [[$itk_component(panImg$i) component image] component hscrollf]
	}
	pack $itk_component(panImg0) $itk_component(panImg1) -side left -fill both -expand 1
	pack $itk_component(panImg2) $itk_component(panImg3) -side left -fill both -expand 1

	for {set i 0} {$i < 4} {incr i} {
	    pan_size $i
	}
    }

    # update canvas size e.g. after a new image was loaded

    method pan_size {imgNr} {
	# configure canvas size
	set img panImg$imgNr
	if [info exists itk_component($img)] {
	    set image [[$itk_component($img) component image] get_image]
	    set canvas [[$itk_component($img) component image] get_canvas]
	    lassign [$image scale] scalex scaley
	    if {$scalex < 0} {
		set scalex [expr 1. / -$scalex]
	    }
	    if {$scaley < 0} {
		set scaley [expr 1. / -$scaley]
	    }
	    set nx [expr int([$image width] * $scalex) + 2]
	    set ny [expr int([$image height] * $scaley) + 2]
	    $canvas config -width $nx -height $ny
	}
    }

    # this method is called by the image code whenever a new image is loaded.

    method new_image {imgNr} {
	pan_size $imgNr
    }

    # for demo load and scale images

    method load_images {} {
	for {set i 0} {$i < 4} {incr i} {
	    $itk_component(img$i) config -file ngc1275.gzfits
	    update       ; # wait until image is loaded
	    $itk_component(img$i) scale 2 2
	}
    }

    method attach_camera {} {
	for {set i 0} {$i < 4} {incr i} {
	    $itk_component(img$i) attach_camera $itk_option(-camera)$i
	}
	for {set i 0} {$i < 4} {incr i} {
	    set procId_($i) [exec tRtd -c $itk_option(-camera)$i -t 1000 &]
	}
    }

    method detach_camera {} {
	for {set i 0} {$i < 4} {incr i} {
	    $itk_component(img$i) detach_camera
	    catch {kill procId_($i)}
	}
    }
    
    # set the cut levels when the user types them in and hits return
    
    method set_cut_levels {args} {
	global ::currimg
        set low [$itk_component(low) get] 
        set high [$itk_component(high) get]
        if {[catch {expr $low} msg] || [catch {expr $high} msg]} {
            error_dialog $msg
        } else {
	    set n $currimg
	    if [catch {expr $currimg -1}] {
		set n "1 2 3 4"
	    }
	    foreach el $n {
		[$itk_component(img[expr $el -1]) get_image] cut $low $high
	    }
        }
    }
    
    # popup cut level dialogue window

    method cut_level_dialog {} {
        utilReUseWidget rtdq4Cut $w_.cut \
            -image $itk_component(img0) \
            -shorthelpwin $w_ \
            -transient 1 \
            -command [code $this updateValues]
    }

    # pop up a window to edit the image colors

    method set_colors {} {
        # note that this window must be shared by all instances
        utilReUseWidget rtd::RtdImageColors .colors \
            -image $itk_component(img0) \
            -shorthelpwin $this \
            -cmap_dir $itk_option(-cmap_dir) \
            -cmap_suffix $itk_option(-cmap_suffix) \
            -itt_suffix $itk_option(-itt_suffix) \
            -default_cmap $itk_option(-default_cmap) \
            -default_itt $itk_option(-default_itt)
        .colors update_allocated

        wm transient .colors [winfo toplevel $w_]
    }

    # update the display with the current image values

    method updateValues {} {
	set img0_ [$itk_component(img0) get_image]
	lassign [$img0_ cut] lcut hcut
	for {set i 1} {$i < 4} {incr i} {
	    [$itk_component(img$i) get_image] cut $lcut $hcut
	}
    }

    # open and load a new FITS image file via file name dialog

    public method open {nr {dir "."} {pattern "*.*fit*"}} {
        set file [filename_dialog $dir $pattern $w_]
        if {"$file" != ""} {
            if {[file isfile $file]} {
                if {[catch {$itk_component(img$nr) config -file $file} msg]} {
                    error_dialog $msg
                }
            } else {
                error_dialog "There is no file named '$file'" $w_
            }
        }
    }

    # -- options --

    itk_option define -panWidth panWidth PanWidth  {150} {}
    itk_option define -panHeight panHeight PanHeight  {150} {}
    itk_option define -barWidth barWidth BarWidth  {10} {}

    # camera name: default: $env(RTD_CAMERA), if set, otherwise RTDSIMULATOR
    itk_option define -camera camera Camera {}

    # default cmap file
    itk_option define -default_cmap default_cmap Default_cmap {real}

    # default ITT file
    itk_option define -default_itt default_itt Default_itt {ramp}

    # suffix for colormap files
    itk_option define -cmap_suffix cmap_suffix Cmap_suffix {lasc}

    # suffix for ITT files
    itk_option define -itt_suffix itt_suffix Itt_suffix {iasc}

    # directory for colormap and ITT files
    itk_option define -cmap_dir cmap_dir Cmap_dir {} {}
    
    # fonts used
    itk_option define -labelfont labelFont LabelFont -Adobe-helvetica-bold-r-normal--12*
    itk_option define -valuefont valueFont ValueFont -Adobe-helvetica-medium-r-normal--12*
    itk_option define -wcsfont wcsFont WcsFont -*-symbol-*-*-*-*-14-*-*-*-*-*-*-*

    # set the width for  displaying labels and values
    itk_option define -labelwidth labelWidth LabelWidth 5
    itk_option define -valuewidth valueWidth ValueWidth 10

    # -- protected vars -- 

    # widget name of magnification menu
    protected variable magwin_

    # process Id's for tRtd
    protected variable procId_
}
