1 | # ---------------------------------------------------------------------- |
---|
2 | # COMPONENT: molvisviewer - view a molecule in 3D |
---|
3 | # |
---|
4 | # This widget brings up a 3D representation of a molecule |
---|
5 | # It connects to the Molvis server running on a rendering farm, |
---|
6 | # transmits data, and displays the results. |
---|
7 | # ====================================================================== |
---|
8 | # AUTHOR: Michael McLennan, Purdue University |
---|
9 | # Copyright (c) 2004-2005 Purdue Research Foundation |
---|
10 | # |
---|
11 | # See the file "license.terms" for information on usage and |
---|
12 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
13 | # ====================================================================== |
---|
14 | package require Itk |
---|
15 | package require BLT |
---|
16 | package require Img |
---|
17 | |
---|
18 | option add *MolvisViewer.width 4i widgetDefault |
---|
19 | option add *MolvisViewer.height 4i widgetDefault |
---|
20 | option add *MolvisViewer.foreground black widgetDefault |
---|
21 | option add *MolvisViewer.controlBackground gray widgetDefault |
---|
22 | option add *MolvisViewer.controlDarkBackground #999999 widgetDefault |
---|
23 | option add *MolvisViewer.font -*-helvetica-medium-r-normal-*-*-120-* widgetDefault |
---|
24 | |
---|
25 | itcl::class Rappture::MolvisViewer { |
---|
26 | inherit itk::Widget |
---|
27 | itk_option define -device device Device "" |
---|
28 | |
---|
29 | constructor {hostlist args} { # defined below } |
---|
30 | destructor { # defined below } |
---|
31 | |
---|
32 | public method emblems {option} |
---|
33 | |
---|
34 | public method connect {{hostlist ""}} |
---|
35 | public method disconnect {} |
---|
36 | public method isconnected {} |
---|
37 | |
---|
38 | protected method _send {args} |
---|
39 | protected method _receive {} |
---|
40 | protected method _receive_image {size} |
---|
41 | protected method _rebuild {} |
---|
42 | protected method _zoom {option} |
---|
43 | protected method _move {option x y} |
---|
44 | protected method _speed {option} |
---|
45 | protected method _serverDown {} |
---|
46 | |
---|
47 | private variable _dispatcher "" ;# dispatcher for !events |
---|
48 | private variable _sid "" ;# socket connection to nanovis server |
---|
49 | private variable _image ;# image displayed in plotting area |
---|
50 | |
---|
51 | private variable _click ;# info used for _move operations |
---|
52 | } |
---|
53 | |
---|
54 | itk::usual MolvisViewer { |
---|
55 | keep -background -foreground -cursor -font |
---|
56 | } |
---|
57 | |
---|
58 | # ---------------------------------------------------------------------- |
---|
59 | # CONSTRUCTOR |
---|
60 | # ---------------------------------------------------------------------- |
---|
61 | itcl::body Rappture::MolvisViewer::constructor {hostlist args} { |
---|
62 | #puts stderr "MolvisViewer::_constructor()" |
---|
63 | Rappture::dispatcher _dispatcher |
---|
64 | $_dispatcher register !serverDown |
---|
65 | $_dispatcher dispatch $this !serverDown "[itcl::code $this _serverDown]; list" |
---|
66 | |
---|
67 | # |
---|
68 | # Set up the widgets in the main body |
---|
69 | # |
---|
70 | option add hull.width hull.height |
---|
71 | pack propagate $itk_component(hull) no |
---|
72 | |
---|
73 | itk_component add bottom_controls { |
---|
74 | frame $itk_interior.b_cntls |
---|
75 | } { |
---|
76 | usual |
---|
77 | rename -background -controlbackground controlBackground Background |
---|
78 | } |
---|
79 | pack $itk_component(bottom_controls) -side bottom -fill y |
---|
80 | |
---|
81 | itk_component add mrewind { |
---|
82 | button $itk_component(bottom_controls).mrewind \ |
---|
83 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
84 | -text "|<" \ |
---|
85 | -command [itcl::code $this _send rewind] |
---|
86 | } { |
---|
87 | usual |
---|
88 | ignore -borderwidth |
---|
89 | rename -highlightbackground -controlbackground controlBackground Background |
---|
90 | } |
---|
91 | pack $itk_component(mrewind) -padx 4 -pady 4 -side left |
---|
92 | |
---|
93 | itk_component add mbackward { |
---|
94 | button $itk_component(bottom_controls).mbackward \ |
---|
95 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
96 | -text "<" \ |
---|
97 | -command [itcl::code $this _send backward] |
---|
98 | } { |
---|
99 | usual |
---|
100 | ignore -borderwidth |
---|
101 | rename -highlightbackground -controlbackground controlBackground Background |
---|
102 | } |
---|
103 | pack $itk_component(mbackward) -padx 4 -pady 4 -side left |
---|
104 | |
---|
105 | itk_component add mstop { |
---|
106 | button $itk_component(bottom_controls).mstop \ |
---|
107 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
108 | -text "Stop" \ |
---|
109 | -command [itcl::code $this _send mstop] |
---|
110 | } { |
---|
111 | usual |
---|
112 | ignore -borderwidth |
---|
113 | rename -highlightbackground -controlbackground controlBackground Background |
---|
114 | } |
---|
115 | pack $itk_component(mstop) -padx 4 -pady 4 -side left |
---|
116 | |
---|
117 | itk_component add mplay { |
---|
118 | button $itk_component(bottom_controls).mplay \ |
---|
119 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
120 | -text "Play" \ |
---|
121 | -command [itcl::code $this _send mplay] |
---|
122 | } { |
---|
123 | usual |
---|
124 | ignore -borderwidth |
---|
125 | rename -highlightbackground -controlbackground controlBackground Background |
---|
126 | } |
---|
127 | pack $itk_component(mplay) -padx 4 -pady 4 -side left |
---|
128 | |
---|
129 | itk_component add mforward { |
---|
130 | button $itk_component(bottom_controls).mforward \ |
---|
131 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
132 | -text ">" \ |
---|
133 | -command [itcl::code $this _send forward] |
---|
134 | } { |
---|
135 | usual |
---|
136 | ignore -borderwidth |
---|
137 | rename -highlightbackground -controlbackground controlBackground Background |
---|
138 | } |
---|
139 | pack $itk_component(mforward) -padx 4 -pady 4 -side left |
---|
140 | |
---|
141 | itk_component add mend { |
---|
142 | button $itk_component(bottom_controls).mend \ |
---|
143 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
144 | -text ">|" \ |
---|
145 | -command [itcl::code $this _send ending] |
---|
146 | } { |
---|
147 | usual |
---|
148 | ignore -borderwidth |
---|
149 | rename -highlightbackground -controlbackground controlBackground Background |
---|
150 | } |
---|
151 | pack $itk_component(mend) -padx 4 -pady 4 -side left |
---|
152 | |
---|
153 | itk_component add mclear { |
---|
154 | button $itk_component(bottom_controls).mclear \ |
---|
155 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
156 | -text "MClear" \ |
---|
157 | -command [itcl::code $this _send mclear] |
---|
158 | } { |
---|
159 | usual |
---|
160 | ignore -borderwidth |
---|
161 | rename -highlightbackground -controlbackground controlBackground Background |
---|
162 | } |
---|
163 | pack $itk_component(mclear) -padx 4 -pady 4 -side left |
---|
164 | |
---|
165 | itk_component add speed { |
---|
166 | ::scale $itk_component(bottom_controls).speed \ |
---|
167 | -borderwidth 1 \ |
---|
168 | -from 100 -to 1000 -orient horizontal \ |
---|
169 | -command [itcl::code $this _speed] |
---|
170 | } { |
---|
171 | usual |
---|
172 | ignore -borderwidth |
---|
173 | rename -highlightbackground -controlbackground controlBackground Background |
---|
174 | } |
---|
175 | pack $itk_component(speed) -padx 4 -pady 4 -side right |
---|
176 | |
---|
177 | itk_component add left_controls { |
---|
178 | frame $itk_interior.l_cntls |
---|
179 | } { |
---|
180 | usual |
---|
181 | rename -background -controlbackground controlBackground Background |
---|
182 | } |
---|
183 | pack $itk_component(left_controls) -side left -fill y |
---|
184 | |
---|
185 | itk_component add show_ball_and_stick { |
---|
186 | button $itk_component(left_controls).sbs \ |
---|
187 | -borderwidth 2 -padx 0 -pady 0 \ |
---|
188 | -image [Rappture::icon ballnstick] \ |
---|
189 | -command [itcl::code $this _send ball_and_stick] |
---|
190 | } { |
---|
191 | usual |
---|
192 | ignore -borderwidth |
---|
193 | rename -highlightbackground -controlbackground controlBackground Background |
---|
194 | } |
---|
195 | pack $itk_component(show_ball_and_stick) -padx 4 -pady 4 |
---|
196 | |
---|
197 | itk_component add show_spheres { |
---|
198 | button $itk_component(left_controls).ss \ |
---|
199 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
200 | -image [Rappture::icon spheres] \ |
---|
201 | -command [itcl::code $this _send spheres] |
---|
202 | } { |
---|
203 | usual |
---|
204 | ignore -borderwidth |
---|
205 | rename -highlightbackground -controlbackground controlBackground Background |
---|
206 | } |
---|
207 | pack $itk_component(show_spheres) -padx 4 -pady 4 |
---|
208 | |
---|
209 | itk_component add show_lines { |
---|
210 | button $itk_component(left_controls).sl \ |
---|
211 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
212 | -image [Rappture::icon lines] \ |
---|
213 | -command [itcl::code $this _send lines] |
---|
214 | } { |
---|
215 | usual |
---|
216 | ignore -borderwidth |
---|
217 | rename -highlightbackground -controlbackground controlBackground Background |
---|
218 | } |
---|
219 | pack $itk_component(show_lines) -padx 4 -pady 4 |
---|
220 | |
---|
221 | itk_component add controls { |
---|
222 | frame $itk_interior.cntls |
---|
223 | } { |
---|
224 | usual |
---|
225 | rename -background -controlbackground controlBackground Background |
---|
226 | } |
---|
227 | pack $itk_component(controls) -side right -fill y |
---|
228 | |
---|
229 | itk_component add reset { |
---|
230 | button $itk_component(controls).reset \ |
---|
231 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
232 | -bitmap [Rappture::icon reset] \ |
---|
233 | -command [itcl::code $this _send reset] |
---|
234 | } { |
---|
235 | usual |
---|
236 | ignore -borderwidth |
---|
237 | rename -highlightbackground -controlbackground controlBackground Background |
---|
238 | } |
---|
239 | pack $itk_component(reset) -padx 4 -pady 4 |
---|
240 | Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level" |
---|
241 | |
---|
242 | itk_component add zoomin { |
---|
243 | button $itk_component(controls).zin \ |
---|
244 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
245 | -bitmap [Rappture::icon zoomin] \ |
---|
246 | -command [itcl::code $this _zoom in] |
---|
247 | } { |
---|
248 | usual |
---|
249 | ignore -borderwidth |
---|
250 | rename -highlightbackground -controlbackground controlBackground Background |
---|
251 | } |
---|
252 | pack $itk_component(zoomin) -padx 4 -pady 4 |
---|
253 | Rappture::Tooltip::for $itk_component(zoomin) "Zoom in" |
---|
254 | |
---|
255 | itk_component add zoomout { |
---|
256 | button $itk_component(controls).zout \ |
---|
257 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
258 | -bitmap [Rappture::icon zoomout] \ |
---|
259 | -command [itcl::code $this _zoom out] |
---|
260 | } { |
---|
261 | usual |
---|
262 | ignore -borderwidth |
---|
263 | rename -highlightbackground -controlbackground controlBackground Background |
---|
264 | } |
---|
265 | pack $itk_component(zoomout) -padx 4 -pady 4 |
---|
266 | Rappture::Tooltip::for $itk_component(zoomout) "Zoom out" |
---|
267 | |
---|
268 | itk_component add labels { |
---|
269 | label $itk_component(controls).labels \ |
---|
270 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
271 | -bitmap [Rappture::icon atoms] |
---|
272 | } { |
---|
273 | usual |
---|
274 | ignore -borderwidth |
---|
275 | rename -highlightbackground -controlbackground controlBackground Background |
---|
276 | } |
---|
277 | pack $itk_component(labels) -padx 4 -pady 8 -ipadx 1 -ipady 1 |
---|
278 | Rappture::Tooltip::for $itk_component(labels) "Show/hide the labels on atoms" |
---|
279 | bind $itk_component(labels) <ButtonPress> \ |
---|
280 | [itcl::code $this emblems toggle] |
---|
281 | |
---|
282 | itk_component add rock { |
---|
283 | button $itk_component(controls).rock \ |
---|
284 | -borderwidth 1 -padx 1 -pady 1 \ |
---|
285 | -text "R" \ |
---|
286 | -command [itcl::code $this _send rock] |
---|
287 | } { |
---|
288 | usual |
---|
289 | ignore -borderwidth |
---|
290 | rename -highlightbackground -controlbackground controlBackground Background |
---|
291 | } |
---|
292 | pack $itk_component(rock) -padx 4 -pady 8 -ipadx 1 -ipady 1 |
---|
293 | |
---|
294 | # |
---|
295 | # RENDERING AREA |
---|
296 | # |
---|
297 | |
---|
298 | itk_component add area { |
---|
299 | frame $itk_interior.area |
---|
300 | } |
---|
301 | pack $itk_component(area) -expand yes -fill both |
---|
302 | |
---|
303 | set _image(plot) [image create photo] |
---|
304 | |
---|
305 | itk_component add 3dview { |
---|
306 | label $itk_component(area).vol -image $_image(plot) \ |
---|
307 | -highlightthickness 0 |
---|
308 | } { |
---|
309 | usual |
---|
310 | ignore -highlightthickness |
---|
311 | } |
---|
312 | pack $itk_component(3dview) -expand yes -fill both |
---|
313 | |
---|
314 | # set up bindings for rotation |
---|
315 | bind $itk_component(3dview) <ButtonPress> \ |
---|
316 | [itcl::code $this _move click %x %y] |
---|
317 | bind $itk_component(3dview) <B1-Motion> \ |
---|
318 | [itcl::code $this _move drag %x %y] |
---|
319 | bind $itk_component(3dview) <ButtonRelease> \ |
---|
320 | [itcl::code $this _move release %x %y] |
---|
321 | bind $itk_component(3dview) <Configure> \ |
---|
322 | [itcl::code $this _send screen %w %h] |
---|
323 | |
---|
324 | connect $hostlist |
---|
325 | |
---|
326 | $_dispatcher register !rebuild |
---|
327 | $_dispatcher dispatch $this !rebuild "[itcl::code $this _rebuild]; list" |
---|
328 | |
---|
329 | eval itk_initialize $args |
---|
330 | } |
---|
331 | |
---|
332 | # ---------------------------------------------------------------------- |
---|
333 | # DESTRUCTOR |
---|
334 | # ---------------------------------------------------------------------- |
---|
335 | itcl::body Rappture::MolvisViewer::destructor {} { |
---|
336 | # puts stderr "MolvisViewer::destructor()" |
---|
337 | after cancel [itcl::code $this _rebuild] |
---|
338 | image delete $_image(plot) |
---|
339 | } |
---|
340 | |
---|
341 | # ---------------------------------------------------------------------- |
---|
342 | # USAGE: connect ?<host:port>,<host:port>...? |
---|
343 | # |
---|
344 | # Clients use this method to establish a connection to a new |
---|
345 | # server, or to reestablish a connection to the previous server. |
---|
346 | # Any existing connection is automatically closed. |
---|
347 | # ---------------------------------------------------------------------- |
---|
348 | itcl::body Rappture::MolvisViewer::connect {{hostlist ""}} { |
---|
349 | # puts stderr "MolvisViewer::connect()" |
---|
350 | |
---|
351 | if ([isconnected]) { |
---|
352 | disconnect |
---|
353 | } |
---|
354 | |
---|
355 | if {"" == $hostlist} { |
---|
356 | return 0 |
---|
357 | } |
---|
358 | |
---|
359 | blt::busy hold $itk_component(hull); |
---|
360 | |
---|
361 | update idletasks |
---|
362 | |
---|
363 | # |
---|
364 | # Connect to the hubvis server. |
---|
365 | # If it's too busy, that server may |
---|
366 | # forward us to another. |
---|
367 | # |
---|
368 | |
---|
369 | set hosts [split $hostlist ,] |
---|
370 | |
---|
371 | foreach {hostname port} [split [lindex $hosts 0] :] break |
---|
372 | |
---|
373 | set hosts [lrange $hosts 1 end] |
---|
374 | |
---|
375 | while {1} { |
---|
376 | if {[catch {socket $hostname $port} sid]} { |
---|
377 | if {[llength $hosts] == 0} { |
---|
378 | blt::busy release $itk_component(hull) |
---|
379 | return 0 |
---|
380 | } |
---|
381 | foreach {hostname port} [split [lindex $hosts 0] :] break |
---|
382 | set hosts [lrange $hosts 1 end] |
---|
383 | continue |
---|
384 | } |
---|
385 | fconfigure $sid -translation binary -encoding binary -buffering line |
---|
386 | puts -nonewline $sid "AB01" |
---|
387 | flush $sid |
---|
388 | |
---|
389 | # read back a reconnection order |
---|
390 | set data [read $sid 4] |
---|
391 | |
---|
392 | if {[binary scan $data cccc b1 b2 b3 b4] != 4} { |
---|
393 | error "couldn't read redirection request" |
---|
394 | } |
---|
395 | |
---|
396 | set hostname [format "%u.%u.%u.%u" \ |
---|
397 | [expr {$b1 & 0xff}] \ |
---|
398 | [expr {$b2 & 0xff}] \ |
---|
399 | [expr {$b3 & 0xff}] \ |
---|
400 | [expr {$b4 & 0xff}]] |
---|
401 | |
---|
402 | if {[string equal $hostname "0.0.0.0"]} { |
---|
403 | fileevent $sid readable [itcl::code $this _receive] |
---|
404 | set _sid $sid |
---|
405 | blt::busy release $itk_component(hull) |
---|
406 | return 1 |
---|
407 | } |
---|
408 | } |
---|
409 | |
---|
410 | blt::busy release $itk_component(hull) |
---|
411 | |
---|
412 | return 0 |
---|
413 | } |
---|
414 | |
---|
415 | # ---------------------------------------------------------------------- |
---|
416 | # USAGE: disconnect |
---|
417 | # |
---|
418 | # Clients use this method to disconnect from the current rendering |
---|
419 | # server. |
---|
420 | # ---------------------------------------------------------------------- |
---|
421 | itcl::body Rappture::MolvisViewer::disconnect {} { |
---|
422 | #puts stderr "MolvisViewer::disconnect()" |
---|
423 | |
---|
424 | if {"" != $_sid} { |
---|
425 | catch { |
---|
426 | close $_sid |
---|
427 | } |
---|
428 | set _sid "" |
---|
429 | } |
---|
430 | } |
---|
431 | |
---|
432 | # ---------------------------------------------------------------------- |
---|
433 | # USAGE: isconnected |
---|
434 | # |
---|
435 | # Clients use this method to see if we are currently connected to |
---|
436 | # a server. |
---|
437 | # ---------------------------------------------------------------------- |
---|
438 | itcl::body Rappture::MolvisViewer::isconnected {} { |
---|
439 | #puts stderr "MolvisViewer::isconnected()" |
---|
440 | return [expr {"" != $_sid}] |
---|
441 | } |
---|
442 | |
---|
443 | # ---------------------------------------------------------------------- |
---|
444 | # USAGE: _send <arg> <arg> ... |
---|
445 | # |
---|
446 | # Used internally to send commands off to the rendering server. |
---|
447 | # ---------------------------------------------------------------------- |
---|
448 | itcl::body Rappture::MolvisViewer::_send {args} { |
---|
449 | # puts stderr "MolvisViewer::_send() $args" |
---|
450 | if {"" == $_sid} { |
---|
451 | $_dispatcher cancel !serverDown |
---|
452 | set x [expr {[winfo rootx $itk_component(area)]+10}] |
---|
453 | set y [expr {[winfo rooty $itk_component(area)]+10}] |
---|
454 | Rappture::Tooltip::cue @$x,$y "Connecting..." |
---|
455 | |
---|
456 | if {[catch {connect} ok] == 0 && $ok} { |
---|
457 | set w [winfo width $itk_component(3dview)] |
---|
458 | set h [winfo height $itk_component(3dview)] |
---|
459 | puts $_sid "screen $w $h" |
---|
460 | after idle [itcl::code $this _rebuild] |
---|
461 | Rappture::Tooltip::cue hide |
---|
462 | return |
---|
463 | } |
---|
464 | |
---|
465 | Rappture::Tooltip::cue @$x,$y "Can't connect to visualization server. This may be a network problem. Wait a few moments and try resetting the view." |
---|
466 | |
---|
467 | return |
---|
468 | } |
---|
469 | |
---|
470 | if {"" != $_sid} { |
---|
471 | puts $_sid $args |
---|
472 | } |
---|
473 | } |
---|
474 | |
---|
475 | # ---------------------------------------------------------------------- |
---|
476 | # USAGE: _receive |
---|
477 | # |
---|
478 | # Invoked automatically whenever a command is received from the |
---|
479 | # rendering server. Reads the incoming command and executes it in |
---|
480 | # a safe interpreter to handle the action. |
---|
481 | # ---------------------------------------------------------------------- |
---|
482 | itcl::body Rappture::MolvisViewer::_receive {} { |
---|
483 | #puts stderr "MolvisViewer::_receive()" |
---|
484 | if {"" != $_sid} { |
---|
485 | if {[gets $_sid line] < 0} { |
---|
486 | disconnect |
---|
487 | $_dispatcher event -after 750 !serverDown |
---|
488 | } elseif {[regexp {^\s*nv>\s*image\s+(\d+)\s*$} $line whole match]} { |
---|
489 | set bytes [read $_sid $match] |
---|
490 | $_image(plot) configure -data $bytes |
---|
491 | update idletasks |
---|
492 | } else { |
---|
493 | # this shows errors coming back from the engine |
---|
494 | puts $line |
---|
495 | } |
---|
496 | } |
---|
497 | } |
---|
498 | |
---|
499 | # ---------------------------------------------------------------------- |
---|
500 | # USAGE: _rebuild |
---|
501 | # |
---|
502 | # Called automatically whenever something changes that affects the |
---|
503 | # data in the widget. Clears any existing data and rebuilds the |
---|
504 | # widget to display new data. |
---|
505 | # ---------------------------------------------------------------------- |
---|
506 | itcl::body Rappture::MolvisViewer::_rebuild {} { |
---|
507 | #puts stderr "MolvisViewer::_rebuild()" |
---|
508 | set recname "ATOM " |
---|
509 | set serial 0 |
---|
510 | set atom "" |
---|
511 | set altLoc "" |
---|
512 | set resName "" |
---|
513 | set chainID "" |
---|
514 | set Seqno "" |
---|
515 | set x 0 |
---|
516 | set y 0 |
---|
517 | set z 0 |
---|
518 | set occupancy 1 |
---|
519 | set tempFactor 0 |
---|
520 | set recID "" |
---|
521 | set segID "" |
---|
522 | set element "" |
---|
523 | set charge "" |
---|
524 | set data1 "" |
---|
525 | set data2 "" |
---|
526 | |
---|
527 | if {$itk_option(-device) != ""} { |
---|
528 | set dev $itk_option(-device) |
---|
529 | |
---|
530 | foreach _atom [$dev children -type atom components.molecule] { |
---|
531 | set symbol [$dev get components.molecule.$_atom.symbol] |
---|
532 | set xyz [$dev get components.molecule.$_atom.xyz] |
---|
533 | regsub {,} $xyz {} xyz |
---|
534 | scan $xyz "%f %f %f" x y z |
---|
535 | set atom $symbol |
---|
536 | set line [format "%6s%5d %4s%1s%3s %1s%5s %8.3f%8.3f%8.3f%6.2f%6.2f%8s\n" $recname $serial $atom $altLoc $resName $chainID $Seqno $x $y $z $occupancy $tempFactor $recID] |
---|
537 | append data1 $line |
---|
538 | incr serial |
---|
539 | } |
---|
540 | |
---|
541 | set data2 [$dev get components.molecule.pdb] |
---|
542 | |
---|
543 | } |
---|
544 | |
---|
545 | if {"" != $data1} { |
---|
546 | eval _send loadpdb \"$data1\" data1 |
---|
547 | } |
---|
548 | |
---|
549 | if {"" != $data2} { |
---|
550 | eval _send loadpdb \"$data2\" data2 |
---|
551 | } |
---|
552 | } |
---|
553 | |
---|
554 | itcl::body Rappture::MolvisViewer::_speed {option} { |
---|
555 | #puts stderr "MolvisViewer::_speed($option)" |
---|
556 | _send mspeed $option |
---|
557 | } |
---|
558 | |
---|
559 | # ---------------------------------------------------------------------- |
---|
560 | # USAGE: _zoom in |
---|
561 | # USAGE: _zoom out |
---|
562 | # USAGE: _zoom reset |
---|
563 | # |
---|
564 | # Called automatically when the user clicks on one of the zoom |
---|
565 | # controls for this widget. Changes the zoom for the current view. |
---|
566 | # ---------------------------------------------------------------------- |
---|
567 | itcl::body Rappture::MolvisViewer::_zoom {option} { |
---|
568 | #puts stderr "MolvisViewer::_zoom()" |
---|
569 | switch -- $option { |
---|
570 | in { |
---|
571 | _send camera zoom 10 |
---|
572 | } |
---|
573 | out { |
---|
574 | _send camera zoom -10 |
---|
575 | } |
---|
576 | reset { |
---|
577 | _send reset |
---|
578 | } |
---|
579 | } |
---|
580 | } |
---|
581 | |
---|
582 | # ---------------------------------------------------------------------- |
---|
583 | # USAGE: _move click <x> <y> |
---|
584 | # USAGE: _move drag <x> <y> |
---|
585 | # USAGE: _move release <x> <y> |
---|
586 | # |
---|
587 | # Called automatically when the user clicks/drags/releases in the |
---|
588 | # plot area. Moves the plot according to the user's actions. |
---|
589 | # ---------------------------------------------------------------------- |
---|
590 | itcl::body Rappture::MolvisViewer::_move {option x y} { |
---|
591 | #puts stderr "MolvisViewer::_move($option $x $y)" |
---|
592 | switch -- $option { |
---|
593 | click { |
---|
594 | $itk_component(3dview) configure -cursor fleur |
---|
595 | set _click(x) $x |
---|
596 | set _click(y) $y |
---|
597 | set _click(time) [clock clicks -milliseconds] |
---|
598 | } |
---|
599 | drag { |
---|
600 | if {[array size _click] == 0} { |
---|
601 | _move click $x $y |
---|
602 | } else { |
---|
603 | set now [clock clicks -milliseconds] |
---|
604 | set diff [expr {abs($_click(time) - $now)}] |
---|
605 | if {$diff < 75} { # 75ms between motion updates |
---|
606 | return |
---|
607 | } |
---|
608 | set w [winfo width $itk_component(3dview)] |
---|
609 | set h [winfo height $itk_component(3dview)] |
---|
610 | if {$w <= 0 || $h <= 0} { |
---|
611 | return |
---|
612 | } |
---|
613 | |
---|
614 | eval _send camera angle [expr $y-$_click(y)] [expr $x-$_click(x)] |
---|
615 | |
---|
616 | set _click(x) $x |
---|
617 | set _click(y) $y |
---|
618 | set _click(time) $now |
---|
619 | } |
---|
620 | } |
---|
621 | release { |
---|
622 | _move drag $x $y |
---|
623 | $itk_component(3dview) configure -cursor "" |
---|
624 | catch {unset _click} |
---|
625 | } |
---|
626 | default { |
---|
627 | error "bad option \"$option\": should be click, drag, release" |
---|
628 | } |
---|
629 | } |
---|
630 | } |
---|
631 | |
---|
632 | # ---------------------------------------------------------------------- |
---|
633 | # USAGE: _serverDown |
---|
634 | # |
---|
635 | # Used internally to let the user know when the connection to the |
---|
636 | # visualization server has been lost. Puts up a tip encouraging the |
---|
637 | # user to press any control to reconnect. |
---|
638 | # ---------------------------------------------------------------------- |
---|
639 | itcl::body Rappture::MolvisViewer::_serverDown {} { |
---|
640 | #puts stderr "MolvisViewer::_serverDown()" |
---|
641 | set x [expr {[winfo rootx $itk_component(area)]+10}] |
---|
642 | set y [expr {[winfo rooty $itk_component(area)]+10}] |
---|
643 | Rappture::Tooltip::cue @$x,$y "Lost connection to visualization server. This happens sometimes when there are too many users and the system runs out of memory.\n\nTo reconnect, reset the view or press any other control. Your picture should come right back up." |
---|
644 | } |
---|
645 | |
---|
646 | # ---------------------------------------------------------------------- |
---|
647 | # USAGE: emblems on |
---|
648 | # USAGE: emblems off |
---|
649 | # USAGE: emblems toggle |
---|
650 | # |
---|
651 | # Used internally to turn labels associated with atoms on/off, and to |
---|
652 | # update the positions of the labels so they sit on top of each atom. |
---|
653 | # ---------------------------------------------------------------------- |
---|
654 | itcl::body Rappture::MolvisViewer::emblems {option} { |
---|
655 | #puts stderr "MolvisViewer::emblems($option)" |
---|
656 | switch -- $option { |
---|
657 | on { |
---|
658 | set state 1 |
---|
659 | } |
---|
660 | off { |
---|
661 | set state 0 |
---|
662 | } |
---|
663 | toggle { |
---|
664 | if {[$itk_component(labels) cget -relief] == "sunken"} { |
---|
665 | set state 0 |
---|
666 | } else { |
---|
667 | set state 1 |
---|
668 | } |
---|
669 | } |
---|
670 | default { |
---|
671 | error "bad option \"$option\": should be on, off, toggle" |
---|
672 | } |
---|
673 | } |
---|
674 | |
---|
675 | if {$state} { |
---|
676 | $itk_component(labels) configure -relief sunken |
---|
677 | _send label on |
---|
678 | } else { |
---|
679 | $itk_component(labels) configure -relief raised |
---|
680 | _send label off |
---|
681 | } |
---|
682 | } |
---|
683 | |
---|
684 | # ---------------------------------------------------------------------- |
---|
685 | # OPTION: -device |
---|
686 | # ---------------------------------------------------------------------- |
---|
687 | itcl::configbody Rappture::MolvisViewer::device { |
---|
688 | #puts stderr "MolvisViewer::device()" |
---|
689 | |
---|
690 | if {$itk_option(-device) != "" } { |
---|
691 | |
---|
692 | if {![Rappture::library isvalid $itk_option(-device)]} { |
---|
693 | error "bad value \"$itk_option(-device)\": should be Rappture::library object" |
---|
694 | } |
---|
695 | |
---|
696 | set state [$itk_option(-device) get components.molecule.about.emblems] |
---|
697 | |
---|
698 | if {$state == "" || ![string is boolean $state] || !$state} { |
---|
699 | emblems off |
---|
700 | } else { |
---|
701 | emblems on |
---|
702 | } |
---|
703 | } |
---|
704 | |
---|
705 | $_dispatcher event -idle !rebuild |
---|
706 | } |
---|
707 | |
---|