proc MQDrawGraphCurrent { w } {
    upvar #0 [winfo name $w] data

    if { [.central.s info Mesh] != $data(infomesh) } {
	MeshQuality $w
    } else {
	MQDrawGraph $w $data(frame) $data(etype)
    }
}


proc MQDrawGraph { w frame etype } {
    global MeshQualityPriv
    upvar #0 [winfo name $w] data
    set data(frame) $frame
    if { ![info exists data(etype)] } {
	set data(etype) unset_etype
    } 
    if { $data(etype) != $etype } {
	set data(etype) $etype
	MQChangeQualityCriteria $w
    }
    
    set c $frame.c
    #$c delete curve
    #$c delete axestext
    #$c delete lineselect
    $c delete all

    set iniang [$frame.f1.e1 get]
    set endang [$frame.f1.e2 get]
    set numdivisions [$frame.f2.e1 get]

    #update
    #set xmax [$c cget -width]
    set xmax [winfo width $c]
#    if { $xmax == 1 } {
#        set xmax [winfo reqwidth $c]
#    }
    set ymax [winfo height $c]

    


    if { [string match Minimum*angle $MeshQualityPriv(qualitytype)] } {
	set listb [.central.s info MeshQuality MinAngle $etype $iniang $endang \
		$numdivisions]
    } elseif { [string match Maximum*angle $MeshQualityPriv(qualitytype)] } {
	set listb [.central.s info MeshQuality MaxAngle $etype $iniang $endang \
		$numdivisions]
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Element vol"] } {
	set listb [.central.s info MeshQuality ElemSize $etype $iniang $endang \
		$numdivisions]
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Minimum edge"] } {
	set listb [.central.s info MeshQuality ElemMinEdge $etype $iniang $endang \
		$numdivisions]
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Maximum edge"] } {
	set listb [.central.s info MeshQuality ElemMaxEdge $etype $iniang $endang \
		$numdivisions]
    } elseif {[string equal $MeshQualityPriv(qualitytype) "Shape quality"] } {
	set listb [.central.s info MeshQuality ElemShapeQuality $etype $iniang $endang \
		$numdivisions]
    }
    set list ""
    set total 0
    for {set i 0 } { $i < $numdivisions } { incr i } {
	if { [ string match $MeshQualityPriv(distributiontype) "Accumulated"]} {
	    incr total [lindex $listb $i]
	    lappend list $total
	} else {
	    #  [ string match $MeshQualityPriv(distributiontype) "Normal"]
	    lappend list [lindex $listb $i]
	}
    } 

    set iniangout [lindex $listb $numdivisions]
    if { [expr abs($iniangout-$iniang)>0.00001] } { 
      set iniang [format "%3.3g" $iniangout]
      $frame.f1.e1 delete 0 end
      $frame.f1.e1 ins end $iniang 
    }

    set endangout [lindex $listb [expr $numdivisions+1]]
    if { [expr abs($endangout-$endang)>0.00001] } { 
      set endang [format "%3.3g" $endangout]
      $frame.f1.e2 delete 0 end
      $frame.f1.e2 ins end $endang 
    }

    set ynummax 0
    for {set i 0 } { $i < $numdivisions } { incr i } {
	set yval [lindex $list $i]
	if { $yval > $ynummax } {
	    set ynummax $yval
	}
	if { $i == 0 || $yval < $ynummin } {
	    set ynummin $yval
	}
    }
    if { $ynummax == $ynummin } { incr ynummax }
    set textwidth [font measure NormalFont $ynummax]
    set xm [expr $textwidth+15]
    set textheight [font metrics NormalFont -linespace]
    set ym [expr int($textheight+15)]
    set MeshQualityPriv(xmargin) $xm
    set MeshQualityPriv(ymargin) $ym
    $c create line $xm $ym $xm [expr $ymax-$ym] [expr $xmax-$xm] \
	    [expr $ymax-$ym]  -tags axestext
    set inumtics 8
    for {set i 0 } { $i < $inumtics } { incr i } {
	set angle [format "%3.3g" \
		[expr $iniang+$i/double($inumtics-1)*($endang-$iniang)]]
	set xval [expr $xm+$i/double($inumtics-1)*($xmax-2*$xm)]
	$c create line $xval [expr $ymax-$ym+2] $xval [expr $ymax-$ym] \
		-tags axestext
	$c create text $xval [expr $ymax-$ym+2] -anchor n -justify center \
		-text $angle -font NormalFont -tags axestext

	set numelms [expr int($ynummin+$i/double($inumtics-1)*($ynummax-$ynummin))]
	set yval [expr $ymax-$ym-$i/double($inumtics-1)*($ymax-2*$ym)]
	$c create line [expr $xm-2] $yval $xm $yval -tags axestext
	$c create text [expr $xm-3] $yval -anchor e -justify right \
		-text $numelms -font NormalFont -tags axestext
    }


    set xfact [expr ($xmax-2.0*$xm)/double($numdivisions)]
    set yfact [expr ($ymax-2.0*$ym)/double($ynummax-$ynummin)]

    set lastyval [expr $ymax-$ym]
    for {set i 0 } { $i < $numdivisions } { incr i } {
	set yval [expr $ymax-$ym-([lindex $list $i]-$ynummin)*$yfact]
	#$c create line [expr $i*$xfact+$xm] $lastyval \
	#        [expr $i*$xfact+$xm] $yval\
	#        [expr ($i+1)*$xfact+$xm] $yval -tags curve -fill blue
	
	#$c create line [expr $i*$xfact+$xm] $lastyval \
	#        [expr ($i+1)*$xfact+$xm] $yval -tags curve -fill blue
	$c create rectangle [expr $i*$xfact+$xm] $lastyval \
		[expr ($i+1)*$xfact+$xm] $yval -tags curve -outline steelblue
	#set lastyval $yval
    }

    $c create text 2 2 -anchor nw -justify left \
	    -text [_ "NumElems"] -font BoldFont -tags axestext
    set textwidth [font measure BoldFont 0.0]
    $c create text [expr $xmax-$textwidth-1.6*$xm] [expr $ymax-1.6*$ym] \
	    -anchor nw -justify left \
	    -text $data(TextX) -font BoldFont -tags axestext

#     toplevel $w.t
#     pack [text $w.t.t] -fill both -expand yes
#     $w.t.t ins end $list



}

proc MQChangeQualityCriteria { w } {
    global MeshQualityPriv
    upvar #0 [winfo name $w] data
    set frame $data(frame)
    if { [string equal $MeshQualityPriv(qualitytype) "Element vol"] } {    
      set data(TextX) [_ "Volume"]
      set data(Units) ""
      $frame.f1.l1 configure -text [_ "%s: From" $data(TextX)]
      $frame.f1.e1 delete 0 end
      $frame.f1.e1 ins end 0.0
      $frame.f1.l2 configure -text [_ "%s To" $data(Units)]
      $frame.f1.e2 delete 0 end
      $frame.f1.e2 ins end 0.0
      $frame.f1.l3 configure -text "$data(Units)"
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Minimum edge"] } {    
      set data(TextX) [_ "Min Size"]
      set data(Units) ""
      $frame.f1.l1 configure -text [_ "%s: From" $data(TextX)]
      $frame.f1.e1 delete 0 end
      $frame.f1.e1 ins end 0.0
      $frame.f1.l2 configure -text [_ "%s To" $data(Units)]
      $frame.f1.e2 delete 0 end
      $frame.f1.e2 ins end 0.0
      $frame.f1.l3 configure -text "$data(Units)"
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Maximum edge"] } {    
      set data(TextX) [_ "Max Size"]
      set data(Units) ""
      $frame.f1.l1 configure -text [_ "%s: From" $data(TextX)]
      $frame.f1.e1 delete 0 end
      $frame.f1.e1 ins end 0.0
      $frame.f1.l2 configure -text [_ "%s To" $data(Units)]
      $frame.f1.e2 delete 0 end
      $frame.f1.e2 ins end 0.0
      $frame.f1.l3 configure -text "$data(Units)"
   } elseif { [string equal $MeshQualityPriv(qualitytype) "Shape quality"] } {    
      set data(TextX) [_ "Quality"]
      set data(Units) ""
      $frame.f1.l1 configure -text [_ "%s: From" $data(TextX)]
      $frame.f1.e1 delete 0 end
      $frame.f1.e1 ins end 0.0
      $frame.f1.l2 configure -text [_ "%s To" $data(Units)]
      $frame.f1.e2 delete 0 end
      $frame.f1.e2 ins end 0.0
      $frame.f1.l3 configure -text "$data(Units)"
    } else {
      set data(TextX) [_ "Angle"]
      set data(Units) [_ "Degrees"]
      $frame.f1.l1 configure -text [_ "%s: From" $data(TextX)]
      $frame.f1.e1 delete 0 end
      $frame.f1.e1 ins end 0.0
      $frame.f1.l2 configure -text [_ "%s To" $data(Units)]
      $frame.f1.e2 delete 0 end
#      $frame.f1.e2 ins end 180.0
# set from==to for automatic mín and máx limits
      $frame.f1.e2 ins end 0.0
      $frame.f1.l3 configure -text "$data(Units)"
    }
    MQDrawGraph $w $data(frame) $data(etype)
}

proc FillMenuWithLayers { m } {
    $m del 0 end
    set layerslist [.central.s info layers]
    if { $layerslist == "" } {
	$m add command -label [_ "There are no layers"] \
      -command {
	  tk_dialogRAM .gid.tempwin [_ "Error window"] \
	      [_ "One layer must be createt before sending to it the filtered elements"] error 0 [_ "OK"]
      }
    } else {
      foreach l $layerslist {
	    $m add command -label $l -command [list SendSelectionToLayer $l]
      }
    }        
}

proc MQCreate { w fr etype } {
    global MeshQualityPriv
    upvar #0 [winfo name $w] data

    global GidPriv
    set GidPriv(selection) ""

    canvas $fr.c -bg white -relief ridge -bd 2
    grid $fr.c -sticky nsew -row 1 -column 1
    GidHelp "$fr.c"  [_ "Double click to see the elements filtered with a x-value."]

#    trace vdelete MeshQualityPriv(qualitytype) w "MQDrawGraphCurrent $w ;#"
    trace vdelete MeshQualityPriv(qualitytype) w "MQChangeQualityCriteria $w ;#"
    trace vdelete MeshQualityPriv(distributiontype) w "MQDrawGraphCurrent $w ;#"
    set MeshQualityPriv(qualitytype) "Minimum angle"  
    set data(TextX) [_ "Angle"]

    frame $fr.f1
    label $fr.f1.l1 -text [_ "Angle: From"]
    entry $fr.f1.e1 -relief sunken -width 5
    $fr.f1.e1 ins end 0.0
    label $fr.f1.l2 -text [_ "Degrees. To"]
    entry $fr.f1.e2 -relief sunken -width 5
    #$fr.f1.e2 ins end 180.0
    $fr.f1.e2 ins end 0.0
    label $fr.f1.l3 -text [_ "Degrees"]
    grid $fr.f1.l1 -row 1 -column 1
    grid $fr.f1.e1 -sticky ew -row 1 -column 2
    grid $fr.f1.l2  -row 1 -column 3
    grid $fr.f1.e2 -sticky ew -row 1 -column 4
    grid $fr.f1.l3 -row 1 -column 5
    grid columnconf $fr.f1 2 -weight 1
    grid columnconf $fr.f1 4 -weight 1

    frame $fr.f2
    label $fr.f2.l1 -text [_ "Num divisions:"]
    entry $fr.f2.e1 -relief sunken -width 5
    $fr.f2.e1 ins end 100

    label $fr.f2.l2 -text [_ "Distribution:"]
    tk_optionMenuRAM $fr.f2.m MeshQualityPriv(distributiontype) \
	    [list [_ "Accumulated"] [_  "Normal"]] \
	    {Accumulated Normal}
    set MeshQualityPriv(distributiontype) "Accumulated"
    grid $fr.f2.l1 -row 1 -column 1
    grid $fr.f2.e1 -sticky ew -row 1 -column 2
    grid $fr.f2.l2 -sticky e -row 1 -column 3
    grid $fr.f2.m -sticky w -row 1 -column 4
    grid columnconf $fr.f2 2 -weight 1
    grid columnconf $fr.f2 4 -weight 1

    frame $fr.type
    label $fr.type.l -anchor w -text [_ "Quality criteria:"]

    switch $etype {
	Tetrahedra -
	Hexahedra -
	Prisma {
	    tk_optionMenuRAM $fr.type.m MeshQualityPriv(qualitytype) \
		    [list [_ "Minimum dihedral angle"] [_ "Maximum dihedral angle"] \
		    [_ "Element vol"] [_ "Minimum edge"] [_ "Maximum edge"] [_ "Shape quality"]] \
		    { "Minimum dihedral angle"  "Maximum dihedral angle"  "Element vol" \
		    "Minimum edge" "Maximum edge" "Shape quality"}
	    set MeshQualityPriv(qualitytype) "Minimum dihedral angle"
	}
	default {
	    tk_optionMenuRAM $fr.type.m MeshQualityPriv(qualitytype) \
		    [list [_ "Minimum angle"] [_ "Maximum angle"] [_ "Element vol"] \
		    [_ "Minimum edge"] [_ "Maximum edge"] [_ "Shape quality"]] \
		    { "Minimum angle" "Maximum angle" "Element vol" "Minimum edge" \
		     "Maximum edge" "Shape quality"}
	    set  MeshQualityPriv(qualitytype) "Minimum angle"
	}
    }

    menubutton  $fr.sendlaytouse  -text [_ "Send To Layer"] -und 0 -relief raised \
	    -menu $fr.sendlaytouse.menu -bd 1  -highlightthickness 1
    menu $fr.sendlaytouse.menu -bd 1 -activeborderwidth 1
    
    FillMenuWithLayers $fr.sendlaytouse.menu

    grid $fr.type.l -row 1 -column 1
    grid $fr.type.m -row 1 -column 2

    grid $fr.f1 -sticky ew -row 2 -column 1
    grid $fr.f2 -sticky ew -row 3 -column 1
    grid $fr.type -sticky w  -row 4 -column 1
    grid $fr.sendlaytouse -sticky e  -row 4 -column 1
    grid columnconf $fr 1 -weight 1
    grid rowconf $fr 1 -weight 1

    bind $fr.f1.e1 <Return> "MQDrawGraphCurrent $w"
    bind $fr.f1.e2 <Return> "MQDrawGraphCurrent $w"
    bind $fr.f2.e1 <Return> "MQDrawGraphCurrent $w"
#    trace var MeshQualityPriv(qualitytype) w "MQDrawGraphCurrent $w ;#"
    trace var MeshQualityPriv(qualitytype) w "MQChangeQualityCriteria $w ;#"
    trace var MeshQualityPriv(distributiontype) w "MQDrawGraphCurrent $w ;#"
    bind $fr.c <Double-Button-1> "SelectElements $w $fr %x %y"
    bind $fr.c <Configure> "MQDrawGraph $w $fr $etype"     
    bind $fr.sendlaytouse <Button-1> "FillMenuWithLayers $fr.sendlaytouse.menu"       
}

proc SendSelectionToLayer { layername } {
    global GidPriv
    #para que se actualice GidPriv(Selection) al valor definitivo
    .central.s process escape 
    if { $GidPriv(selection) == "" } {
	tk_dialogRAM .gid.tempwin [_ "Error window"] \
	    [_ "Double-click first on the graph\n to select filtered elements"] \
	    error 0 [_ "OK"]
    } else {	
	set len [ string length $GidPriv(selection) ]
	if { $len >= 2} {
	    set sel [ string range $GidPriv(selection) 1 [ expr $len - 2]]
	    eval GiD_Process escape escape escape View Layers Entities [list $layername] $sel escape
	}         
    }
}

proc MeshQuality { { w .meshq } } {
    set mesh [.central.s info Mesh]
    if { [lindex $mesh 0] == 0 } {
	catch { destroy $w }
	tk_dialogRAM .gid.tempwin [_ "Error window"] [_ "There are no meshes"] \
	    error 0 [_ "OK"]
	return
    }
    set meshtypes [lrange $mesh 1 end]
    regsub {Linear} $meshtypes "" meshtypes
    regsub {Prisma} $meshtypes "" meshtypes
    if { $meshtypes == "" } {
	catch { destroy $w }
	tk_dialogRAM .gid.tempwin [_ "Error window"] \
	    [_ "There are no meshes of triangles, quadrilaterals, tetrahedrals or hexahedrals"] \
	    error 0 [_ "OK"]
	return
    }


    InitWindow $w [_ "Mesh quality"] MeshQualityWindowGeom ""
    wm withdraw $w

    set def_back [$w cget -background]
    frame $w.buts -bg [CCColorActivo $def_back]
    #button $w.buts.ok -text Actualize -command "MQDrawGraphCurrent $w"
    #button $w.buts.cn -text Close -command "destroy $w"
    #pack $w.buts.ok $w.buts.cn -side left -padx 5 -ipadx 5 -pady 5 
    button $w.buts.cn -text [_ "Close"] \
	    -command "destroy $w ; .central.s process {escape escape}"
    grid $w.buts.cn -row 1 -column 1 -padx 5 -pady 6 

    frame $w.f
    grid $w.buts -row 1 -column 0 -sticky ews -columnspan 7
    grid $w.f -row 0 -column 0 -sticky nsew
    grid rowconfigure $w.f 0 -weight 1
    grid columnconfigure $w.f 0 -weight 1
    grid rowconfigure $w 0 -weight 1
    grid columnconfigure $w 0 -weight 1
    
    set func "optionbar $w.f.c"
    foreach qq $meshtypes {
	set pref [string tolower $qq]
	set holder [frame $w.f.$pref]
	set pref [string toupper \
		[string range $pref 0 0]][string range $pref 1 end]
	lappend func [list [_ "%s" $pref ] $holder [list MQDrawGraph $w $holder $pref]]
	 MQCreate $w $holder $pref
    }
    eval $func
    pack $w.f.c -fill both -expand yes
    update idletasks
    wm deicon $w

    upvar #0 [winfo name $w] data
    set data(infomesh) $mesh
    bind $w <Escape> "tkButtonInvoke $w.buts.cn"
}

proc SelectElements { w frame x y } {
    upvar #0 [winfo name $w] data
    global MeshQualityPriv
    

    set c $frame.c   
    $c delete lineselect
    set iniang [$frame.f1.e1 get]
    set endang [$frame.f1.e2 get]
    #set xmax [$c cget -width] 
    #set ymax [$c cget -height] 
    set xmax [winfo width $c]
    #if { $xmax == 1 } {
#        set xmax [winfo reqwidth $c]
#    }
    set ymax [winfo height $c]
#    if { $ymax == 1 } {
#        set ymax [winfo reqheight $c]
#    }

    set xm $MeshQualityPriv(xmargin) 
    set ym $MeshQualityPriv(ymargin)
    set value [expr ($x-$xm)/($xmax-2.0*$xm)*($endang-$iniang)+$iniang]
    if { $value < $iniang } { 
	set value $iniang 
	set x [expr ($value-$iniang)/($endang-$iniang)*($xmax-2.0*$xm)+$xm]
    } elseif { $value > $endang } {
	set value $endang 
	set x [expr ($value-$iniang)/($endang-$iniang)*($xmax-2.0*$xm)+$xm]
    } 
    if { $value < 1e-7 } {
	set value 1e-7
    }
    $c create line $x $ym $x [expr $ymax-$ym] -tags lineselect -fill red
    if { [catch { set whatuse [lindex [.central.s info Project] 4] }] } {
	set whatuse GEOMETRYUSE
    }   
    if { $whatuse != "MESHUSE" } {
	.central.s process escape escape escape escape meshing meshview
    }
    #.central.s process escape escape escape escape view label off
    #.central.s process label select elements
    .central.s process escape escape escape escape view select elements
    if { [string match Minimum*angle $MeshQualityPriv(qualitytype)] } {
	.central.s process filter:badminangle=$value and elementtype=$data(etype)
    } elseif { [string match Maximum*angle $MeshQualityPriv(qualitytype)] } {
	.central.s process filter:badmaxangle=$value and elementtype=$data(etype)
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Element vol"] } {
	.central.s process filter:minvolume=$value and elementtype=$data(etype)
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Minimum edge"] } {
	.central.s process filter:minlength=$value and elementtype=$data(etype)
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Maximum edge"] } {
	.central.s process filter:maxlength=$value and elementtype=$data(etype)
    } elseif { [string equal $MeshQualityPriv(qualitytype) "Shape quality"] } {
	.central.s process filter:minquality=$value and elementtype=$data(etype)
    }
    .central.s process 1:
}
