27 if {$tcl_platform(os)=="Darwin" && [
file exists $minskyHome/../Resources/fontconfig/fonts.conf]} {
28 set env(FONTCONFIG_FILE) $minskyHome/../Resources/fontconfig/fonts.conf
31 if {[minsky.ravelVersion]=="unavailable"} {
41 set backgroundColour lightGray
42 set preferences(nRecentFiles) 10
43 set preferences(panopticon) 0
44 set preferences(focusFollowsMouse) 0
45 set preferences(multipleEquities) 0
49 switch $tcl_platform(os) {
51 "windows" {minsky.defaultFont "Arial Unicode MS"}
56 if {$tcl_platform(platform)=="unix"} {
57 set rcfile "$env(HOME)/.minskyrc"
58 }
elseif {$tcl_platform(platform)=="windows"} {
59 set rcfile "$env(USERPROFILE)/.minskyrc"
61 if [
file exists $rcfile] {
62 catch {source $rcfile}
67 if {![
file exists [
file join $tcl_library init.tcl]] ||
68 [
file normalize $tcl_library]==[
file normalize $minskyHome/library]} {
69 set tcl_library $minskyHome/library/tcl
74 if {![
info exists tk_library]} {
75 regsub tcl [
file tail [
info library]] tk tk_library
76 set tk_library [
file join [
file dirname [
info library]] $tk_library]
78 if {![
file exists [
file join $tk_library tk.tcl]]
80 set tk_library $minskyHome/library/tk
89 set env(TCL_LIBRARY) $tcl_library
90 set env(TK_LIBRARY) $tk_library
92 proc setFname {name} {
93 global fname workDir progName
94 if [
string length $name] {
96 set workDir [
file dirname $name]
97 catch {
wm title . "$progName: $fname"}
105 proc value.value {args} {
107 return [minsky.value.value [
lindex $args 0]]
109 return [minsky.value.value 0]
112 proc attachTraceProc {namesp} {
113 foreach p [
info commands $namesp*] {
114 if {$p ne "::traceProc"} {
115 trace remove execution $p enterstep traceProc
116 trace add execution $p enterstep traceProc
120 foreach n [
namespace children $namesp] {
125 proc traceProc {args} {
126 array set frameInfo [
info frame -2]
127 if {[
info exists frameInfo(proc)]&&[
info exists frameInfo(line)]} {
128 cov.add $frameInfo(proc) $frameInfo(line)
130 if {[
info exists frameInfo(file)]&&[
info exists frameInfo(line)]} {
131 cov.add $frameInfo(file) $frameInfo(line)
135 if [
info exists env(MINSKY_COV)] {
138 cov.init $env(MINSKY_COV) w
140 rename tcl_exit tcl_exit2
141 proc tcl_exit {args} {
143 proc traceProc {args} {}
151 proc setCursor {cur} {}
154 if {$argc>1 && [
string match "*.tcl" $argv(1)]} {source $argv(1)}
156 source $tcl_library/init.tcl
158 if {$tcl_platform(os)=="Darwin"} {
159 if {[
catch {GUI}] || [
catch {source [
file join $tk_library tk.tcl]}]} {
161 exec osascript << "tell application \"System Events\"
163 display dialog \"GUI failed to initialise, try installing XQuartz\"
168 source [
file join $tk_library tk.tcl]
171 source [
file join $tk_library bgerror.tcl]
172 source $minskyHome/library/init.tcl
173 source $minskyHome/helpRefDb.tcl
175 disableEventProcessing
180 rename ::tk::SetFocusGrab ::tk::SetFocusGrab_
181 proc ::tk::SetFocusGrab {grab focus} {
182 ::tk::SetFocusGrab_ $grab $focus
183 wm attributes $grab -topmost 1
189 proc setBackgroundColour bgc {
190 global backgroundColour
191 set backgroundColour $bgc
194 ttk::style configure TNotebook -background $backgroundColour
195 ttk::style configure TNotebook.Tab -background $backgroundColour
196 ttk::style map TNotebook.Tab -background "selected $bgc active $bgc"
197 if [
winfo exists .controls.runmode] {.controls.runmode configure -selectcolor $bgc}
201 option add *Menu.tearOff 0
203 tk appname [
file rootname [
file tail $argv(0)]]
204 wm title . "$progName: $fname"
206 proc tk_focusPrev {win} {
return $win}
207 proc tk_focusNext {win} {
return $win}
208 if {$preferences(focusFollowsMouse)} {
212 set old [
bind all <Enter>]
214 if {"%d" eq "NotifyAncestor" || "%d" eq "NotifyNonlinear" \
215 || "%d" eq "NotifyInferior"} {
220 bind all <Enter> "$old; $script"
222 bind all <Enter> $script
225 proc setCursor {cur} {. configure -cursor $cur update idletasks}
227 if {[tk windowingsystem]=="win32"} {
230 bind . <MouseWheel> {
231 switch [winfo containing %X %Y] {
234 # on Winblows, min val of |%D| is 120, so just use sign
237 zoomAt %x %y [expr 1.0/1.1]
244 source $minskyHome/library/tooltip.tcl
245 namespace import tooltip::tooltip
247 source $minskyHome/library/obj-browser.tcl
251 if {[tk windowingsystem] == "aqua"} {
252 event add <<contextMenu>> <Button-2> <Control-Button-1>
253 event add <<middleMouse>> <Button-3>
254 event add <<middleMouse-Motion>> <B3-Motion>
255 event add <<middleMouse-ButtonRelease>> <B3-ButtonRelease>
257 event add <<contextMenu>> <Button-3>
258 event add <<middleMouse>> <Button-2>
259 event add <<middleMouse-Motion>> <B2-Motion>
260 event add <<middleMouse-ButtonRelease>> <B2-ButtonRelease>
265 proc deiconify {widget} {
267 after idle "wm deiconify $widget; raise $widget; focus -force $widget"
271 menu .menubar -type menubar
273 if {[tk windowingsystem] == "aqua"} {
275 .menubar.apple add command -label "About Minsky" -command aboutMinsky
276 .menubar add cascade -menu .menubar.apple
281 proc ::tk::mac::OpenDocument {args} {
286 proc ::tk::mac::ShowHelp {} {
help Introduction}
294 .menubar add cascade -menu .menubar.file -label File -underline 0
296 menu .menubar.edit -postcommand togglePaste
297 .menubar add cascade -menu .menubar.edit -label Edit -underline 0
299 menu .menubar.bookmarks -postcommand generateBookmarkMenu
300 .menubar add cascade -menu .menubar.bookmarks -label Bookmarks -underline 0
301 menu .menubar.bookmarks.deleteMenu
304 .menubar add cascade -menu .menubar.ops -label Insert -underline 0
306 menu .menubar.options
307 .menubar add cascade -menu .menubar.options -label Options -underline 0
308 .menubar.options add command -label "Preferences" -command showPreferences
313 set preferencesVars {
314 godleyDisplay "Godley Table Show Values" 1 bool
315 godleyDisplayStyle "Godley Table Output Style" sign { enum
318 multipleEquities "Enable multiple equity columns" 1 bool
319 nRecentFiles "Number of recent files to display" 10 text
320 wrapLaTeXLines "Wrap long equations in LaTeX export" 1 bool
321 panopticon "Enable panopticon" 1 bool
322 focusFollowsMouse "Focus follows mouse" 1 bool
324 lappend preferencesVars defaultFont "Font" [defaultFont] font
326 foreach {var text default type} $preferencesVars {
328 if {![
info exists preferences($var)]} {
329 set preferences($var) $default
333 proc showPreferences {} {
334 if [
winfo exists .preferencesForm]
return 335 global preferences_input preferences preferencesVars
336 foreach var [
array names preferences] {
337 set preferences_input($var) $preferences($var)
340 toplevel .preferencesForm
341 wm resizable .preferencesForm 0 0
345 grid [
label .preferencesForm.label$row -text "Preferences"] -column 1 -columnspan 999 -pady 10
349 grid [
frame .preferencesForm.f1] -column 1 -row 1 -rowspan 999 -padx 10
350 grid [
frame .preferencesForm.f2] -column 999 -row 1 -rowspan 999 -padx 10
353 foreach {var text default type} $preferencesVars {
354 set rowdict($text) $row
356 grid [
label .preferencesForm.label$row -text $text] -column 10 -row $row -sticky e -pady 5
360 grid [
entry .preferencesForm.text$row -width 20 -textvariable preferences_input($var)] -column 20 -row $row -sticky ew -columnspan 999
363 grid [
checkbutton .preferencesForm.cb$row -variable preferences_input($var)] -row $row -column 20 -sticky w
366 grid [ttk::combobox .preferencesForm.font -textvariable preferences_input($var) -values [lsort [listFonts]] -state readonly] -row $row -column 20 -sticky w
367 image create cairoSurface fontSampler -surface minsky.fontSampler
368 grid [
label .preferencesForm.fontSample -image fontSampler -width 150 -height 20] -row $row -column 30 -sticky w
369 bind .preferencesForm.font <<ComboboxSelected>> {
370 defaultFont [.preferencesForm.font get]
371 fontSampler.requestRedraw
376 if {[
llength $type] > 1} {
377 switch [
lindex $type 0] {
380 foreach {valtext val} [
lrange $type 1 end] {
381 grid [
radiobutton .preferencesForm.rb${row}v$column -text $valtext -variable preferences_input($var) -value $val] -row $row -column $column
386 }
else { error "unknown preferences widget $type"}
393 set preferences(initial_focus) ".preferencesForm.cb$rowdict(Godley Table Show Values)"
395 frame .preferencesForm.buttonBar
396 button .preferencesForm.buttonBar.ok -text OK -command {setPreferenceParms; closePreferencesForm; redrawAllGodleyTables}
397 button .preferencesForm.buttonBar.cancel -text cancel -command {closePreferencesForm}
398 pack .preferencesForm.buttonBar.ok [
label .preferencesForm.buttonBar.spacer -width 2] .preferencesForm.buttonBar.cancel -side left -pady 10
399 grid .preferencesForm.buttonBar -column 1 -row 999 -columnspan 999
401 bind .preferencesForm <Key-Return> {invokeOKorCancel .preferencesForm.buttonBar}
403 wm title .preferencesForm "Preferences"
407 ::tk::TabToWindow $preferences(initial_focus)
409 grab set .preferencesForm
410 wm transient .preferencesForm .
413 .menubar.options add command -label "Background Colour" -command {
414 set bgc [tk_chooseColor -initialcolor $backgroundColour]
416 set backgroundColour $bgc
417 setBackgroundColour $backgroundColour
421 menu .menubar.rungeKutta
422 .menubar.rungeKutta add command -label "Simulation" -command {
423 foreach {var text} $rkVars { set rkVarInput($var) [$var] }
424 set implicitSolver [implicit]
427 ::tk::TabToWindow $rkVarInput(initial_focus)
428 ensureWindowVisible .rkDataForm
430 wm transient .rkDataForm .
432 .menubar add cascade -label "Simulation" -menu .menubar.rungeKutta
436 if {[tk windowingsystem] != "aqua"} {
437 .menubar.help add command -label "Minsky Documentation" -command {help Introduction}
439 .menubar add cascade -label Help -menu .menubar.help
441 bind . <F1> topLevelHelp
442 bind .menubar.file <F1> {help File}
446 . configure -menu .menubar
451 label .controls.statusbar -text "t: 0 Δt: 0"
457 button .controls.run -text run -command runstop
458 button .controls.reset -text reset -command reset
459 button .controls.step -text step -command {step}
461 image create photo runButton -file "$minskyHome/icons/Play.gif"
462 image create photo stopButton -file "$minskyHome/icons/Pause.gif"
463 image create photo resetButton -file "$minskyHome/icons/Rewind.gif"
464 image create photo stepButton -file "$minskyHome/icons/Last.gif"
466 button .controls.run -image runButton -height 25 -width 25 -command runstop
467 button .controls.reset -image resetButton -height 25 -width 25 -command reset
468 button .controls.step -image stepButton -height 25 -width 25 -command {step}
471 image create photo recalculate -file "$minskyHome/icons/recalculate.gif"
472 button .controls.recalculate -image recalculate -height 25 -width 25 -command reset
473 image create photo rec -file "$minskyHome/icons/rec.gif"
474 image create photo runmode -file "$minskyHome/icons/runmode.gif"
475 image create photo recplay -file "$minskyHome/icons/recplay.gif"
477 checkbutton .controls.rec -image rec -height 25 -width 25 -command toggleRecording -variable eventRecording -indicatoron 0
478 checkbutton .controls.runmode -image runmode -height 25 -width 25 -selectimage recplay -variable recordingReplay -command replay -indicatoron 0 -selectcolor $backgroundColour
479 checkbutton .controls.reverse -text "Rev" -command {
480 minsky.reverse $reverse} -variable reverse
482 tooltip .controls.recalculate "Recalculate"
483 tooltip .controls.rec "Record"
484 tooltip .controls.runmode "Simulate/Recording Replay"
485 tooltip .controls.reverse "Reverse simulation"
486 tooltip .controls.run "Run/Stop"
487 tooltip .controls.reset "Reset simulation"
488 tooltip .controls.step "Step simulation"
491 bind .controls.step <ButtonPress-1> {set buttonPressed 1; autoRepeatButton .controls.step}
492 bind . <ButtonRelease-1> {set buttonPressed 0}
494 proc generateBookmarkMenu {} {
495 .menubar.bookmarks delete 0 end
496 .menubar.bookmarks add command -label "Bookmark this position" -command addBookMark
497 .menubar.bookmarks.deleteMenu delete 0 end
498 .menubar.bookmarks add cascade -label "Delete ..." -menu .menubar.bookmarks.deleteMenu
499 .menubar.bookmarks add separator
501 foreach i [minsky.canvas.model.bookmarkList] {
502 .menubar.bookmarks add command -label $i -command "canvas.model.gotoBookmark $p; canvas.requestRedraw"
503 .menubar.bookmarks.deleteMenu add command -label $i -command "canvas.model.deleteBookmark $p"
508 proc addBookMark {} {
509 toplevel .bookMarkDialog
510 frame .bookMarkDialog.name
511 label .bookMarkDialog.name.text -text "Bookmark name"
512 entry .bookMarkDialog.name.val
513 pack .bookMarkDialog.name.text .bookMarkDialog.name.val -side left
514 pack .bookMarkDialog.name
516 minsky.canvas.model.addBookmark [.bookMarkDialog.name.val get]
519 wm transient .bookMarkDialog
520 focus .bookMarkDialog.name.val
521 grab set .bookMarkDialog
525 proc invokeButton button {
527 if {$buttonPressed} {
534 proc autoRepeatButton button {
535 after 500 invokeButton $button
538 proc setSimulationDelay {delay} {
542 if {$delay != [simulationDelay]} {
544 simulationDelay $delay
549 label .controls.slowSpeed -text "slow"
550 label .controls.fastSpeed -text "fast"
551 scale .controls.simSpeed -variable delay -command setSimulationDelay -to 0 -from 12 -length 150 -label "Simulation Speed" -orient horizontal -showvalue 0
555 pack .controls.recalculate .controls.rec .controls.runmode .controls.reverse .controls.run .controls.reset .controls.step .controls.slowSpeed .controls.simSpeed .controls.fastSpeed -side left
556 pack .controls.statusbar -side right -fill x
558 grid .controls -row 0 -column 0 -columnspan 1000 -sticky ew
560 menu .menubar.file.recent
563 .exportPlots add command -label "as SVG" -command {minsky.renderAllPlotsAsSVG [file rootname $fname]}
564 .exportPlots add command -label "as CSV" -command {minsky.exportAllPlotsAsCSV [file rootname $fname]}
567 .menubar.file add command -label "About Minsky" -command aboutMinsky
568 .menubar.file add command -label "Upgrade" -command {openURL http://www.patreon.com/hpcoder}
569 .menubar.file add command -label "New System" -command newSystem -underline 0 -accelerator $meta_menu-N
570 .menubar.file add command -label "Open" -command openFile -underline 0 -accelerator $meta_menu-O
571 .menubar.file add cascade -label "Recent Files" -menu .menubar.file.recent
572 .menubar.file add command -label "Library" -command "openURL https://github.com/highperformancecoder/minsky-models"
574 .menubar.file add command -label "Save" -command save -underline 0 -accelerator $meta_menu-S
575 .menubar.file add command -label "SaveAs" -command saveAs -underline 4 -accelerator $meta_menu-A
576 .menubar.file add command -label "Insert File as Group" -command insertFile
577 .menubar.file add command -label "Import Vensim MDL file" -command importMDL
579 .menubar.file add command -label "Dimensional Analysis" -command {
581 tk_messageBox -type ok -icon info -message "Dimension Analysis passed"
584 .menubar.file add command -label "Export resolution factor: [minsky.canvas.resolutionScaleFactor]" -command {setExportResolutionFactor minsky.canvas}
585 .menubar.file add command -label "Export Canvas" -command exportCanvas
586 .menubar.file add cascade -label "Export Plots" -menu .exportPlots
587 .menubar.file add checkbutton -label "Log simulation" -variable simLogging \
589 .menubar.file add checkbutton -label "Recording" -command toggleRecording -variable eventRecording
590 .menubar.file add checkbutton -label "Replay recording" -command replay -variable recordingReplay
592 .menubar.file add command -label "Quit" -command exit -underline 0 -accelerator $meta_menu-Q
593 .menubar.file add separator
594 .menubar.file add command -foreground #5f5f5f -label "Debugging Use"
595 .menubar.file add command -label "Redraw" -command canvas.requestRedraw
596 .menubar.file add command -label "Object Browser" -command obj_browser
597 .menubar.file add command -label "Select items" -command selectItems
598 .menubar.file add command -label "Command" -command cli
600 .menubar.file configure -postcommand {
601 .menubar.file entryconfigure "Export resolution factor:*" -label "Export resolution factor: [minsky.canvas.resolutionScaleFactor]"
604 proc imageFileTypes {} {
606 set fileTypes {{"SVG" .svg TEXT} {"PDF" .pdf TEXT} {"Postscript" .eps TEXT} {"Portable Network Graphics" .png TEXT}}
607 if {$tcl_platform(platform)=="windows"} {
lappend fileTypes {"EMF" .emf TEXT}}
611 proc setExportResolutionFactor {setter} {
612 toplevel .resolutionFactor
613 wm title .resolutionFactor "Export resolution scale factor"
614 ttk::spinbox .resolutionFactor.value -from 1 -to 1000 -increment 1
615 pack .resolutionFactor.value
616 .resolutionFactor.value set [$setter.resolutionScaleFactor]
617 buttonBar .resolutionFactor "$setter.resolutionScaleFactor \[.resolutionFactor.value get\]"
621 proc renderImage {filename type surf} {
623 if [
string match -nocase *.svg "$filename"] {
624 $surf.renderToSVG "$filename"
625 }
elseif [
string match -nocase *.pdf "$filename"] {
626 $surf.renderToPDF "$filename"
627 }
elseif {[
string match -nocase *.ps "$filename"] || [
string match -nocase *.eps "$filename"]} {
628 $surf.renderToPS "$filename"
629 }
elseif {[
string match -nocase *.png "$filename"]} {
630 $surf.renderToPNG "$filename"
631 }
elseif {$tcl_platform(platform)=="windows" && [
string match -nocase *.emf "$filename"]} {
632 $surf.renderToEMF "$filename"
635 "SVG" {$surf.renderToSVG "$filename.svg"}
636 "PDF" {$surf.renderToPDF "$filename.pdf"}
637 "PNG" {$surf.renderToPNG "$filename.png"}
638 "EMF" {$surf.renderToEMF "$filename.emf"}
639 "Postscript" {$surf.renderToPS "$filename.eps"}
640 default {
return false}
646 proc exportCanvas {} {
647 global workDir type fname preferences tabSurface
650 lappend fileTypes {"LaTeX" .tex TEXT} {"Matlab" .m TEXT}
651 set f [
tk_getSaveFile -filetypes $fileTypes \
652 -initialdir $workDir -typevariable type -initialfile [
file rootname [
file tail $fname]]]
654 set workDir [
file dirname $f]
656 set surf [
lindex [.tabs tabs] [.tabs index current]].canvas
657 if [
renderImage $f $type $tabSurface([.tabs tab current -text])]
return 658 if {[
string match -nocase *.tex "$f"]} {
659 latex "$f" $preferences(wrapLaTeXLines)
660 }
elseif {[
string match -nocase *.m "$f"]} {
664 "LaTeX" {latex "$f.tex" $preferences(wrapLaTeXLines)}
665 "Matlab" {matlab "$f.m"}
672 global varNames allLogVars varIds
677 frame .logVars.buttons
678 button .logVars.buttons.ok -text OK -command logVarsOK
679 checkbutton .logVars.buttons.all -text All -variable allLogVars -command {
680 .logVars.selection.selection selection [expr $allLogVars?"set":"clear"] 0 end
682 pack .logVars.buttons.ok .logVars.buttons.all -side left
684 foreach v [variableValues.#keys] {
685 if {![regexp "^constant:" $v]} {
687 lappend varNames [minsky.value.name]
691 frame .logVars.selection
692 listbox .logVars.selection.selection -listvariable varNames -selectmode extended -height 30 -yscrollcommand ".logVars.selection.vscroll set" -selectforeground blue
693 scrollbar .logVars.selection.vscroll -orient vertical -command ".logVars.selection.selection yview"
694 pack .logVars.selection.selection -fill both -side left -expand y
695 pack .logVars.selection.vscroll -fill y -side left -expand y
696 pack .logVars.buttons .logVars.selection
700 wm transient .logVars
704 global workDir varIds
705 set indices [.logVars.selection.selection curselection]
707 foreach i $indices {
lappend vars [
lindex $varIds $i]}
710 openLogFile [
tk_getSaveFile -defaultextension .dat -initialdir $workDir]
716 .menubar.edit add command -label "Undo" -command "undo 1" -accelerator $meta_menu-Z
717 .menubar.edit add command -label "Redo" -command "undo -1" -accelerator $meta_menu-Y
718 .menubar.edit add command -label "Cut" -command cut -accelerator $meta_menu-X
719 .menubar.edit add command -label "Copy" -command "minsky.copy" -accelerator $meta_menu-C
720 .menubar.edit add command -label "Paste" -command "minsky.paste" -accelerator $meta_menu-V
721 .menubar.edit add command -label "Group selection" -command "minsky.createGroup" -accelerator $meta_menu-G
722 .menubar.edit add command -label "Dimensions" -command dimensionsDialog
723 .menubar.edit add command -label "Remove units" -command minsky.deleteAllUnits
724 .menubar.edit add command -label "Randomize layout" -command minsky.randomLayout
725 .menubar.edit add command -label "Auto layout" -command minsky.autoLayout
727 proc getClipboard {} {
729 catch {
clipboard get -type UTF8_STRING} contents
733 proc getClipboard {} {
735 catch {
clipboard get -type UTF8_STRING} contents
739 proc togglePaste {} {
741 .menubar.edit entryconfigure "Paste" -state disabled
743 .menubar.edit entryconfigure "Paste" -state normal
751 minsky.canvas.requestRedraw
760 proc dimensionsDialog {} {
761 populateMissingDimensions
763 grid [
button .dimensions.cancel -text Cancel -command "destroy .dimensions"] \
764 [
button .dimensions.ok -text OK -command {
765 set colRows [grid size .dimensions]
766 for {set i 2} {$i<[lindex $colRows 1]} {incr i} {
767 set dim [.dimensions.g${i}_dim get]
769 set d [dimensions.@elem $dim]
770 $d.type [.dimensions.g${i}_type get]
771 if [info exists timeFormatStrings([.dimensions.g${i}_units get])] {
772 $d.units $timeFormatStrings([.dimensions.g${i}_units get])
774 $d.units [.dimensions.g${i}_units get]
782 grid [
label .dimensions.g1_dim -text Dimension] \
783 [
label .dimensions.g1_type -text Type]\
784 [
label .dimensions.g1_units -text "Units/Format"]
785 tooltip .dimensions.g1_units "Value type: enter a unit string, eg m/s; time type: enter a strftime format string, eg %Y-%m-%d %H:%M:%S, or %Y-Q%Q"
787 set colRows [
grid size .dimensions]
788 for {
set i [
lindex $colRows 1]} {$i<[dimensions.size]+3} {
incr i} {
789 grid [
entry .dimensions.g${i}_dim] \
790 [ttk::combobox .dimensions.g${i}_type -state readonly \
791 -values {string value time}] \
792 [ttk::combobox .dimensions.g${i}_units \
793 -postcommand "dimFormatPopdown .dimensions.g${i}_units \[.dimensions.g${i}_type get\] {}"
797 foreach dim [dimensions.#keys] {
798 set d [dimensions.@elem $dim]
799 .dimensions.g${i}_dim delete 0 end
800 .dimensions.g${i}_dim insert 0 $dim
801 .dimensions.g${i}_type set [$d.type]
802 .dimensions.g${i}_units delete 0 end
803 .dimensions.g${i}_units insert 0 [$d.units]
811 array set timeFormatStrings {
814 "12/31/99" "%m/%d/%y"
815 "12/31/1999" "%m/%d/%Y"
816 "31/12/99" "%d/%m/%y"
817 "31/12/1999" "%d/%m/%Y"
818 "1999-12-31T13:37:46" "%Y-%m-%dT%H:%M:%S"
819 "12/31/1999 01:37 PM" "%m/%d/%Y %I:%M %p"
820 "12/31/99 01:37 PM" "%m/%d/%y %I:%M %p"
821 "12/31/1999 13:37 PM" "%m/%d/%Y %H:%M %p"
822 "12/31/99 13:37 PM" "%m/%d/%y %H:%M %p"
823 "Friday, December 31, 1999" "%A, %B %d, %Y"
824 "Dec 31, 99" "%b %d, %y"
825 "Dec 31, 1999" "%b %d, %Y"
826 "31. Dec. 1999" "%d. %b. %Y"
827 "December 31, 1999" "%B %d, %Y"
828 "31. December 1999" "%d. %B %Y"
829 "Fri, Dec 31, 99" "%a, %b %d, %y"
830 "Fri 31/Dec 99" "%a %d/%b %y"
831 "Fri, Dec 31, 1999" "%a, %b %d, %Y"
832 "Friday, December 31, 1999" "%A, %B %d, %Y"
834 "99-12-31" "%y-%m-%d"
835 "1999-12-31" "%Y-%m-%d"
839 "4th quarter 99" "%Qth quarter %y"
842 proc rewriteTimeComboBox {comboBox} {
843 global timeFormatStrings
844 if [
info exists timeFormatStrings([$comboBox get])] {
845 $comboBox set $timeFormatStrings([$comboBox get])
850 proc dimFormatPopdown {comboBox type onSelect} {
851 global timeFormatStrings
854 $comboBox configure -values {}
856 bind $comboBox <<ComboboxSelected>> $onSelect
859 $comboBox configure -values {}
860 bind $comboBox <<ComboboxSelected>> $onSelect
863 $comboBox configure -values [lsort [
array names timeFormatStrings]]
864 bind $comboBox <<ComboboxSelected>> "rewriteTimeComboBox $comboBox; $onSelect"
874 wm protocol . WM_DELETE_WINDOW exit
876 bind . <$meta-s> save
877 bind . <$meta-S> save
878 bind . <$meta-a> saveAs
879 bind . <$meta-A> saveAs
880 bind . <$meta-o> openFile
881 bind . <$meta-O> openFile
882 bind . <$meta-n> newSystem
883 bind . <$meta-N> newSystem
884 bind . <$meta-q> exit
885 bind . <$meta-Q> exit
886 bind . <$meta-y> "undo -1"
887 bind . <$meta-Y> "undo -1"
888 bind . <$meta-z> "undo 1"
889 bind . <$meta-Z> "undo 1"
890 bind . <$meta-x> {minsky.cut}
891 bind . <$meta-X> {minsky.cut}
892 bind . <$meta-c> {minsky.copy}
893 bind . <$meta-C> {minsky.copy}
894 bind . <$meta-v> {pasteAt}
895 bind . <$meta-V> {pasteAt}
896 bind . <$meta-g> {minsky.createGroup}
897 bind . <$meta-G> {minsky.createGroup}
900 ttk::notebook .tabs -padding 0
901 ttk::notebook::enableTraversal .tabs
904 bind .tabs <Right> {}
905 grid .tabs -column 0 -row 10 -sticky news
906 grid columnconfigure . 0 -weight 1
907 grid rowconfigure . 10 -weight 1
910 proc buttonBar {window okProc} {
911 frame $window.buttonBar
912 button $window.buttonBar.ok -text "OK" -command "okAction \{$okProc\} $window"
913 button $window.buttonBar.cancel -text "Cancel" -command "cancelWin $window"
914 pack $window.buttonBar.cancel $window.buttonBar.ok -side left
915 pack $window.buttonBar -side top
916 bind $window <Key-Return> "$window.buttonBar.ok invoke"
917 bind $window <Key-Escape> "$window.buttonBar.cancel invoke"
920 proc okAction {okProc window} {
921 if [
catch $okProc msg] {
922 tk_messageBox -icon error -parent $window -message $msg
929 proc cancelWin window {
934 proc ensureWindowVisible window {
935 if {![
winfo ismapped $window]} {
936 tkwait visibility $window
944 proc textEntryPopup {win init okproc} {
945 if {![
winfo exists $win]} {
948 pack $win.entry -side top -ipadx 50
953 $win.entry delete 0 end
954 $win.entry insert 0 $init
962 bind .tabs <<contextMenu>> {
963 set windows [.tabs tabs]
964 set idx [.tabs identify tab %x %y]
965 if {$idx<[llength $windows]} {
966 .wiring.context delete 0 end
967 .wiring.context add command -label Help -command "
968 help $helpTopics([lindex $windows $idx])"
969 tk_popup .wiring.context %X %Y
973 proc addTab {window label surface} {
974 image create cairoSurface rendered$window -surface $surface
976 global canvasHeight canvasWidth tabSurface helpTopics
977 label .$window.canvas -image rendered$window -height $canvasHeight -width $canvasWidth
978 .tabs add .$window -text $label -padding 0
979 set tabSurface($label) $surface
980 set helpTopics(.$window) tabs:$label
984 addTab wiring "Wiring" minsky.canvas
985 addTab equations "Equations" minsky.equationDisplay
986 pack .equations.canvas -fill both -expand 1
990 proc hoverMouseTab {tabId} {
991 set tab [
lindex [.tabs tabs] [.tabs index current]]
996 proc wrapHoverMouseTab {tabId op x y} {
997 after cancel hoverMouseTab $tabId
999 catch {$tabId.$op $x $y}
1000 after 3000 hoverMouseTab $tabId
1003 proc tabContext {x y X Y} {
1004 switch [
lindex [.tabs tabs] [.tabs index current]] {
1006 .variables.context delete 0 end
1007 set r [variableTab.rowY $y]
1008 switch [variableTab.clickType $x $y] {
1011 set varName [variableTab.getVarName $r]
1012 .variables.context add command -label "Remove $varName from tab" -command "variableTab.toggleVarDisplay $r; variableTab.requestRedraw"
1015 tk_popup .variables.context $X $Y
1018 .plts.context delete 0 end
1019 if [getPlotTabItemAt $x $y] {
1020 .plts.context add command -label "Remove plot from tab" -command "plotTab.togglePlotDisplay; plotTab.requestRedraw"
1022 tk_popup .plts.context $X $Y
1027 source $minskyHome/godley.tcl
1028 source $minskyHome/plots.tcl
1029 source $minskyHome/group.tcl
1030 source $minskyHome/wiring.tcl
1031 source $minskyHome/csvImport.tcl
1032 source $minskyHome/ravel.tcl
1033 source $minskyHome/variablePane.tcl
1035 pack .wiring.canvas -fill both -expand 1
1037 proc setScrollBars {} {
1038 switch [
lindex [.tabs tabs] [.tabs index current]] {
1040 set x0 [
expr (10000-[minsky.canvas.model.x])/20000.0]
1041 set y0 [
expr (10000-[minsky.canvas.model.y])/20000.0]
1042 .hscroll set $x0 [
expr $x0+[
winfo width .wiring.canvas]/20000.0]
1043 .vscroll set $y0 [
expr $y0+[
winfo height .wiring.canvas]/20000.0]
1046 if {[equationDisplay.width]>0} {
1047 set x0 [
expr [equationDisplay.offsx]/[equationDisplay.width]]
1048 .hscroll set $x0 [
expr $x0+[
winfo width .wiring.canvas]/[equationDisplay.width]]
1049 }
else {.hscroll set 0 1}
1050 if {[equationDisplay.height]>0} {
1051 set y0 [
expr [equationDisplay.offsx]/[equationDisplay.height]]
1052 .vscroll set $y0 [
expr $y0+[
winfo height .wiring.canvas]/[equationDisplay.height]]
1053 }
else {.vscroll set 0 1}
1056 set x0 [
expr (10000-[parameterTab.offsx])/20000.0]
1057 set y0 [
expr (10000-[parameterTab.offsy])/20000.0]
1058 .hscroll set $x0 [
expr $x0+[
winfo width .parameters.canvas]/20000.0]
1059 .vscroll set $y0 [
expr $y0+[
winfo height .parameters.canvas]/20000.0]
1062 set x0 [
expr (10000-[variableTab.offsx])/20000.0]
1063 set y0 [
expr (10000-[variableTab.offsy])/20000.0]
1064 .hscroll set $x0 [
expr $x0+[
winfo width .variables.canvas]/20000.0]
1065 .vscroll set $y0 [
expr $y0+[
winfo height .variables.canvas]/20000.0]
1068 set x0 [
expr (10000-[plotTab.offsx])/20000.0]
1069 set y0 [
expr (10000-[plotTab.offsy])/20000.0]
1070 .hscroll set $x0 [
expr $x0+[
winfo width .plts.canvas]/20000.0]
1071 .vscroll set $y0 [
expr $y0+[
winfo height .plts.canvas]/20000.0]
1074 set x0 [
expr (10000-[godleyTab.offsx])/20000.0]
1075 set y0 [
expr (10000-[godleyTab.offsy])/20000.0]
1076 .hscroll set $x0 [
expr $x0+[
winfo width .gdlys.canvas]/20000.0]
1077 .vscroll set $y0 [
expr $y0+[
winfo height .gdlys.canvas]/20000.0]
1082 bind .tabs <<NotebookTabChanged>> {setScrollBars}
1084 proc panCanvas {offsx offsy} {
1086 switch [
lindex [.tabs tabs] [.tabs index current]] {
1088 minsky.canvas.model.moveTo $offsx $offsy
1089 canvas.requestRedraw
1092 equationDisplay.offsx $offsx
1093 equationDisplay.offsy $offsy
1094 equationDisplay.requestRedraw
1097 parameterTab.offsx $offsx
1098 parameterTab.offsy $offsy
1099 parameterTab.requestRedraw
1102 variableTab.offsx $offsx
1103 variableTab.offsy $offsy
1104 variableTab.requestRedraw
1107 plotTab.offsx $offsx
1108 plotTab.offsy $offsy
1109 plotTab.requestRedraw
1112 godleyTab.offsx $offsx
1113 godleyTab.offsy $offsy
1114 godleyTab.requestRedraw
1121 ttk::sizegrip .sizegrip
1122 proc scrollCanvases {xyview args} {
1123 set win [
lindex [.tabs tabs] [.tabs index current]]
1124 set ww [
winfo width $win]
1125 set wh [
winfo height $win]
1128 set x [minsky.canvas.model.x]
1129 set y [minsky.canvas.model.y]
1132 set x1 [
expr 0.5*$w]
1133 set y1 [
expr 0.5*$h]
1136 set x [equationDisplay.offsx]
1137 set y [equationDisplay.offsy]
1140 set w [equationDisplay.width]
1141 set h [equationDisplay.height]
1144 set x [parameterTab.offsx]
1145 set y [parameterTab.offsy]
1148 set x1 [
expr 0.5*$w]
1149 set y1 [
expr 0.5*$h]
1152 set x [variableTab.offsx]
1153 set y [variableTab.offsy]
1156 set x1 [
expr 0.5*$w]
1157 set y1 [
expr 0.5*$h]
1160 set x [plotTab.offsx]
1161 set y [plotTab.offsy]
1164 set x1 [
expr 0.5*$w]
1165 set y1 [
expr 0.5*$h]
1168 set x [godleyTab.offsx]
1169 set y [godleyTab.offsy]
1172 set x1 [
expr 0.5*$w]
1173 set y1 [
expr 0.5*$h]
1176 switch [
lindex $args 0] {
1179 xview {
panCanvas [
expr $x1-$w*[
lindex $args 1]] $y}
1180 yview {
panCanvas $x [
expr $y1-$h*[
lindex $args 1]]}
1184 switch [
lindex $args 2] {
1185 units {
set incr [
expr [
lindex $args 1]*0.01]}
1186 # page corresponds to one full screens worth
1187 pages {
set incr [
expr [
lindex $args 1]*0.1]}
1196 scrollbar .vscroll -orient vertical -command "scrollCanvases yview"
1197 scrollbar .hscroll -orient horiz -command "scrollCanvases xview"
1201 bind . <Key-Prior> {scrollCanvases yview scroll -1 pages}
1202 bind . <Key-Next> {scrollCanvases yview scroll 1 pages}
1203 bind . <Key-Home> {scrollCanvases xview scroll -1 pages}
1204 bind . <Key-End> {scrollCanvases xview scroll 1 pages}
1207 if {[tk windowingsystem] == "aqua"} {
1208 set panIcon closedhand
1216 .equations.canvas configure -cursor $panIcon
1217 bind .equations.canvas <Button-1> {
1218 set panOffsX [expr %x-[equationDisplay.offsx]]
1219 set panOffsY [expr %y-[equationDisplay.offsy]]
1221 bind .equations.canvas <B1-Motion> {panCanvas [expr %x-$panOffsX] [expr %y-$panOffsY]}
1223 grid .sizegrip -row 999 -column 999
1224 grid .vscroll -column 999 -row 10 -rowspan 989 -sticky ns
1225 grid .hscroll -row 999 -column 0 -columnspan 999 -sticky ew
1227 image create photo zoomOutImg -file $minskyHome/icons/zoomOut.gif
1228 button .controls.zoomOut -image zoomOutImg -height 24 -width 37 \
1229 -command {zoom 0.91}
1230 tooltip .controls.zoomOut "Zoom Out"
1232 image create photo zoomInImg -file $minskyHome/icons/zoomIn.gif
1233 button .controls.zoomIn -image zoomInImg -height 24 -width 37 \
1235 tooltip .controls.zoomIn "Zoom In"
1237 image create photo zoomOrigImg -file $minskyHome/icons/zoomOrig.gif
1238 button .controls.zoomOrig -image zoomOrigImg -height 24 -width 37 \
1240 if {[minsky.model.zoomFactor]>0} {
1241 zoom [expr 1/[minsky.model.relZoom]]
1243 minsky.model.setZoom 1
1247 tooltip .controls.zoomOrig "Reset Zoom/Origin"
1249 image create photo zoomFitImg -file $minskyHome/icons/zoomFit.gif
1250 button .controls.zoomFit -image zoomFitImg -height 24 -width 37 \
1252 set cb [minsky.canvas.model.cBounds]
1253 set z1 [expr double([winfo width .wiring.canvas])/([lindex $cb 2]-[lindex $cb 0])]
1254 set z2 [expr double([winfo height .wiring.canvas])/([lindex $cb 3]-[lindex $cb 1])]
1255 if {$z2<$z1} {set z1 $z2}
1256 set x [expr -0.5*([lindex $cb 2]+[lindex $cb 0])]
1257 set y [expr -0.5*([lindex $cb 3]+[lindex $cb 1])]
1261 tooltip .controls.zoomFit "Zoom to fit"
1262 pack .controls.zoomOut .controls.zoomIn .controls.zoomOrig .controls.zoomFit -side left
1264 set delay [simulationDelay]
1272 .controls.run configure -text run
1274 .controls.run configure -image runButton
1280 .controls.run configure -text stop
1282 .controls.run configure -image stopButton
1290 global recordingReplay eventRecordR simTMax simTStart
1291 if {$recordingReplay} {
1292 if {[
gets $eventRecordR cmd]>=0} {
1301 if {[
catch minsky.step errMsg options] && [running]} {
runstop}
1302 if {[minsky.t0]>[t] || [minsky.tmax]<[t]} {
runstop}
1303 .controls.statusbar configure -text "t: [t] Δt: [
format %g [deltaT]]"
1304 if $preferences(godleyDisplay) redrawAllGodleyTables
1306 return -options $options $errMsg
1314 set d [expr int(pow(10,$delay/4.0))]
1326 global recordingReplay eventRecordR simLogging eventRecording
1327 if {$eventRecording} {
1328 set eventRecording 0
1333 if {$recordingReplay} {
1334 seek $eventRecordR 0 start
1336 canvas.requestRedraw
1342 set err [
catch minsky.reset result]
1343 .controls.statusbar configure -text "t: 0 Δt: 0"
1344 .controls.run configure -image runButton
1346 redrawAllGodleyTables
1347 return -code $err $result
1353 proc populateRecentFiles {} {
1354 global recentFiles preferences
1355 .menubar.file.recent delete 0 end
1356 if {[
llength $recentFiles]>$preferences(nRecentFiles)} {
1357 set recentFiles [
lreplace $recentFiles $preferences(nRecentFiles) end]
1359 foreach f $recentFiles {
1360 .menubar.file.recent insert 0 command -label "[
file tail $f]" \
1361 -command "openNamedFile \"[regsub -all {\\} $f /]\""
1369 global fname workDir preferences
1370 set ofname [
tk_getOpenFile -multiple 1 -filetypes {
1371 {Minsky {.mky}} {Ravel {.rvl}} {XML {.xml}} {All {.*}}} -initialdir $workDir]
1375 proc autoBackupName {} {
1379 proc openNamedFile {ofname} {
1380 global fname workDir preferences
1384 if {[
file exists [
autoBackupName]] && [
tk_messageBox -message "Auto save file exists, do you wish to load it" -type yesno]=="yes"} {
1385 eval minsky.load {[autoBackupName]}
1387 eval minsky.load {$ofname}
1396 minsky.multipleEquities $preferences(multipleEquities)
1397 setGodleyDisplayValue $preferences(godleyDisplay) $preferences(godleyDisplayStyle)
1401 .controls.simSpeed set [simulationDelay]
1404 canvas.requestRedraw
1406 event generate .wiring.canvas <Expose>
1413 proc insertFile {} {
1415 set fname [
tk_getOpenFile -multiple 1 -filetypes {
1416 {Minsky {.mky}} {Ravel {.rvl}} {XML {.xml}} {All {.*}}} -initialdir $workDir]
1417 eval insertGroupFromFile $fname
1423 set fname [
tk_getOpenFile -multiple 1 -filetypes {
1424 {Vensim {.mdl}} {All {.*}}} -initialdir $workDir]
1425 eval importVensim $fname
1426 minsky.model.autoLayout
1430 proc recentreCanvas {} {
1431 switch [
lindex [.tabs tabs] [.tabs index current]] {
1432 .wiring {canvas.recentre}
1434 equationDisplay.offsx 0
1435 equationDisplay.offsy 0
1436 equationDisplay.requestRedraw
1439 parameterTab.offsx 0
1440 parameterTab.offsy 0
1441 parameterTab.requestRedraw
1446 variableTab.requestRedraw
1451 plotTab.requestRedraw
1456 godleyTab.requestRedraw
1461 proc fileTypes {defaultExtension} {
1462 if {$defaultExtension==".rvl"} {
1463 return {{"Ravel" .rvl TEXT} {"Minsky" .mky TEXT} {"All Files" * TEXT}}
1465 return {{"Minsky" .mky TEXT} {"Ravel" .rvl TEXT} {"All Files" * TEXT}}
1470 global fname workDir
1471 set ext [minsky.model.defaultExtension]
1472 if {![
string length $fname]} {
1473 setFname [
tk_getSaveFile -defaultextension $ext -initialdir $workDir \
1475 if [
string length $fname] {
1476 set workDir [
file dirname $fname]
1477 eval minsky.save {$fname}
1483 global fname workDir
1484 set ext [minsky.model.defaultExtension]
1485 setFname [
tk_getSaveFile -defaultextension $ext -initialdir $workDir \
1487 if [
string length $fname]
save 1493 switch [
tk_messageBox -message "Save?" -type yesnocancel] {
1496 cancel {
return -level [
info level]}
1506 global fname progName
1509 wm title . "$progName: New System"
1514 proc toggleImplicitSolver {} {
1515 global implicitSolver
1516 implicit $implicitSolver
1520 proc invokeOKorCancel {window} {
1521 if [
string equal [
focus] "$window.cancel"] {
1522 $window.cancel invoke
1529 timeUnit "Time unit"
1530 stepMin "Min Step Size"
1531 stepMax "Max Step Size"
1532 nSteps "No. steps per iteration"
1534 tmax "Run until time"
1535 epsAbs "Absolute error"
1536 epsRel "Relative error"
1537 order "Solver order (1,2 or 4)"
1540 proc deiconifyRKDataForm {} {
1541 if {![
winfo exists .rkDataForm]} {
1542 global rkVarInput rkVars
1543 toplevel .rkDataForm
1544 wm resizable .rkDataForm 0 0
1548 grid [
label .rkDataForm.label$row -text "Simulation parameters"] -column 1 -columnspan 999 -pady 10
1551 foreach {var text} $rkVars {
1552 set rowdict($text) $row
1553 grid [
label .rkDataForm.label$row -text $text] -column 10 -row $row -sticky e
1554 grid [
entry .rkDataForm.text$row -width 20 -textvariable rkVarInput($var)] -column 20 -row $row -sticky ew
1557 grid [
label .rkDataForm.implicitlabel -text "Implicit solver"] -column 10 -row $row -sticky e
1558 grid [
checkbutton .rkDataForm.implicitcheck -variable implicitSolver -command toggleImplicitSolver] -column 20 -row $row -sticky ew
1560 set rkVarInput(initial_focus) ".rkDataForm.text$rowdict(Min Step Size)"
1561 frame .rkDataForm.buttonBar
1562 button .rkDataForm.buttonBar.ok -text OK -command {setRKparms; closeRKDataForm}
1563 button .rkDataForm.buttonBar.cancel -text cancel -command {closeRKDataForm}
1564 pack .rkDataForm.buttonBar.ok [
label .rkDataForm.buttonBar.spacer -width 2] .rkDataForm.buttonBar.cancel -side left -pady 10
1565 grid .rkDataForm.buttonBar -column 1 -row 999 -columnspan 999
1567 bind .rkDataForm <Key-Return> {invokeOKorCancel .rkDataForm.buttonBar}
1569 wm title .rkDataForm "Simulation parameters"
1571 bind .rkDataForm <F1> {help RungeKutta}
1573 set helpTopics(.rkDataForm) RungeKutta
1574 bind .rkDataForm <<contextMenu>> {helpContext %X %Y}
1580 proc closeRKDataForm {} {
1581 grab release .rkDataForm
1582 wm withdraw .rkDataForm
1585 proc setRKparms {} {
1586 global rkVars rkVarInput
1587 foreach {var text} $rkVars { $var $rkVarInput($var)}
1591 proc closePreferencesForm {} {
1592 destroy .preferencesForm
1595 proc setPreferenceParms {} {
1596 global preferencesVars preferences preferences_input
1598 foreach var [
array names preferences_input] {
1599 set preferences($var) $preferences_input($var)
1601 defaultFont $preferences(defaultFont)
1602 multipleEquities $preferences(multipleEquities)
1604 if {$preferences(focusFollowsMouse)} {
1605 tk_focusFollowsMouse 1608 set old [
bind all <Enter>]
1610 if {"%d" eq "NotifyAncestor" || "%d" eq "NotifyNonlinear" \
1611 || "%d" eq "NotifyInferior"} {
1616 bind all <Enter> "$old; $script"
1618 bind all <Enter> $script
1626 set helpTopics(.#menubar) Menu
1627 set helpTopics(.menubar.file) File
1628 set helpTopics(.menubar.edit) Edit
1629 set helpTopics(.menubar.ops) Insert
1630 set helpTopics(.menubar.options) Options
1631 set helpTopics(.controls.rec) RecReplayButtons
1632 set helpTopics(.controls.runmode) RecReplayButtons
1633 set helpTopics(.controls.run) RunButtons
1634 set helpTopics(.controls.reset) RunButtons
1635 set helpTopics(.controls.step) RunButtons
1636 set helpTopics(.controls.simSpeed) Speedslider
1637 set helpTopics(.controls.statusbar) SimTime
1638 set helpTopics(.controls.zoomOut) ZoomButtons
1639 set helpTopics(.controls.zoomIn) ZoomButtons
1640 set helpTopics(.controls.zoomOrig) ZoomButtons
1641 set helpTopics(.controls.zoomFit) ZoomButtons
1646 menu .contextHelp -tearoff 0
1647 foreach win [
array names helpTopics] {
1648 bind $win <<contextMenu>> {helpContext %X %Y}
1652 proc topLevelHelp {} {
1653 helpFor [
winfo pointerx .] [
winfo pointery .]
1657 proc helpContext {x y} {
1658 .contextHelp delete 0 end
1659 .contextHelp add command -label Help -command "helpFor $x $y"
1660 tk_popup .contextHelp $x $y
1664 proc helpFor {x y} {
1666 set win [
winfo containing $x $y]
1667 if {$win==".wiring.canvas"} {
1669 }
elseif [
info exists helpTopics($win)] {
1670 help $helpTopics($win)
1676 proc canvasHelp {} {
1679 if [getItemAt $x $y] {
1680 help [minsky.canvas.item.classType]
1681 }
elseif [getWireAt $x $y] {
1683 }
else {
help DesignCanvas}
1686 proc openURL {URL} {
1688 if {[tk windowingsystem]=="win32"} {
1690 }
elseif {$tcl_platform(os)=="Darwin"} {
1692 }
elseif [
catch {
exec xdg-open $URL &}] {
1694 foreach browser {firefox konqueror seamonkey opera} {
1695 set browserNotFound [
catch {
exec $browser $URL &}]
1696 if {!$browserNotFound} break
1698 if $browserNotFound {
1699 tk_messageBox -detail "Unable to find a working web browser,
1700 please consult $URL" -type ok -icon warning
1706 global minskyHome externalLabel
1709 if {$topic=="Introduction"} {
1710 set URL "file://$minskyHome/library/help/minsky.html"
1712 set URL "file://$minskyHome/library/help/minsky$externalLabel($topic)"
1717 proc aboutMinsky {} {
1718 tk_messageBox -message "
1719 Minsky [minskyVersion]\n
1720 Version used to save file [fileVersion]\n
1721 Tcl/Tk [
info tclversion]\n
1722 Ravel [ravelVersion]
1724 Minsky is FREE software, distributed under the
1725 GNU General Public License. It comes with ABSOLUTELY NO WARRANTY.
1726 See http://www.gnu.org/licenses/ for details
1728 Some icons from the Antü Plasma Suita are licensed under Creative
1729 Commons Attribution-Share Alike 3.0 Unported license
1730 (https://creativecommons.org/licenses/by-sa/3.0/deed.en).
1732 Ravel is copyright Ravelation Pty Ltd. A separate license needs to
1733 be purchased to use Ravel. See https://ravelation.hpcoders.com.au
1735 Thanks to following Minsky Unicorn sponsors:
1742 proc deleteSubsidiaryTopLevels {} {
1745 canvas.defaultRotation 0
1746 set globals(godley_tables) {}
1748 foreach w [
info commands .godley*] {
destroy $w}
1749 foreach w [
info commands .plot*] {
destroy $w}
1750 foreach image [
image names] {
1751 if [regexp ".plot.*|godleyImage.*|groupImage.*|varImage.*|opImage.*|plot_image.*" $image] {
1760 switch [
tk_messageBox -message "Save before exiting?" -type yesnocancel] {
1763 cancel {
return -level [
info level]}
1770 global rcfile workDir backgroundColour preferences recentFiles
1772 set rc [open $rcfile w]
1773 puts $rc "set workDir $workDir"
1774 puts $rc "set canvasWidth [
winfo width .wiring.canvas]"
1775 puts $rc "set canvasHeight [
winfo height .wiring.canvas]"
1776 puts $rc "set backgroundColour $backgroundColour"
1777 foreach p [
array names preferences] {
1778 puts $rc "set preferences($p) \{$preferences($p)\}"
1780 puts $rc {minsky.defaultFont $preferences(defaultFont)}
1781 puts $rc "set recentFiles \{$recentFiles\}"
1789 proc setFname {name} {
1790 global fname workDir recentFiles preferences progName
1791 if [
string length $name] {
1793 set workDir [
file dirname $name]
1794 if {[lsearch $recentFiles $fname]==-1} {
1796 if {[
llength $recentFiles]>=$preferences(nRecentFiles)} {
1797 set recentFiles [
lreplace $recentFiles 0 0]
1799 lappend recentFiles $fname
1804 if {[regexp "\}$" $fname] && ![regexp "\}$" $workDir]} {
1805 set workDir "$workDir\}"
1807 catch {
wm title . "$progName: $fname"}
1812 set getters {wire op constant integral data var plot godley group switchItem item items wires}
1813 foreach i $getters {
1814 foreach j [
info commands $i.*] {
rename $j {}}
1817 rename unknown ecolab_unknown
1818 proc unknown {procname args} {
1821 if [regexp ^wiringGroup\. $procname] {
1823 eval [regsub ^wiringGroup $procname minsky] $args
1824 }
elseif [regexp ^([
join $getters |])\. $procname] {
1825 eval wiringGroup.$procname $args
1827 eval ecolab_unknown $procname $args
1835 if [
string match "*.mdl" $argv(1)] {
1836 catch {
eval importVensim $argv(1)}
1837 minsky.model.autoLayout
1839 .controls.zoomFit invoke
1840 }
elseif {![
string match "*.tcl" $argv(1)]} {
1854 proc addEvent {event window button height state width x y delta keysym subwindow} {
1855 global eventRecord eventRecording
1856 if {$eventRecording && [
info exists eventRecord] && [
llength [
file channels $eventRecord]]} {
1857 set rec "event generate $window $event "
1858 foreach option {button height state width x y delta keysym} {
1860 if {($event=="<Key>" || $event=="<KeyRelease>") && $option=="delta"} continue
1861 append rec [
ifDef $option]
1863 puts $eventRecord $rec
1867 proc startRecording {filename} {
1868 if {[
string length $filename]>0} {
1869 minsky.startRecording $filename
1874 proc stopRecording {} {
1875 minsky.stopRecording
1878 proc toggleRecording {} {
1879 global eventRecording workDir
1880 if $eventRecording {
1881 startRecording [
tk_getSaveFile -filetypes {{"TCL scripts" .tcl TEXT} {"All Files" * }}\
1882 -defaultextension .tcl -initialdir $workDir]
1888 proc checkRecordingVersion ver {
1889 if {$ver!=[minskyVersion]} {
1890 tk_messageBox -icon warning -message "Recording version $ver differs from current Minsky version [minskyVersion]" -detail "Recording may not replay correctly"
1895 set recordingReplay 0
1898 global recordingReplay eventRecordR workDir eventRecording
1900 if {$recordingReplay} {
1902 set fname [
tk_getOpenFile -filetypes {{"TCL scripts" .tcl TEXT} {"All Files" * }} \
1903 -defaultextension .tcl -initialdir $workDir]
1904 if {[
string length $fname]>0} {
1905 set eventRecordR [
eval open {$fname} r]
1910 set recordingReplay 0
1919 if {[
llength [
info commands afterMinskyStarted]]>0} {
1923 setGodleyDisplayValue $preferences(godleyDisplay) $preferences(godleyDisplayStyle)
1924 disableEventProcessing