#                E L L E D I T F R A M E . T C L
# BRL-CAD
#
# Copyright (c) 2002-2023 United States Government as represented by
# the U.S. Army Research Laboratory.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# version 2.1 as published by the Free Software Foundation.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this file; see the file named COPYING for more
# information.
#
###
#
#    The class for editing ells within Archer.
#

::itcl::class EllEditFrame {
    inherit GeometryEditFrame

    constructor {args} {}
    destructor {}

    public {
	# Override what's in GeometryEditFrame
	method initGeometry {gdata}
	method updateGeometry {}
	method checkpointGeometry {}
	method revertGeometry {}
	method createGeometry {obj}
	method p {obj args}
    }

    protected {
	common setA 1
	common setB 2
	common setC 3
	common setABC 4

	variable mVx ""
	variable mVy ""
	variable mVz ""
	variable mAx ""
	variable mAy ""
	variable mAz ""
	variable mBx ""
	variable mBy ""
	variable mBz ""
	variable mCx ""
	variable mCy ""
	variable mCz ""

	# Checkpoint values
	variable checkpointed_name ""
	variable cmVx ""
	variable cmVy ""
	variable cmVz ""
	variable cmAx ""
	variable cmAy ""
	variable cmAz ""
	variable cmBx ""
	variable cmBy ""
	variable cmBz ""
	variable cmCx ""
	variable cmCy ""
	variable cmCz ""


	variable mCurrentGridRow 0

	# Methods used by the constructor
	# override methods in GeometryEditFrame
	method buildUpperPanel
	method buildLowerPanel

	# Override what's in GeometryEditFrame
	method updateGeometryIfMod {}
	method initEditState {}
    }

    private {}
}


# ------------------------------------------------------------
#                      CONSTRUCTOR
# ------------------------------------------------------------

::itcl::body EllEditFrame::constructor {args} {
    eval itk_initialize $args
}

# ------------------------------------------------------------
#                        OPTIONS
# ------------------------------------------------------------


# ------------------------------------------------------------
#                      PUBLIC METHODS
# ------------------------------------------------------------

## - initGeometry
#
# Initialize the variables containing the object's specification.
#
::itcl::body EllEditFrame::initGeometry {gdata} {
    set _V [bu_get_value_by_keyword V $gdata]
    set mVx [lindex $_V 0]
    set mVy [lindex $_V 1]
    set mVz [lindex $_V 2]
    set _A [bu_get_value_by_keyword A $gdata]
    set mAx [lindex $_A 0]
    set mAy [lindex $_A 1]
    set mAz [lindex $_A 2]
    set _B [bu_get_value_by_keyword B $gdata]
    set mBx [lindex $_B 0]
    set mBy [lindex $_B 1]
    set mBz [lindex $_B 2]
    set _C [bu_get_value_by_keyword C $gdata]
    set mCx [lindex $_C 0]
    set mCy [lindex $_C 1]
    set mCz [lindex $_C 2]

    GeometryEditFrame::initGeometry $gdata
    set curr_name $itk_option(-geometryObject)
    if {$cmVx == "" || "$checkpointed_name" != "$curr_name"} {checkpointGeometry}

}

::itcl::body EllEditFrame::updateGeometry {} {
    if {$itk_option(-mged) == "" ||
	$itk_option(-geometryObject) == ""} {
	return
    }

    $itk_option(-mged) adjust $itk_option(-geometryObject) \
	V [list $mVx $mVy $mVz] \
	A [list $mAx $mAy $mAz] \
	B [list $mBx $mBy $mBz] \
	C [list $mCx $mCy $mCz]

    GeometryEditFrame::updateGeometry
}

::itcl::body EllEditFrame::checkpointGeometry {} {
    set checkpointed_name $itk_option(-geometryObject)
    set cmVx $mVx
    set cmVy $mVy
    set cmVz $mVz
    set cmAx $mAx
    set cmAy $mAy
    set cmAz $mAz
    set cmBx $mBx
    set cmBy $mBy
    set cmBz $mBz
    set cmCx $mCx
    set cmCy $mCy
    set cmCz $mCz
}

::itcl::body EllEditFrame::revertGeometry {} {
    set mVx $cmVx
    set mVy $cmVy
    set mVz $cmVz
    set mAx $cmAx
    set mAy $cmAy
    set mAz $cmAz
    set mBx $cmBx
    set mBy $cmBy
    set mBz $cmBz
    set mCx $cmCx
    set mCy $cmCy
    set mCz $cmCz

    updateGeometry
}


::itcl::body EllEditFrame::createGeometry {obj} {
    if {![GeometryEditFrame::createGeometry $obj]} {
	return
    }

    $itk_option(-mged) put $obj ell \
	V [list $mCenterX $mCenterY $mCenterZ] \
	A [list $mDelta 0 0] \
	B [list 0 $mDelta 0] \
	C [list 0 0 $mDelta]
}

::itcl::body EllEditFrame::p {obj args} {
    if {[llength $args] != 1 || ![string is double $args]} {
	return "Usage: p sf"
    }

    switch -- $mEditMode \
	$setA {
	    $::ArcherCore::application p_pscale $obj a $args
	} \
	$setB {
	    $::ArcherCore::application p_pscale $obj b $args
	} \
	$setC {
	    $::ArcherCore::application p_pscale $obj c $args
	} \
	$setABC {
	    $::ArcherCore::application p_pscale $obj abc $args
	}

    return ""
}


# ------------------------------------------------------------
#                      PROTECTED METHODS
# ------------------------------------------------------------

::itcl::body EllEditFrame::buildUpperPanel {} {
    set parent [$this childsite]
    itk_component add ellType {
	::ttk::label $parent.elltype \
	    -text "Ellipsoid:" \
	    -anchor e
    } {}
    itk_component add ellName {
	::ttk::label $parent.ellname \
	    -textvariable [::itcl::scope itk_option(-geometryObject)] \
	    -anchor w
    } {}

    # Create header labels
    itk_component add ellXL {
	::ttk::label $parent.ellXL \
	    -text "X"
    } {}
    itk_component add ellYL {
	::ttk::label $parent.ellYL \
	    -text "Y"
    } {}
    itk_component add ellZL {
	::ttk::label $parent.ellZL \
	    -text "Z"
    } {}

    # create widgets for vertices and vectors
    itk_component add ellVL {
	::ttk::label $parent.ellVL \
	    -text "V:" \
	    -anchor e
    } {}
    itk_component add ellVxE {
	::ttk::entry $parent.ellVxE \
	    -textvariable [::itcl::scope mVx] \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellVyE {
	::ttk::entry $parent.ellVyE \
	    -textvariable [::itcl::scope mVy] \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellVzE {
	::ttk::entry $parent.ellVzE \
	    -textvariable [::itcl::scope mVz] \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellVUnitsL {
	::ttk::label $parent.ellVUnitsL \
	    -textvariable [::itcl::scope itk_option(-units)] \
	    -anchor e
    } {}
    itk_component add ellAL {
	::ttk::label $parent.ellAL \
	    -state disabled \
	    -text "A:" \
	    -anchor e
    } {}
    itk_component add ellAxE {
	::ttk::entry $parent.ellAxE \
	    -textvariable [::itcl::scope mAx] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellAyE {
	::ttk::entry $parent.ellAyE \
	    -textvariable [::itcl::scope mAy] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellAzE {
	::ttk::entry $parent.ellAzE \
	    -textvariable [::itcl::scope mAz] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellAUnitsL {
	::ttk::label $parent.ellAUnitsL \
	    -textvariable [::itcl::scope itk_option(-units)] \
	    -anchor e
    } {}
    itk_component add ellBL {
	::ttk::label $parent.ellBL \
	    -state disabled \
	    -text "B:" \
	    -anchor e
    } {}
    itk_component add ellBxE {
	::ttk::entry $parent.ellBxE \
	    -textvariable [::itcl::scope mBx] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellByE {
	::ttk::entry $parent.ellByE \
	    -textvariable [::itcl::scope mBy] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellBzE {
	::ttk::entry $parent.ellBzE \
	    -textvariable [::itcl::scope mBz] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellBUnitsL {
	::ttk::label $parent.ellBUnitsL \
	    -textvariable [::itcl::scope itk_option(-units)] \
	    -anchor e
    } {}
    itk_component add ellCL {
	::ttk::label $parent.ellCL \
	    -state disabled \
	    -text "C:" \
	    -anchor e
    } {}
    itk_component add ellCxE {
	::ttk::entry $parent.ellCxE \
	    -textvariable [::itcl::scope mCx] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellCyE {
	::ttk::entry $parent.ellCyE \
	    -textvariable [::itcl::scope mCy] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellCzE {
	::ttk::entry $parent.ellCzE \
	    -textvariable [::itcl::scope mCz] \
	    -state disabled \
	    -validate key \
	    -validatecommand {::cadwidgets::Ged::validateDouble %P}
    } {}
    itk_component add ellCUnitsL {
	::ttk::label $parent.ellCUnitsL \
	    -textvariable [::itcl::scope itk_option(-units)] \
	    -anchor e
    } {}

    itk_component add checkpointButton {
	::ttk::button $parent.checkpointButton \
	-text {CheckPoint} \
	-command "[::itcl::code $this checkpointGeometry]"
    } {}

    itk_component add revertButton {
	::ttk::button $parent.revertButton \
	-text {Revert} \
	-command "[::itcl::code $this revertGeometry]"
    } {}


    grid $itk_component(ellType) \
	-row $mCurrentGridRow \
	-column 0 \
	-sticky nsew
    grid $itk_component(ellName) \
	-row $mCurrentGridRow \
	-column 1 \
	-columnspan 3 \
	-sticky nsew
    incr mCurrentGridRow
    grid x $itk_component(ellXL) \
	$itk_component(ellYL) \
	$itk_component(ellZL)
    incr mCurrentGridRow
    grid $itk_component(ellVL) \
	$itk_component(ellVxE) \
	$itk_component(ellVyE) \
	$itk_component(ellVzE) \
	$itk_component(ellVUnitsL) \
	-row $mCurrentGridRow \
	-sticky nsew
    incr mCurrentGridRow
    grid $itk_component(ellAL) \
	$itk_component(ellAxE) \
	$itk_component(ellAyE) \
	$itk_component(ellAzE) \
	$itk_component(ellAUnitsL) \
	-row $mCurrentGridRow \
	-sticky nsew
    incr mCurrentGridRow
    grid $itk_component(ellBL) \
	$itk_component(ellBxE) \
	$itk_component(ellByE) \
	$itk_component(ellBzE) \
	$itk_component(ellBUnitsL) \
	-row $mCurrentGridRow \
	-sticky nsew
    incr mCurrentGridRow
    grid $itk_component(ellCL) \
	$itk_component(ellCxE) \
	$itk_component(ellCyE) \
	$itk_component(ellCzE) \
	$itk_component(ellCUnitsL) \
	-row $mCurrentGridRow \
	-sticky nsew
    incr mCurrentGridRow
    set col 0
    grid $itk_component(checkpointButton) \
	-row $mCurrentGridRow \
	-column $col \
	-columnspan 2 \
	-sticky nsew
    incr col
    incr col
    grid $itk_component(revertButton) \
	-row $mCurrentGridRow \
	-column $col \
	-columnspan 2 \
	-sticky nsew

    grid columnconfigure $parent 1 -weight 1
    grid columnconfigure $parent 2 -weight 1
    grid columnconfigure $parent 3 -weight 1
    pack $parent -expand yes -fill x -anchor n

    # Set up bindings
    bind $itk_component(ellVxE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellVyE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellVzE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellAxE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellAyE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellAzE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellBxE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellByE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellBzE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellCxE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellCyE) <Return> [::itcl::code $this updateGeometryIfMod]
    bind $itk_component(ellCzE) <Return> [::itcl::code $this updateGeometryIfMod]
}

::itcl::body EllEditFrame::buildLowerPanel {} {
    set parent [$this childsite lower]
    set row 0
    foreach attribute {A B C ABC} {
	itk_component add set$attribute {
	    ::ttk::radiobutton $parent.set_$attribute \
		-variable [::itcl::scope mEditMode] \
		-value [subst $[subst set$attribute]] \
		-text "Set $attribute" \
		-command [::itcl::code $this initEditState]
	} {}

	grid $itk_component(set$attribute) -row $row -column 0 -sticky nsew
	incr row
    }
}

::itcl::body EllEditFrame::updateGeometryIfMod {} {
    if {$itk_option(-mged) == "" ||
	$itk_option(-geometryObject) == ""} {
	return
    }

    set gdata [$itk_option(-mged) get $itk_option(-geometryObject)]
    set gdata [lrange $gdata 1 end]

    set _V [bu_get_value_by_keyword V $gdata]
    set _Vx [lindex $_V 0]
    set _Vy [lindex $_V 1]
    set _Vz [lindex $_V 2]
    set _A [bu_get_value_by_keyword A $gdata]
    set _Ax [lindex $_A 0]
    set _Ay [lindex $_A 1]
    set _Az [lindex $_A 2]
    set _B [bu_get_value_by_keyword B $gdata]
    set _Bx [lindex $_B 0]
    set _By [lindex $_B 1]
    set _Bz [lindex $_B 2]
    set _C [bu_get_value_by_keyword C $gdata]
    set _Cx [lindex $_C 0]
    set _Cy [lindex $_C 1]
    set _Cz [lindex $_C 2]

    if {$mVx == ""  ||
	$mVx == "-" ||
	$mVy == ""  ||
	$mVy == "-" ||
	$mVz == ""  ||
	$mVz == "-" ||
	$mAx == ""  ||
	$mAx == "-" ||
	$mAy == ""  ||
	$mAy == "-" ||
	$mAz == ""  ||
	$mAz == "-" ||
	$mBx == ""  ||
	$mBx == "-" ||
	$mBy == ""  ||
	$mBy == "-" ||
	$mBz == ""  ||
	$mBz == "-" ||
	$mCx == ""  ||
	$mCx == "-" ||
	$mCy == ""  ||
	$mCy == "-" ||
	$mCz == ""  ||
	$mCz == "-"} {
	# Not valid
	return
    }

    if {$_Vx != $mVx ||
	$_Vy != $mVy ||
	$_Vz != $mVz ||
	$_Ax != $mAx ||
	$_Ay != $mAy ||
	$_Az != $mAz ||
	$_Bx != $mBx ||
	$_By != $mBy ||
	$_Bz != $mBz ||
	$_Cx != $mCx ||
	$_Cy != $mCy ||
	$_Cz != $mCz} {
	updateGeometry
    }
}

::itcl::body EllEditFrame::initEditState {} {
    set mEditCommand pscale
    set mEditPCommand [::itcl::code $this p]
    configure -valueUnits "mm"

    switch -- $mEditMode \
	$setA {
	    set mEditParam1 a
	    set mEditClass $EDIT_CLASS_SCALE
	} \
	$setB {
	    set mEditParam1 b
	    set mEditClass $EDIT_CLASS_SCALE
	} \
	$setC {
	    set mEditParam1 c
	    set mEditClass $EDIT_CLASS_SCALE
	} \
	$setABC {
	    set mEditParam1 abc
	    set mEditClass $EDIT_CLASS_SCALE
	} \
	default {
	    set mEditCommand ""
	    set mEditPCommand ""
	    set mEditParam1 ""
	}

    GeometryEditFrame::initEditState
}


# Local Variables:
# mode: Tcl
# tab-width: 8
# c-basic-offset: 4
# tcl-indent-level: 4
# indent-tabs-mode: t
# End:
# ex: shiftwidth=4 tabstop=8
