From ab91ab6feab5c5bd579bdb623f062cf30e793644 Mon Sep 17 00:00:00 2001 From: isz Date: Mon, 6 Oct 2014 16:56:21 +0400 Subject: [PATCH] 0025231: DRAW - make top level menu useful -Meaningful texts are provided instead of commands in File menu (e.g. restore->Load Shape (restore)) -tk_getOpenFile is used in "open file" dialogs -tk_chooseDirectory is used in "change directory" dialog -Added menu "Help" with submenus "System info", "Commands", "About", "User Guide" -Added menu "Samples" with submenu "View samples" -Added menu "Load" with submenus "pload " --- samples/tcl/DataExchangeDemo.tcl | 3 + samples/tcl/ModelingDemo.tcl | 3 + samples/tcl/VisualizationDemo.tcl | 3 + samples/tcl/bottle.tcl | 2 + samples/tcl/cad.tcl | 2 + samples/tcl/cutter.tcl | 2 + samples/tcl/drill.tcl | 2 + samples/tcl/materials.tcl | 3 + samples/tcl/raytrace.tcl | 3 + samples/tcl/spheres.tcl | 3 + samples/tcl/xde.tcl | 3 + src/DrawResources/CURVES.tcl | 1 + src/DrawResources/DrawTK.tcl | 562 +++++++++++++++++++++++------- src/DrawResources/OCC_logo.png | Bin 0 -> 13630 bytes src/DrawResources/SURFACES.tcl | 1 + 15 files changed, 462 insertions(+), 131 deletions(-) create mode 100644 src/DrawResources/OCC_logo.png diff --git a/samples/tcl/DataExchangeDemo.tcl b/samples/tcl/DataExchangeDemo.tcl index 51f5f47095..32a592dcff 100644 --- a/samples/tcl/DataExchangeDemo.tcl +++ b/samples/tcl/DataExchangeDemo.tcl @@ -1,5 +1,8 @@ # Copyright (c) 1999-2014 OPEN CASCADE SAS # +#Category: Demos +#Title: Import and export +# # This file is part of Open CASCADE Technology software library. # # This library is free software; you can redistribute it and / or modify it diff --git a/samples/tcl/ModelingDemo.tcl b/samples/tcl/ModelingDemo.tcl index 32e3d2d88a..53f313bf52 100644 --- a/samples/tcl/ModelingDemo.tcl +++ b/samples/tcl/ModelingDemo.tcl @@ -1,5 +1,8 @@ # Copyright (c) 1999-2014 OPEN CASCADE SAS # +#Category: Demos +#Title: Modeling operations +# # This file is part of Open CASCADE Technology software library. # # This library is free software; you can redistribute it and / or modify it diff --git a/samples/tcl/VisualizationDemo.tcl b/samples/tcl/VisualizationDemo.tcl index b3177d56dc..0d5f4180b2 100644 --- a/samples/tcl/VisualizationDemo.tcl +++ b/samples/tcl/VisualizationDemo.tcl @@ -1,5 +1,8 @@ # Copyright (c) 1999-2014 OPEN CASCADE SAS # +#Category: Demos +#Title: Displaying 3d viewer +# # This file is part of Open CASCADE Technology software library. # # This library is free software; you can redistribute it and / or modify it diff --git a/samples/tcl/bottle.tcl b/samples/tcl/bottle.tcl index 86cf9e3f10..b11ca2ce56 100755 --- a/samples/tcl/bottle.tcl +++ b/samples/tcl/bottle.tcl @@ -1,4 +1,6 @@ # Script reproducing creation of bottle model as described in OCCT Tutorial +#Category: Modeling +#Title: OCCT Tutorial bottle shape pload MODELING VISUALIZATION diff --git a/samples/tcl/cad.tcl b/samples/tcl/cad.tcl index d6a5931b84..076906a97d 100644 --- a/samples/tcl/cad.tcl +++ b/samples/tcl/cad.tcl @@ -1,5 +1,7 @@ # This script creates a model described at # http://www.caddd.org/2010/04/opencascade-challenge.html +#Category: Modeling +#Title: CAD shape pload MODELING VISUALIZATION diff --git a/samples/tcl/cutter.tcl b/samples/tcl/cutter.tcl index 953726ee8b..40e51aef06 100644 --- a/samples/tcl/cutter.tcl +++ b/samples/tcl/cutter.tcl @@ -1,4 +1,6 @@ # Sample: creation of milling cutter +#Category: Modeling +#Title: Milling cutter pload MODELING VISUALIZATION diff --git a/samples/tcl/drill.tcl b/samples/tcl/drill.tcl index 03fe96d590..baef045a61 100644 --- a/samples/tcl/drill.tcl +++ b/samples/tcl/drill.tcl @@ -1,4 +1,6 @@ # Sample: creation of simple twist drill bit +#Category: Modeling +#Title: Drill pload MODELING VISUALIZATION diff --git a/samples/tcl/materials.tcl b/samples/tcl/materials.tcl index f1b81ceae8..c43f4dc55b 100644 --- a/samples/tcl/materials.tcl +++ b/samples/tcl/materials.tcl @@ -1,5 +1,8 @@ # Script displays properties of different materials available in OCCT +#Category: Visualization +#Title: Material properties in viewer + set THE_MATERIALS {brass bronze copper gold jade neon_phc pewter obsidian plaster plastic satin silver steel stone chrome aluminium water glass diamond charcoal} set THE_COLORS {default red green blue1} set THE_ROW_DIST 35 diff --git a/samples/tcl/raytrace.tcl b/samples/tcl/raytrace.tcl index 31ad19a691..aacb668b95 100644 --- a/samples/tcl/raytrace.tcl +++ b/samples/tcl/raytrace.tcl @@ -1,5 +1,8 @@ # Script demonstrating ray tracing in 3d view +#Category: Visualization +#Title: Ray tracing + # make bottle by calling another script source [file join [file dirname [info script]] bottle.tcl] diff --git a/samples/tcl/spheres.tcl b/samples/tcl/spheres.tcl index fdf88ed4f4..2267912025 100644 --- a/samples/tcl/spheres.tcl +++ b/samples/tcl/spheres.tcl @@ -1,6 +1,9 @@ # test performance of display of heavy scene involving multiple interactive # objects, on example of 1000 spheres +#Category: Visualization +#Title: Display of complex scene and animation + pload MODELING pload VISUALIZATION diff --git a/samples/tcl/xde.tcl b/samples/tcl/xde.tcl index 0ec06a2fa8..2e00651565 100644 --- a/samples/tcl/xde.tcl +++ b/samples/tcl/xde.tcl @@ -1,6 +1,9 @@ # Simple sample demonstrating work with assemblies in XDE, and assignment of # names and colors to components vs. instances +#Category: Application Framework +#Title: Work with assemblies, colors etc. in XDE + pload MODELING pload OCAF pload XDE diff --git a/src/DrawResources/CURVES.tcl b/src/DrawResources/CURVES.tcl index d2930d72ff..f85e7814da 100644 --- a/src/DrawResources/CURVES.tcl +++ b/src/DrawResources/CURVES.tcl @@ -29,3 +29,4 @@ addmenu Curves "Hyperbola" { addmenu Curves "Parabola" { dialbox parabola name b center {0 0 0} normal {0 0 1} xdir {1 0 0} focus 1 } +redrawhelp diff --git a/src/DrawResources/DrawTK.tcl b/src/DrawResources/DrawTK.tcl index 12dd252e15..44c017072c 100644 --- a/src/DrawResources/DrawTK.tcl +++ b/src/DrawResources/DrawTK.tcl @@ -27,7 +27,21 @@ if { [info exists tk_library] } { } } +#fills menu "Load" with submenus +proc fillloadmenu {} { + set chan [open [file nativename $::env(CASROOT)/src/DrawResources/DrawPlugin]] + while {[gets $chan line] >= 0} { + if {[lindex [split $line ""] 0] != "!"} { + if {[lindex [split $line ""] 0] == ""} {continue} + set plugname [lindex [split $line " "] 0] + addmenu Load "pload $plugname" "pload $plugname" + } + } + close $chan +} + wm geometry . +10+10 +bind . {vcommands} frame .mbar -relief raised -bd 2 pack .mbar -side top -fill x @@ -53,7 +67,7 @@ proc addmenuitem {menu options} { proc addmenu {menu submenu {command ""}} { if {$command == ""} {set command $submenu} - addmenuitem $menu "command -label $submenu -command {$command}" + addmenuitem $menu "command -label {$submenu} -command {$command}" } ################################# @@ -62,10 +76,13 @@ proc addmenu {menu submenu {command ""}} { # the file menu -addmenu File datadir vdatadir -addmenu File restore vrestore -addmenu File source vsource -addmenu File exit +addmenu File "Choose Data Directory" vdatadir +addmenu File "Load Shape (restore)" vrestore +addmenu File "Load Script (source)" vsource +addmenu File Exit exit + +# the Load menu +fillloadmenu # the view menu @@ -87,15 +104,35 @@ addmenu Display 2dfit "2dfit; repaint" addmenu Display clear addmenu Display 2dclear +# the samples menu +addmenu Samples "View samples" vsample + +# the help menu + +addmenu Help "System Info" sysinfo +addmenu Help Commands vcommands +addmenu Help About about +addmenu Help "User Guide" openuserguide + +#redraw help submenu in the end of menu +proc redrawhelp {} { + global theMenus + set m $theMenus(Help) + destroy [string trimright $m ".menu"] + if [info exists theMenus(Help)] {unset theMenus(Help)} + addmenu Help "System Info" sysinfo + addmenu Help Commands vcommands + addmenu Help About about + addmenu Help "User Guide" openuserguide +} ################################# # Modal dialog box -# add OK, help, cancel buttons +# add OK, help, cancel buttons ################################# proc modaldialog {box okproc {helpproc ""} {cancelproc ""}} { wm geometry $box +10+60 - button $box.ok -text ok -command "$okproc ; destroy $box" pack $box.ok -side left button $box.ko -text Cancel -command "$cancelproc ; destroy $box" @@ -107,6 +144,11 @@ proc modaldialog {box okproc {helpproc ""} {cancelproc ""}} { grab set $box } + +################################# +# File menu procedures +################################# + ############################## # # dialbox command arg1 val1 arg2 val2 ... @@ -114,7 +156,6 @@ proc modaldialog {box okproc {helpproc ""} {cancelproc ""}} { ############################## proc dialbox args { - set com [lindex $args 0] toplevel .d @@ -141,151 +182,410 @@ proc dialbox args { append com ";repaint" modaldialog .d $com "help [lindex $args 0]" -} - - -#################################### -# Modal get file -# select a file and launch a command -# - file is the original value -# - okproc is the OK procedure, -# it will be called with the filename -# - title is the box title -# - filter is called on each subfile -# - Buttons are added in the dialbox, if none it is created -#################################### - -proc retyes {file} {return 1} - -proc getfile {file okproc title {filter "retyes"} {box ""}} { - - if {$box == ""} { - set box ".s" - toplevel .s - } - wm title $box $title - - # The text entry at the top - frame $box.d - entry $box.d.e -relief sunken -width 40 - $box.d.e insert end $file - button $box.d.s -text scan -command "filescan $filter $box" - pack $box.d.e -side left - pack $box.d.s -side right - pack $box.d -side top - - # The list box with the files - frame $box.f - listbox $box.f.l -relief sunken -yscrollcommand "$box.f.s set" - scrollbar $box.f.s -relief sunken -command "$box.f.l yview" - pack $box.f.l $box.f.s -side left -fill y - pack $box.f -side top - - filescan $filter $box - - bind $box.f.l "fileclick $box $filter $okproc" - - modaldialog $box [concat $okproc " \[" $box.d.e "get\]"] -} - -# when double click -proc fileclick {box filter okproc} { - filescan $filter $box [selection get] - set f [$box.d.e get] - if {! [file isdirectory $f]} { - destroy $box - $okproc $f - } -} - -proc filescan {filter box {subfile ""}} { - - set s [$box.d.e get] - if {$s == "."} {set s [pwd]/} - - $box.d.e delete 0 end - if {$subfile != ""} { - if {$subfile == ".."} { - set s [file dirname [file dirname $s]]/ - } else { - set s [file dirname $s]/$subfile } - } - $box.d.e insert end $s - - # list directories - $box.f.l delete 0 end - $box.f.l insert end ".." - if [file isdirectory $s] { - set d $s - if {![string match */ $s]} {append s "/"} - } else { - set d [file dirname $s] - } - foreach f [glob -nocomplain $d/*] { - if [$filter $f] { - set x [file tail $f] - if [file isdirectory $f] {append x "/"} - $box.f.l insert end $x - } - } -} - - -################################# -# File menu procedures -################################# - -# -# dialog box for datadir -# - -proc isdir {f} {return [file isdirectory $f]} - proc sdatadir {d} { - global Draw_DataDir - set Draw_DataDir $d + global Draw_DataDir + set Draw_DataDir $d } proc vdatadir {} { - global Draw_DataDir - toplevel .s - frame .s.t - button .s.t.d -text data -command { - .s.d.e delete 0 end - .s.d.e insert end $env(WBCONTAINER)/data/ - filescan isdir .s - } - pack .s.t.d -side left - pack .s.t -side top - getfile $Draw_DataDir sdatadir "Data Directory" isdir .s + global Draw_DataDir + sdatadir [tk_chooseDirectory -title "Data Directory" -initialdir $Draw_DataDir] } -proc notild {f} {return [expr ! [string match *~ $f]]} - proc rresto {f} { + if {[file exists $f]} { if {! [file isdirectory $f]} { - uplevel \#0 "brestore $f [file tail $f]" - repaint + puts "restore $f [file tail $f]" + uplevel \#0 "restore $f [file tail $f]" + repaint } + } } proc vrestore {} { - global Draw_DataDir - getfile $Draw_DataDir rresto "Restore" notild + global Draw_DataDir + rresto [tk_getOpenFile -title "Load Shape (restore)" -filetypes {{{BREP} {.brep}}} -initialdir $Draw_DataDir] } proc ssour {f} { - global Draw_Source + global Draw_Source + if {[file exists $f]} { set Draw_Source $f if {! [file isdirectory $f]} { - uplevel \#0 "source $f" + puts "source $f [file tail $f]" + uplevel \#0 "source $f" } + } } set Draw_Source [pwd] proc vsource {} { - global Draw_Source - getfile $Draw_Source ssour "Source" notild + global Draw_Source + ssour [tk_getOpenFile -title "Load Script (source)" -filetypes {{{All Files} *}} -initialdir Draw_Source] +} + +#Creates a "Samples" window +proc vsamples {} { + #create list {{category} {title} {filename}} + set alistofthree "" + foreach fname [file nativename [glob -path $::env(CASROOT)/samples/tcl/ *]] { + if {[lindex [split $fname "."] end] != "tcl"} {continue} + set chan [open $fname] + set istitlefound 0 + while {[gets $chan line] >= 0} { + if {[lindex [split $line " "] 0] == "#Category:"} { + set acategory [string trimleft $line "#Category: "] + } + if {[lindex [split $line " "] 0] == "#Title:"} { + set atitle [string trimleft $line "#Title: "] + lappend alistofthree $acategory $atitle $fname + incr istitlefound + break + } + } + close $chan + if {$istitlefound == 0} { + lappend alistofthree Other "[lindex [split $fname \\] end]" $fname + } + } + #create window + toplevel .samples + wm title .samples "Samples" + wm geometry .samples +0+0 + wm minsize .samples 800 600 + frame .samples.right + frame .samples.left + frame .samples.right.textframe + frame .samples.right.botframe + ttk::treeview .samples.left.tree -selectmode browse -yscrollcommand {.samples.left.treescroll set} + pack .samples.left.tree -fill both -expand 1 -side left + .samples.left.tree column #0 -minwidth 200 + .samples.left.tree heading #0 -text "Samples" + pack .samples.right -side right -fill both -expand 1 -padx 10 -pady 10 + pack .samples.left -side left -padx 10 -pady 10 -fill both + pack .samples.right.textframe -side top -fill both -expand 1 + pack .samples.right.botframe -side bottom -fill both -expand 1 + text .samples.right.textframe.text -yscrollcommand {.samples.right.textframe.scroll set} -xscrollcommand {.samples.right.botframe.scrollx set} -wrap none -width 40 -height 32 + pack .samples.right.textframe.text -fill both -side left -expand 1 + .samples.right.textframe.text delete 0.0 end + .samples.right.textframe.text configure -state disabled + set i 1 + foreach {acat title fnam} $alistofthree { + if [.samples.left.tree exists $acat] { + .samples.left.tree insert $acat end -id $title -text $title -tags "selected$i" + .samples.left.tree tag bind selected$i <1> "fillsampletext {$fnam}" + incr i + continue + } else { + .samples.left.tree insert {} end -id $acat -text $acat + .samples.left.tree insert $acat end -id $title -text $title -tags "selected$i" + .samples.left.tree tag bind selected$i <1> "fillsampletext {$fnam}" + incr i + } + } + scrollbar .samples.right.textframe.scroll -command {.samples.right.textframe.text yview} + scrollbar .samples.left.treescroll -command {.samples.left.tree yview} + scrollbar .samples.right.botframe.scrollx -command {.samples.right.textframe.text xview} -orient horizontal + pack .samples.right.textframe.scroll -side right -fill y + pack .samples.right.botframe.scrollx -side top -fill x + pack .samples.left.treescroll -side right -fill y + button .samples.right.botframe.button -text "Run sample" -state disabled + pack .samples.right.botframe.button -fill none -pady 10 +} + +#Fills the textbox in "Samples" window +proc fillsampletext {fname} { + .samples.right.botframe.button configure -state normal -command "lower .samples;catch {vclose ALL};catch {vremove -all}; catch {vclear}; source {$fname}" + .samples.right.textframe.text configure -state normal + .samples.right.textframe.text delete 0.0 end + set chan [open "$fname"] + while {[gets $chan line] >= 0} { + .samples.right.textframe.text insert end "$line\n" + } + close $chan + .samples.right.textframe.text configure -state disabled +} + +#Creates a "Commands help" window +proc vcommands {} { + global Draw_Groups Find_Button_Click_Count Entry_Cache + set Find_Button_Click_Count 0 + set Entry_Cache "" + toplevel .commands + focus .commands + wm minsize .commands 800 600 + wm title .commands "Commands help" + wm geometry .commands +0+0 + frame .commands.t + frame .commands.left + ttk::treeview .commands.left.tree -selectmode browse -yscrollcommand {.commands.left.treescroll set} + .commands.left.tree column #0 -width 300 + .commands.left.tree heading #0 -text "Help treeview" + pack .commands.left.tree -expand 1 -fill both -side left + pack .commands.t -side right -fill both -expand 1 -padx 10 -pady 10 + pack .commands.left -side left -fill both -padx 10 -pady 10 + pack [frame .commands.t.top] -side top -fill x -padx 10 -pady 10 + text .commands.t.text -yscrollcommand {.commands.t.scroll set} -width 40 + .commands.t.text delete 0.0 end + pack .commands.t.text -fill both -side left -expand 1 + .commands.t.text configure -state disabled + pack [entry .commands.t.top.e -width 20] -side left + pack [button .commands.t.top.findcom -text "Find command" -command vhelpsearch] -side left -padx 10 + pack [button .commands.t.top.textfind -text "Find in text" -command "vhelptextsearch; incr Find_Button_Click_Count"] -side left + set i 1 + set j 100 + set newgroupinx 0 + foreach h [lsort [array names Draw_Groups]] { + .commands.left.tree insert {} end -id $i -text $h -tags "info$i" + .commands.left.tree tag bind info$i <1> "vcomhelp {$h}" + set newgroupinx $j + foreach f [lsort $Draw_Groups($h)] { + .commands.left.tree insert $i end -id $j -text $f -tags "selected$j" + .commands.left.tree tag bind selected$j <1> "vcomhelp {$h} $j $newgroupinx" + incr j + } + incr i + } + scrollbar .commands.t.scroll -command {.commands.t.text yview} + scrollbar .commands.left.treescroll -command {.commands.left.tree yview} + pack .commands.t.scroll -side right -fill y + pack .commands.left.treescroll -side right -fill y -expand 1 + #hotkeys + bind .commands.t.top.e {vhelpsearch} + bind .commands {focus .commands.t.top.e} + bind .commands {focus .commands.t.top.e} + bind .commands {destroy .commands} + } + +############################################################ +# Fills the textbox in "Commands help" window +# $h -group of commands to display +# $selindex - index of selected item in the treeview +# $startindex - index of item int the treeview to start from +############################################################ +proc vcomhelp {h {selindex -1} {startindex 0}} { + global Draw_Helps Draw_Groups + set highlighted false + .commands.t.text configure -state normal + .commands.t.text delete 1.0 end + foreach f [lsort $Draw_Groups($h)] { + if {$startindex == $selindex} { + .commands.t.text insert end "$f : $Draw_Helps($f)\n\n" "highlightline" + incr startindex + set highlighted true + continue + } + .commands.t.text insert end "$f : $Draw_Helps($f)\n\n" + incr startindex + } + .commands.t.text tag configure highlightline -background yellow -relief raised + .commands.t.text configure -state disabled + if {$highlighted == true} {.commands.t.text see highlightline.last} +} + +#Creates a "About" window +proc about {} { + toplevel .about + focus .about + wm resizable .about 0 0 + wm title .about "About" + set screenheight [expr {int([winfo screenheight .]*0.5-200)}] + set screenwidth [expr {int([winfo screenwidth .]*0.5-200)}] + wm geometry .about 400x200+$screenwidth+$screenheight + image create photo occlogo -file $::env(CASROOT)/src/DrawResources/OCC_logo.png -format png + frame .about.logo -bg red + frame .about.links -bg blue + frame .about.copyright + pack .about.logo -side top -fill both + pack .about.links -fill both + pack .about.copyright -side top -fill both + label .about.logo.img -image occlogo + pack .about.logo.img -fill both + text .about.links.text -bg lightgray -fg blue -height 1 -width 10 + .about.links.text insert end "http://www.opencascade.com/" "link1" + .about.links.text tag bind link1 <1> "_launchBrowser http://www.opencascade.com/" + .about.links.text tag bind link1 ".about.links.text configure -cursor hand2" + .about.links.text tag bind link1 ".about.links.text configure -cursor arrow" + .about.links.text tag configure link1 -underline true -justify center + pack .about.links.text -fill both + label .about.copyright.text -text "Copyright (c) 1999-2014 OPEN CASCADE SAS" + button .about.button -text "OK" -command "destroy .about" + pack .about.button -padx 10 -pady 10 + pack .about.copyright.text + .about.links.text configure -state disabled + grab .about + bind .about {destroy .about} +} + +#Executes files and hyperlinks +proc launchBrowser url { + global tcl_platform + + if {$tcl_platform(platform) eq "windows"} { + set command [list {*}[auto_execok start] {}] + } elseif {$tcl_platform(os) eq "Darwin"} { + set command [list open] + } else { + set command [list xdg-open] + } + exec {*}$command $url & +} + +#Safe execution of files and hyperlinks +proc _launchBrowser {url} { + if [catch {launchBrowser $url} err] { + tk_messageBox -icon error -message "error '$err' with '$command'" + } +} +################################################################ +# This procedure tries to open an userguide on Draw Harness in pdf format +# If there is no a such one, then tries to open it in html format +# Else opens a site with this guide +################################################################ +proc openuserguide {} { + if [file exists $::env(CASROOT)/doc/pdf/user_guides/occt_test_harness.pdf] { + _launchBrowser $::env(CASROOT)/doc/pdf/user_guides/occt_test_harness.pdf + } elseif [file exists $::env(CASROOT)/doc/overview/html/occt_user_guides__test_harness.html] { + _launchBrowser $::env(CASROOT)/doc/overview/html/occt_user_guides__test_harness.html + } else { + _launchBrowser {http://dev.opencascade.org/doc/overview/html/occt_user_guides__test_harness.html} + } +} + +#Search through commands and display the result +proc vhelpsearch {} { + global Draw_Groups Entry_Cache + set searchstring [.commands.t.top.e get] + set i 1 + set j 100 + set newgroupinx 0 + set isfound 0 + foreach h [lsort [array names Draw_Groups]] { + set newgroupinx $j + foreach f [lsort $Draw_Groups($h)] { + if {$f == $searchstring} { + incr isfound + .commands.left.tree see $j + .commands.left.tree selection set $j + vcomhelp $h $j $newgroupinx + break + } + incr j + } + incr i + } + if {$isfound == 0} { + errorhelp "No help found for '$searchstring'!" + } else {set Entry_Cache ""} +} + +#Displays an error window with $errstring inside +proc errorhelp {errstring} { + toplevel .errorhelp + focus .errorhelp + wm resizable .errorhelp 0 0 + wm title .errorhelp "Error" + set screenheight [expr {int([winfo screenheight .]*0.5-200)}] + set screenwidth [expr {int([winfo screenwidth .]*0.5-200)}] + wm geometry .errorhelp +$screenwidth+$screenheight + text .errorhelp.t -width 40 -height 5 + .errorhelp.t insert end $errstring + button .errorhelp.button -text "OK" -command "destroy .errorhelp" + pack .errorhelp.t + .errorhelp.t configure -state disabled + pack .errorhelp.button -padx 10 -pady 10 + bind .errorhelp {destroy .errorhelp} + grab .errorhelp +} + +#Search through text of help and display the result +proc vhelptextsearch {} { + global Draw_Helps Draw_Groups Find_Button_Click_Count Entry_Cache End_of_Search + set searchstring [.commands.t.top.e get] + if {$Entry_Cache != $searchstring} { + set Find_Button_Click_Count 0 + set End_of_Search 0 + set Entry_Cache $searchstring + } + if {$End_of_Search} { + errorhelp "No more '$searchstring' found!" + return + } + .commands.t.text configure -state normal + .commands.t.text delete 0.0 end + set i 0 + set isfound 0 + foreach h [lsort [array names Draw_Groups]] { + foreach f [lsort $Draw_Groups($h)] { + if [string match *$searchstring* $Draw_Helps($f)] { + incr i + if {$i > $Find_Button_Click_Count+1} {incr isfound; break} + .commands.t.text insert end "$f : " + foreach line [list $Draw_Helps($f)] { + foreach word [split $line " "] { + if [string match *$searchstring* $word] { + .commands.t.text insert end "$word" "highlightword" + .commands.t.text insert end " " + continue + } + .commands.t.text insert end "$word " + } + } + .commands.t.text insert end \n\n + } + } + } + if {!$isfound} { + incr End_of_Search + } + .commands.t.text tag configure highlightword -background yellow -relief raised + .commands.t.text see end +} + +#Create a "System information" window +proc sysinfo {} { + toplevel .info + wm title .info "System information" + wm resizable .info 0 0 + pack [frame .info.top] -side top -fill both -padx 5 -pady 10 + pack [frame .info.bot] -side bottom -fill both -padx 5 -pady 10 + pack [frame .info.top.left] -side left -fill both -padx 5 -pady 10 + pack [frame .info.top.mid] -side left -fill both -padx 5 -pady 10 + pack [frame .info.top.right] -side left -fill both -padx 5 -pady 10 + pack [label .info.top.left.label -text "OCCT build configuration "] + pack [label .info.top.mid.label -text "Memory info"] + pack [label .info.top.right.label -text "OpenGL info"] + pack [text .info.top.left.text -width 50 -height 20] + pack [text .info.top.mid.text -width 50 -height 20] + pack [text .info.top.right.text -width 50 -height 20] + pack [button .info.bot.button -text "Update" -command rescaninfo] + pack [button .info.bot.close -text "Close" -command "destroy .info"] -pady 10 + rescaninfo +} + +#Updates information in "System information" window +proc rescaninfo {} { + .info.top.left.text configure -state normal + .info.top.mid.text configure -state normal + .info.top.right.text configure -state normal + .info.top.left.text delete 0.0 end + .info.top.mid.text delete 0.0 end + .info.top.right.text delete 0.0 end + .info.top.left.text insert end [dversion] + .info.top.mid.text insert end [meminfo] + set glinfo "" + if [catch {vglinfo} err] { + if {$err == ""} { + .info.top.right.text insert end "No active view. Please call vinit." + } else { + .info.top.right.text insert end "VISUALIZATION is not loaded. Please call pload VISUALIZATION" + } + } else { + .info.top.right.text insert end [vglinfo] + } + .info.top.left.text configure -state disabled + .info.top.mid.text configure -state disabled + .info.top.right.text configure -state disabled } diff --git a/src/DrawResources/OCC_logo.png b/src/DrawResources/OCC_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5745283fbf6ae6b51a20a802d6b8399253b620ba GIT binary patch literal 13630 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