Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
bookmark.tcl
Go to the documentation of this file.
1 # bookmark.tcl:
2 # Bookmarks list and Recently-used files list in Scid.
3 
4 set bookmarks(data) {}
5 set bookmarks(subMenus) 0
6 
7 # Read the bookmarks file if it exists:
8 catch {source [scidConfigFile bookmarks]}
9 
10 
11 namespace eval ::bookmarks {}
12 
13 # ::bookmarks::PostMenu:
14 # Posts the bookmarks toolbar menu.
15 #
16 proc ::bookmarks::PostMenu {} {
17  .main.tb.bkm.menu post [winfo pointerx .] [winfo pointery .]
18  if {[::bookmarks::CanAdd]} {
19  .main.tb.bkm.menu activate 0
20  } else {
21  .main.tb.bkm.menu activate 2
22  }
23 }
24 
25 # ::bookmarks::Refresh:
26 # Updates all bookmarks submenus.
27 #
28 proc ::bookmarks::Refresh {} {
29  foreach menu {.menu.file.bookmarks .main.tb.bkm.menu} {
31  }
32 }
33 
34 proc ::bookmarks::RefreshMenu {menu} {
35  global bookmarks helpMessage
36 
38  $menu delete 0 end
39  # $menu configure -disabledforeground [$menu cget -foreground]
40  set numBookmarkEntries [llength $bookmarks(data)]
41  $menu add command -label FileBookmarksAdd -command ::bookmarks::AddCurrent
42  set helpMessage($menu,0) FileBookmarksAdd
43  $menu add cascade -label FileBookmarksFile -menu $menu.file
44  menu $menu.file
45  set helpMessage($menu,1) FileBookmarksFile
46  if {! [::bookmarks::CanAdd]} {
47  $menu entryconfigure 0 -state disabled
48  $menu entryconfigure 1 -state disabled
49  }
50  $menu add command -label FileBookmarksEdit -command ::bookmarks::Edit
51  set helpMessage($menu,2) FileBookmarksEdit
52  if {$bookmarks(subMenus)} {
53  set display List
54  set newval 0
55  } else {
56  set display Sub
57  set newval 1
58  }
59  $menu add command -label FileBookmarks$display \
60  -command "set bookmarks(subMenus) $newval; ::bookmarks::Refresh"
61  set helpMessage($menu,3) FileBookmarks$display
62  foreach tag [list Add File Edit $display] {
63  configMenuText $menu FileBookmarks$tag FileBookmarks$tag $::language
64  }
65  if {$numBookmarkEntries == 0} { return}
66  $menu add separator
67 
68  # Add each bookmark entry:
69  set current $menu
70  set inSubMenu 0
71  set nfolders 0
72  foreach entry $bookmarks(data) {
73  if {$entry == ""} { continue}
74  set isfolder [::bookmarks::isfolder $entry]
75 
76  if {$isfolder} {
77  incr nfolders
78  $menu.file add command -label [::bookmarks::Text $entry] \
79  -command "::bookmarks::AddCurrent $nfolders"
80  }
81 
82  if {! $bookmarks(subMenus)} {
83  if {$isfolder} {
84  $current add command -label [::bookmarks::IndexText $entry]
85  } elseif {!$isfolder} {
86  $current add command -label [::bookmarks::IndexText $entry] \
87  -command [list ::bookmarks::Go $entry]
88  }
89  continue
90  }
91 
92  # Move out of submenu where necessary:
93  if {$isfolder && $inSubMenu} {
94  set current [winfo parent $current]
95  }
96 
97  if {$isfolder} {
98  # Menu (folder) entry:
99  set current [::bookmarks::NewSubMenu $current $entry]
100  set inSubMenu 1
101  } else {
102  # Bookmark entry:
103  $current add command -label [::bookmarks::Text $entry] \
104  -command [list ::bookmarks::Go $entry]
105  }
106  }
107 }
108 
109 # ::bookmarks::CanAdd:
110 # Returns 1 if the current game can be added as a bookmark.
111 # It must be in an open database, not a PGN file, and not game number 0.
112 #
113 proc ::bookmarks::CanAdd {} {
114  if {[sc_game number] == 0} { return 0}
115  if {$::curr_db == $::clipbase_db} { return 0}
116  set fname [sc_base filename $::curr_db]
117  foreach suffix {.pgn .PGN} {
118  if {[string match "*$suffix" "$fname"]} { return 0}
119  }
120  return 1
121 }
122 
123 # ::bookmarks::AddCurrent:
124 # Adds the current game to the bookmarks list.
125 #
126 proc ::bookmarks::AddCurrent {{folder 0}} {
127  global bookmarks
128  if {! [sc_base inUse]} {
129  return
130  }
131  set text [::bookmarks::New game]
132  set len [llength $bookmarks(data)]
133  set fcount 0
134  for {set i 0} {$i < $len} {incr i} {
135  if {[::bookmarks::isfolder [lindex $bookmarks(data) $i]]} {
136  if {$fcount == $folder} { break}
137  incr fcount
138  }
139  }
140  set bookmarks(data) [linsert $bookmarks(data) $i $text]
143 }
144 
145 # ::bookmarks::New:
146 # Returns a bookmarks list entry for the current game or a new folder.
147 #
148 proc ::bookmarks::New {type} {
149  if {$type == "folder"} { return [list "f" ""]}
150  set text "[file tail [sc_base filename $::curr_db]]: [sc_game info result], "
151  append text "[::utils::string::Surname [sc_game info white]] - "
152  append text "[::utils::string::Surname [sc_game info black]], "
153  append text "[::utils::string::CityName [sc_game info site]] "
154  set round [sc_game info round]
155  if {$round != "" && $round != "?"} { append text "($round) "}
156  append text "[sc_game info year]"
157  set list [list "g" $text]
158  sc_game pgn
159  lappend list [sc_base filename $::curr_db] [sc_game number] [sc_pos pgnOffset]
160  lappend list [sc_game info white] [sc_game info black]
161  lappend list [sc_game info year] [sc_game info site]
162  lappend list [sc_game info round] [sc_game info result]
163  return $list
164 }
165 
166 # ::bookmarks::Go
167 #
168 # Jumps to a selected bookmark.
169 #
170 proc ::bookmarks::Go {entry} {
171  if {[::bookmarks::isfolder $entry]} { return}
172  set fname [lindex $entry 2]
173  set gnum [lindex $entry 3]
174  set ply [lindex $entry 4]
175  set slot [sc_base slot $fname]
176  if {$slot != 0} {
177  sc_base switch $slot
178  } else {
179  busyCursor .
180  if {[catch { ::file::Open $fname} result]} {
181  unbusyCursor .
182  tk_messageBox -icon warning -type ok -parent . \
183  -title "Scid" -message "Unable to load the database:\n$fname\n\n$result"
184  return
185  }
186  unbusyCursor .
187  set ::glist 1
188  ::recentFiles::add "[file rootname $fname].si4"
189  }
190  # Find and load the best database game matching the bookmark:
191  set white [lindex $entry 5]
192  set black [lindex $entry 6]
193  set year [lindex $entry 7]
194  set site [lindex $entry 8]
195  set round [lindex $entry 9]
196  set result [lindex $entry 10]
197 
198  set best [sc_game find $gnum $white $black $site $round $year $result]
199  if {[catch {::game::Load $best}]} {
200  tk_messageBox -icon warning -type ok -parent . \
201  -title "Scid" -message "Unable to load game number: $best"
202  } else {
203  sc_move pgn $ply
204  }
207 }
208 
209 # ::bookmarks::DeleteChildren
210 #
211 # Deletes all submenus of a bookmark menu.
212 #
213 proc ::bookmarks::DeleteChildren {w} {
214  foreach child [winfo children $w] {
216  destroy $child
217  }
218 }
219 
220 # ::bookmarks::NewSubMenu
221 #
222 # Creates a new bookmark submenu.
223 #
224 proc ::bookmarks::NewSubMenu {w entry} {
225  set i 1
226  while {[winfo exists $w.m$i]} { incr i}
227  $w add cascade -label [::bookmarks::Text $entry] -menu $w.m$i
228  menu $w.m$i -tearoff 0
229  return $w.m$i
230 }
231 
232 # Globals used for bookmark editing:
233 #
234 set bookmarks(edit) ""
235 set bookmarks(ismenu) 0
236 
237 
238 # ::bookmarks::Edit
239 #
240 # Creates the bookmark editing window.
241 #
242 proc ::bookmarks::Edit {} {
243  global bookmarks
244  set w .bmedit
245  if {[winfo exists $w]} { return}
246  set bookmarks(old) $bookmarks(data)
248  wm title $w "Scid: [tr FileBookmarksEdit]"
249  # wm transient $w .
250  bind $w <F1> {helpWindow Bookmarks}
251  ttk::entry $w.e -width 40 \
252  -textvariable bookmarks(edit) -font font_Small -exportselection 0
253  bind $w.e <FocusIn> {.bmedit.e configure -background lightYellow}
254  bind $w.e <FocusOut> {.bmedit.e configure -background white}
255 
256  trace variable bookmarks(edit) w ::bookmarks::EditRefresh
257  pack $w.e -side top -fill x
258  pack [ttk::frame $w.b2] -side bottom -fill x
259  pack [ttk::frame $w.b1] -side bottom -fill x
260  pack [ttk::frame $w.f] -side top -fill both -expand 1
261  listbox $w.f.list -width 50 -height 10 -yscrollcommand "$w.f.ybar set" \
262  -fg black -bg white -exportselection 0 -font font_Small -setgrid 1
263  ttk::scrollbar $w.f.ybar -takefocus 0 -command "$w.f.list yview"
264  bind $w.f.list <<ListboxSelect>> ::bookmarks::EditSelect
265  pack $w.f.ybar -side right -fill y
266  pack $w.f.list -side left -fill x -expand 1
267  foreach entry $bookmarks(data) {
268  $w.f.list insert end [::bookmarks::IndexText $entry]
269  }
270  dialogbutton $w.b1.newFolder -text $::tr(NewSubmenu) \
271  -command {::bookmarks::EditNew folder}
272  dialogbutton $w.b1.newGame -text [tr FileBookmarksAdd] \
273  -command {::bookmarks::EditNew game}
274  if {! [::bookmarks::CanAdd]} { $w.b1.newGame configure -state disabled}
275  dialogbutton $w.b1.delete -text $::tr(Delete) -command ::bookmarks::EditDelete
276  ttk::button $w.b2.up -image tb_up -command {::bookmarks::EditMove up}
277  ttk::button $w.b2.down -image tb_down -command {::bookmarks::EditMove down}
278  dialogbutton $w.b2.ok -text "OK" -command ::bookmarks::EditDone
279  dialogbutton $w.b2.cancel -text $::tr(Cancel) -command {
280  set bookmarks(data) $bookmarks(old)
281  catch {grab release .bmedit}
282  destroy .bmedit
283  }
284  pack $w.b1.newFolder $w.b1.newGame $w.b1.delete -side left -padx 2 -pady 2
285  pack $w.b2.up $w.b2.down -side left -padx 2 -pady 2
286  packdlgbuttons $w.b2.cancel $w.b2.ok
287  set bookmarks(edit) ""
288 
289  wm withdraw $w
290  update idletasks
291  set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
292  - [winfo vrootx .]}]
293  set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
294  - [winfo vrooty .]}]
295  wm geom $w +$x+$y
296  wm deiconify $w
297  update
298  catch {grab .bmedit}
299 }
300 
301 # ::bookmarks::EditDone
302 #
303 # Updates the bookmarks and closes the bookmark editing window.
304 #
305 proc ::bookmarks::EditDone {} {
306  catch {grab release .bmedit}
307  destroy .bmedit
310 }
311 
312 # ::bookmarks::EditRefresh
313 #
314 # Updates the bookmarks whenever the contents of the bookmark
315 # editing entry box are changed.
316 #
317 proc ::bookmarks::EditRefresh {args} {
318  global bookmarks
319  set list .bmedit.f.list
320  set sel [lindex [$list curselection] 0]
321  if {$sel == ""} { return}
322  set text $bookmarks(edit)
323  set e [lindex $bookmarks(data) $sel]
324  set e [::bookmarks::SetText $e $text]
325  set text [::bookmarks::IndexText $e]
326  set bookmarks(data) [lreplace $bookmarks(data) $sel $sel $e]
327  $list insert $sel $text
328  $list delete [expr {$sel + 1}]
329  $list selection clear 0 end
330  $list selection set $sel
331 }
332 
333 # ::bookmarks::EditSelect
334 #
335 # Sets the bookmark editing entry box when a bookmark is selected.
336 #
337 proc ::bookmarks::EditSelect {{sel ""}} {
338  global bookmarks
339  set list .bmedit.f.list
340  set sel [lindex [$list curselection] 0]
341  if {$sel == ""} {
342  .bmedit.e delete 0 end
343  return
344  }
345  if {$sel >= [llength $bookmarks(data)]} {
346  $list selection clear 0 end
347  set bookmarks(edit) ""
348  return
349  }
350  set e [lindex $bookmarks(data) $sel]
351  set bookmarks(ismenu) [::bookmarks::isfolder $e]
352  set bookmarks(edit) [::bookmarks::Text $e]
353 }
354 
355 # ::bookmarks::isfolder:
356 # Returns 1 if this bookmark entry is a folder (submenu).
357 #
358 proc ::bookmarks::isfolder {entry} {
359  if {[lindex $entry 0] == "f"} { return 1}
360  return 0
361 }
362 
363 # ::bookmarks::Text:
364 # Returns the entry text of a bookmark.
365 #
366 proc ::bookmarks::Text {entry} {
367  return [lindex $entry 1]
368 }
369 
370 proc ::bookmarks::IndexText {entry} {
371  set text ""
372  if {[lindex $entry 0] == "f"} {
373  append text "\[[lindex $entry 1]\]"
374  } else {
375  append text " [lindex $entry 1]"
376  }
377  return $text
378 }
379 
380 proc ::bookmarks::SetText {entry text} {
381  return [lreplace $entry 1 1 $text]
382 }
383 
384 # ::bookmarks::EditMove
385 #
386 # Moves the selected bookmark "up" or "down" one place.
387 #
388 proc ::bookmarks::EditMove {{dir "up"}} {
389  global bookmarks
390  set w .bmedit
391  set list $w.f.list
392  set sel [lindex [$list curselection] 0]
393  if {$sel == ""} { return}
394  set e [lindex $bookmarks(data) $sel]
395  set text [::bookmarks::IndexText $e]
396  set newsel $sel
397  if {$dir == "up"} {
398  incr newsel -1
399  if {$newsel < 0} { return}
400  } else {
401  incr newsel
402  if {$newsel >= [$list index end]} { return}
403  }
404  set bookmarks(data) [lreplace $bookmarks(data) $sel $sel]
405  set bookmarks(data) [linsert $bookmarks(data) $newsel $e]
406  $list selection clear 0 end
407  $list delete $sel
408  $list insert $newsel $text
409  $list selection set $newsel
410 }
411 
412 # ::bookmarks::EditDelete
413 #
414 # Deletes the selected bookmark.
415 #
416 proc ::bookmarks::EditDelete {} {
417  global bookmarks
418  set w .bmedit
419  set list $w.f.list
420  set sel [lindex [$list curselection] 0]
421  if {$sel == ""} { return}
422  set bookmarks(data) [lreplace $bookmarks(data) $sel $sel]
423  $list selection clear 0 end
424  $list delete $sel
425  set bookmarks(edit) ""
426 }
427 
428 # ::bookmarks::EditNew
429 #
430 # Inserts a new entry ("folder" for a submenu or "game" for the
431 # current game) after the selected bookmark.
432 #
433 proc ::bookmarks::EditNew {{type "folder"}} {
434  global bookmarks
435  set w .bmedit
436  set list $w.f.list
437  set folder 0
438  if {[string index $type 0] == "f"} {
439  set folder 1
440  set entry [::bookmarks::New folder]
441  } else {
442  set entry [::bookmarks::New game]
443  }
444  set sel [lindex [$list curselection] 0]
445  if {$sel == ""} {
446  lappend bookmarks(data) $entry
447  set sel [$list index end]
448  $list insert end [::bookmarks::IndexText $entry]
449  $list selection clear 0 end
450  $list selection set $sel
451  $list see $sel
453  return
454  }
455  incr sel
456  set bookmarks(data) [linsert $bookmarks(data) $sel $entry]
457  $list insert $sel [::bookmarks::IndexText $entry]
458  $list selection clear 0 end
459  $list selection set $sel
460  $list see $sel
462 }
463 
464 # ::bookmarks::Save
465 #
466 # Saves the bookmarks file, reporting any error in a message box if
467 # reportError is true.
468 #
469 proc ::bookmarks::Save {{reportError 0}} {
470  global bookmarks
471  set f {}
472  set filename [scidConfigFile bookmarks]
473  if {[catch {open $filename w} f]} {
474  if {$reportError} {
475  tk_messageBox -title "Scid" -type ok -icon warning \
476  -message "Unable to write bookmarks file: $filename\n$f"
477  }
478  return
479  }
480  puts $f "# Scid $::scidVersion bookmarks file\n"
481  foreach i {subMenus data} {
482  puts $f "set bookmarks($i) [list [set bookmarks($i)]]"
483  puts $f ""
484  }
485  close $f
486 }
487 
488 
489 # End of file: bookmark.tcl