Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Writing Tcl/Tk plugins and extensions for VMD

It's always a good idea to consult the main Tcl/Tk web site, the Tcl Style Guide, and the Tcl Wiki for tips on writing good Tcl/Tk scripts and packages.

Tcl Packages

VMD doesn't do anything particularly special in support of Tcl packages other than to provide hooks by which they can be registered in the VMD "Extensions" menu and subdirectories in the VMD installation directory which are automatically scanned for plugins when VMD starts up, by virtue of adding these directories to the Tcl auto_path. Platform-independent script extensions are stored in [file join $env(VMDDIR) plugins noarch tcl]. Tcl extensions implemented by compiled C/C++ code are stored in [file join $env(VMDDIR) plugins [vmdinfo arch] tcl]. Tcl packages are loaded via commands such as package require mypackage.

Tcl packages which implement a Tk-based GUI are registered in the VMD "Extensions" menu with the "menu tk" command, as in menu tk register "MyToolName" mytoolproc. Currently, all of the Tcl package plugins shipped with VMD by default are added to the "Extensions" menu with a sequence of hard-coded package require and menu tk register commands and associated exception handling code, place in vmdinit.tcl which is executed at VMD startup time.

Since there can potentially be a huge number of plugins loaded into VMD at any one time, it is critical that Tcl/Tk-based VMD plugins use their namespaces to avoid name collisions with variables and procs used by other plugins.

Text Viewer example Tcl/Tk VMD extension package

The example below illustrates a relatively simple Tcl/Tk package which is added to the VMD "Extensions" menu with the command vmd_install_extension, which takes 3 main arguments; the package name, the Tk menu callback proc, and the VMD "Extensions" menu listing for the plugin/extension to be listed under. The package name parameter is the same as one would use with the Tcl package require command. The Tk callback proc is normally a proc in the global namespace which initializes the plugin if it hasn't been done already, and returns a valid Tk window handle to be registered in the VMD "Extensions" menu. The "Extensions" menu entry text determines the top and subsequent sub-menu names to be used to categorize the plugin, separated by forward slash characters. While there are no rules governing the creation of new plugin categories, it is best to use one of the existing extension categories whenever possible.

    vmd_install_extension textview textview_tk "Data/Text Viewer"

The package is written using Tcl namespaces to prevent proc and variable name collisions, except for the textview_tk proc which is in the global namespace, to allow it to be registered easily with the call to vmd_install_extension as described above.

##
## Text Viewer 1.0
##
## A script to view textual molecule info via a simple Tk interface
##
## Author: John E. Stone
##
## Id: textview.tcl,v 1.3 2006/02/01 21:32:32 johns Exp
##

## Tell Tcl that we're a package and any dependencies we may have
package provide textview 1.0

namespace eval TextView:: {
  namespace export textview

  # window handles
  variable w                                          ;# handle to main window
  variable textfile   "untitled.txt"                  ;# text file
}

#
# Create the window and initialize data structures
#
proc TextView::textview {} {
  variable w
  variable textfile

  # If already initialized, just turn on
  if { [winfo exists .textview] } {
    wm deiconify $w
    return
  }

  set w [toplevel ".textview"]
  wm title $w "Text Viewer"
  wm resizable $w 0 0

  ##
  ## make the menu bar
  ##
  frame $w.menubar -relief raised -bd 2 ;# frame for menubar
  pack $w.menubar -padx 1 -fill x

  menubutton $w.menubar.help -text Help -underline 0 -menu $w.menubar.help.menu
  menubutton $w.menubar.file -text File -underline 0 -menu $w.menubar.file.menu

  ##
  ## help menu
  ##
  menu $w.menubar.help.menu -tearoff no
  $w.menubar.help.menu add command -label "Help..." -command "vmd_open_url [string trimright [vmdinfo www] /]/plugins/textview"
  # XXX - set menubutton width to avoid truncation in OS X
  $w.menubar.help config -width 5

  menu $w.menubar.file.menu -tearoff no
  $w.menubar.file.menu add command -label "New" -command  TextView::newfile
  $w.menubar.file.menu add command -label "Open" -command TextView::loadfile
  $w.menubar.file.menu add command -label "Save" -command  TextView::savefile
  $w.menubar.file.menu add command -label "Save As" -command  TextView::saveasfile
  $w.menubar.file config -width 5
  pack $w.menubar.file -side left
  pack $w.menubar.help -side right


  ##
  ## main window area
  ## 
  frame $w.txt
  label $w.txt.label -width 80 -relief sunken -bg White -textvariable TextView::textfile
  text $w.txt.text -bg White -bd 2 -yscrollcommand "$::TextView::w.txt.vscr set"
  scrollbar $w.txt.vscr -command "$::TextView::w.txt.text yview"
  pack $w.txt.label 
  pack $w.txt.text $w.txt.vscr -side left -fill y

  pack $w.menubar $w.txt
}

proc TextView::newfile { } {
  variable w
  variable textfile

  $w.txt.text delete 1.0 {end - 1c}
  set textfile "untitled.txt"
}

proc TextView::loadfile { } {
  variable w
  variable textfile

  newfile
   
  set file_types {
    {"Tcl Files" { .tcl .TCL .tk .TK} }
    {"Text Files" { .txt .TXT} }
    {"All Files" * }
  }

  set textfile [tk_getOpenFile -filetypes $file_types \
                -initialdir pwd -initialfile "$TextView::textfile" \
                -defaultextension .txt]

  set rc [ catch { set fd [open $textfile "r"] } ]
  if { $rc == 1} {
    set textfile "untitled.txt"
    return
  }

  set line ""
  while {[gets $fd line] != -1} {
    set dtext "$line\n"
    $w.txt.text insert end $dtext
  } 

  close $fd
}

proc TextView::savefile { } {
  variable w
  variable textfile

  set rc [ catch { set fd [open $textfile "w"] } ]
  if { $rc == 1} {
    puts "failed to open file $textfile"
    return
  }

  puts $fd [$w.txt.text get 1.0 {end -1c}]

  close $fd
}

proc TextView::saveasfile { } {
  variable w
  variable textfile

  set file_types {
    {"Tcl Files" { .tcl .TCL .tk .TK} }
    {"Text Files" { .txt .TXT} }
    {"All Files" * }
  }

  set textfile [tk_getSaveFile -filetypes $file_types \
                -initialdir pwd -initialfile $TextView::textfile \
                -defaultextension .txt]

  set rc [ catch { set fd [open $textfile "w"] } ]
  if { $rc == 1} {
    puts "failed to open file $textfile"
    return
  }

  puts $fd [$w.txt.text get 1.0 {end -1c}]

  close $fd
}

proc textview_tk {} {
  TextView::textview
  return $TextView::w
}

Id:
plg_tcltk.dox,v 1.6 2008/03/31 19:40:26 johns Exp


Generated on Thu Nov 7 03:10:06 2024 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002