1 # ui-main.tcl --
2 #
3 # FIXME: This file needs a description here.
4 #
5 # Copyright (c) 2001-2002 The Regents of the University of California.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # A. Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # B. Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 # C. Neither the names of the copyright holders nor the names of its
17 # contributors may be used to endorse or promote products derived from this
18 # software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 Import enable
32 import Observer SessionReceiver TopLevelWindow
33 import VEListbox VicReceiver
34
35 ######
36 #veUI
37 # This class fires up the main user interface for the Video Explorer
38 # application. It creates the menubar and the basic layout for the
39 # multiple views.
40 #
41
42 Class veUI -superclass Observer
43
44 veUI instproc init {w} {
45 # session_list: Tcl list of IP addresses of the active sessions
46 # listview_listbox_: A listbox widget that is used during the list view
47 $self instvar listview_listbox_
48 global view old_view default_prefs session_list
49
50 wm title . "Video Explorer"
51 wm minsize . 250 200
52
53 $self build_menubar $w
54 $self init_keybindings
55 $self init_preferences
56
57 # List of all sessions that have been added
58 set session_list {}
59 # Denotes the current view (default: Vic)
60 set view $default_prefs(view)
61 # Denotes the previous view (default: Vic)
62 set old_view $view
63
64 # Two frames which are packed and unpacked when the user switches views
65 frame .list
66 frame .vic
67 set listview_listbox_ [new VEListbox .list]
68
69 if {$view == "vic"} {
70 pack .vic -anchor nw
71 } elseif {$view == "list"} {
72 pack .list -fill both -expand true
73 }
74 }
75
76 #
77 # Initializes some simple keybindings on the main Video Explorer widget.
78 #
79 veUI instproc init_keybindings {} {
80 bind . <a> "new AddSessionPopUp $self"
81 bind . <r> "new RemoveSessionPopUp $self"
82 bind . <q> "exit"
83 }
84
85 #
86 # Builds the File/Edit/View menubar at the top of the Video Explorer widget.
87 #
88 veUI instproc build_menubar {w} {
89 menu .menubar
90 . config -menu .menubar
91 foreach m {File Edit View} {
92 set $m [menu .menubar.m$m -tearoff 0]
93 .menubar add cascade -label $m -menu .menubar.m$m
94 }
95 $File add command -label "Add Session" \
96 -command "new AddSessionPopUp $self"
97 $File add command -label "Remove Session" \
98 -command "new RemoveSessionPopUp $self"
99 $File add command -label Quit -command exit
100
101 $Edit add command -label Preferences -command "Pref_Dialog"
102
103 $View add radio -label Vic -variable view -value vic\
104 -command "$self toggle_view"
105 $View add radio -label List -variable view -value list\
106 -command "$self toggle_view"
107
108 }
109
110 #
111 # Checks that the entered IP to add is in valid addr/port format and that
112 # the user is not already in the session when adding a session.
113 #
114 veUI instproc check_spec_to_add {} {
115 global session_list
116
117 # gets the spec that was typed by the user into the entry widget
118 set spec_ [.addSessionPopUp.entry get]
119 set spec_split [split $spec_ /]
120 set n [llength $spec_split]
121 set port [lindex $spec_split 1]
122 if { $n == 2 } {
123 if { [string match \[0-9\]* $port] && $port <= 65536} {
124 if { [lsearch -exact $session_list $spec_] == -1 } {
125 lappend session_list $spec_
126 $self add_session $spec_
127 } else {
128 new ErrorPopUp .spec_exists_popup "Error in IP Address" \
129 "You are already connected to this session: $spec_" \
130 .addSessionPopUp
131 }
132 } else {
133 new ErrorPopUp .badport "Error in IP Address" \
134 "Port number must be smaller than 65537" \
135 .addSessionPopUp
136 }
137 } else {
138 new ErrorPopUp .bad_spec_popup "Error in IP Address" \
139 "Please specify both address and port\
140 in the form: address/port" .addSessionPopUp
141 }
142 }
143
144 #
145 # Checks that the entered IP to remove is in valid addr/port format and that
146 # the user is connected to that session when removing a session.
147 #
148 veUI instproc check_spec_to_remove {} {
149 global session_list
150
151 # gets the spec that was typed by the user into the entry widget
152 set spec_ [.removeSessionPopUp.entry get]
153 set spec_split [split $spec_ /]
154 set n [llength $spec_split]
155 set port [lindex $spec_split 1]
156 if { $n == 2 } {
157 if { [string match \[0-9\]* $port] && $port <= 65536} {
158 set spec_index [lsearch -exact $session_list $spec_]
159 if { $spec_index != -1 } {
160 $self remove_session $spec_
161 } else {
162 new ErrorPopUp .spec_nonexists_popup "Error in IP Address"\
163 "You are not connected to this session: $spec_"\
164 .removeSessionPopUp
165 }
166 } else {
167 new ErrorPopUp .badport "Error in IP Address" \
168 "Port number must be smaller than 65537" \
169 .removeSessionPopUp
170 }
171 } else {
172 new ErrorPopUp .bad_spec_popup "Error in IP Address" \
173 "Please specify both address and port\
174 in the form: address/port" .removeSessionPopUp
175 }
176 }
177
178 #
179 # Returns the index of the spec in the session_list
180 #
181 veUI instproc get_spec_index {spec} {
182 global session_list
183 return [lsearch -exact $session_list $spec]
184 }
185
186 #
187 # Adds the session by making a new VicReceiver and adding the spec
188 # to the list-view listbox.
189 #
190 veUI instproc add_session {spec} {
191 set spec_window [join [split $spec .] /]
192 global sr_vic_$spec_window
193 $self instvar listview_listbox_
194 destroy .addSessionPopUp
195
196 set vic_session [new VicReceiver $spec $self]
197 $listview_listbox_ insert end $spec "$self session_popup $spec"
198 }
199
200 #
201 # Removes the session by destroying the vic-view session and removing the
202 # spec from the list-view listbox. It also destroys any related toplevel
203 # windows relating to that session.
204 #
205 veUI instproc remove_session {spec} {
206 $self instvar listview_listbox_
207 global session_list
208 set spec_window [join [split $spec .] /]
209 global sr_vic_$spec_window sr_list_$spec_window
210 set spec_index [$self get_spec_index $spec]
211 set session_list [lreplace $session_list $spec_index $spec_index]
212
213 destroy .removeSessionPopUp
214 $listview_listbox_ delete $spec_index
215 destroy .vic.$spec_window
216 [set sr_vic_$spec_window] detachAll
217 [set sr_vic_$spec_window] unpack_VEuw
218
219 if {[winfo exists .session$spec_window]} {
220 [set sr_list_$spec_window] detachAll
221 [set sr_list_$spec_window] unpack_VEuw
222 destroy .session$spec_window
223 }
224 }
225
226 #
227 # Toggles the view as the user requests. Depending on the old_view and
228 # current view, it packs and unpacks windows as necessary.
229 #
230 veUI instproc toggle_view {} {
231 global session_list
232
233 #remove the old_view
234 global view old_view
235 if {$old_view == "vic"} {
236 $self unpack_vic
237 } elseif {$old_view == "list"} {
238 $self unpack_list
239 }
240
241 #pack the requested view
242 if {$view == "vic"} {
243 pack .vic -anchor nw
244 set old_view vic
245 } elseif {$view == "list"} {
246 pack .list -fill both -expand true
247 set old_view list
248 }
249 }
250
251 #
252 # Unpacks the vic-view only by unpacking the parent frame .vic and it's
253 # associated toplevel windows, if they exist.
254 #
255 veUI instproc unpack_vic {} {
256 global session_list
257 foreach session $session_list {
258 set spec_window [join [split $session .] /]
259 global sr_vic_$spec_window
260 [set sr_vic_$spec_window] unpack_VEuw
261 }
262 pack forget .vic
263
264 }
265
266 #
267 # Unpacks the list-view by unpacking the parent frame .list and it's
268 # associated toplevel windows, if they exist.
269 #
270 veUI instproc unpack_list {} {
271 global session_list
272 foreach session $session_list {
273 set spec_window [join [split $session .] /]
274 global sr_list_$spec_window
275 if {[winfo exists .session$spec_window]} {
276 [set sr_list_$spec_window] detachAll
277 [set sr_list_$spec_window] unpack_VEuw
278 destroy .session$spec_window
279 }
280 }
281 pack forget .list
282 }
283
284 #
285 # In list-view, pop-up a window that has a SessionReciever widget, which
286 # displays video for the selected spec.
287 #
288 veUI instproc session_popup {spec} {
289 set spec_window [join [split $spec .] /]
290 set w .list$spec_window
291 global sr_list_$spec_window
292
293 if {[winfo exists $w]} {
294 [set sr_list_$spec_window] detachAll
295 destroy $w
296 } else {
297 toplevel $w
298 wm title $w $spec
299 wm resizable $w 0 0
300 set sr_list_$spec_window [new SessionReceiver $spec $w]
301
302 # frame from SessionReceiver init
303 # pack $w -side left -expand true
304 }
305 }
306
307 veUI instproc init_preferences {} {
308 global default_prefs
309 Pref_Init ve-user-defaults ve-app-defaults
310 Pref_Add {{default_prefs(view) view {CHOICE vic list} "View" \
311 "This setting toggles the view of the VideoExplorer at startup."}}
312
313 }
314
315
316 #######
317 #AddSessionPopUp
318 # Creates an entry pop-up window for [File->Add Session]
319 #
320
321 Class AddSessionPopUp -superclass TopLevelWindow
322
323 AddSessionPopUp instproc init {ui_} {
324 $self next .addSessionPopUp
325 set path_ .addSessionPopUp
326 toplevel $path_
327 wm title $path_ "Add Session..."
328 wm resizable $path_ 0 0
329
330 label $path_.label -text "Enter the IP address of the session\
331 you would like to join:" -anchor w
332 entry $path_.entry -relief sunken
333 grid $path_.label -pady 5 -padx 10
334 grid $path_.entry -sticky we -padx 20
335 bind $path_.entry <Return> "$ui_ check_spec_to_add"
336
337 set buttons_ $path_.buttons
338 frame $buttons_
339 grid $buttons_ -sticky s
340 button $buttons_.enter -text Join -pady 5\
341 -command "$ui_ check_spec_to_add"
342 button $buttons_.cancel -text Cancel -pady 5\
343 -command "destroy .addSessionPopUp"
344 pack $buttons_.cancel -side right
345 pack $buttons_.enter -side right
346
347 focus $path_
348 grab $path_
349
350 }
351
352 ######
353 #RemoveSessionPopUp
354 # Creates an entry pop-up window for [File->Remove Session]
355 #
356
357 Class RemoveSessionPopUp -superclass TopLevelWindow
358
359 RemoveSessionPopUp instproc init {ui_} {
360 $self next .removeSessionPopUp
361 set path_ .removeSessionPopUp
362 toplevel $path_
363 wm title $path_ "Remove Session..."
364 wm resizable $path_ 0 0
365
366 label $path_.label -text "Enter the IP address of the session\
367 you would like to remove:" -anchor w
368 entry $path_.entry -relief sunken
369 grid $path_.label -pady 5 -padx 10
370 grid $path_.entry -sticky we -padx 20
371 bind $path_.entry <Return> "$ui_ check_spec_to_remove"
372
373 set buttons_ $path_.buttons
374 frame $buttons_
375 grid $buttons_ -sticky s
376 button $buttons_.enter -text Remove -pady 5\
377 -command "$ui_ check_spec_to_remove"
378 button $buttons_.cancel -text Cancel -pady 5\
379 -command "destroy .removeSessionPopUp"
380 pack $buttons_.cancel -side right
381 pack $buttons_.enter -side right
382
383 focus $path_
384 grab $path_
385 }
386
387
388 ######
389 #ErrorPopUp
390 # Creates a simple error window with a text message and 'OK' button
391 #
392
393 Class ErrorPopUp -superclass TopLevelWindow
394
395 ErrorPopUp instproc init {w title text regrab} {
396 set popup $w
397 toplevel $popup
398 wm title $popup $title
399 wm resizable $popup 0 0
400 message $popup.msg -justify center -aspect 1000 -text $text
401 button $popup.ok -text OK \
402 -command "destroy $popup"
403 grid $popup.msg
404 grid $popup.ok
405 bind $popup <Escape> "destroy $popup"
406 bind $popup <Return> "destroy $popup"
407 focus $popup
408 grab $popup
409 tkwait window $popup
410 grab release $popup
411 focus $regrab
412 grab $regrab
413 }
414
415
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.