... | ... |
@@ -10,160 +10,8 @@ set tk_strictMotif |
10 | 10 |
|
11 | 11 |
wm title . "mamegui.tcl" |
12 | 12 |
|
13 |
- |
|
14 |
-#------------------------------------- |
|
15 |
-# Scrolled frame implementation |
|
16 |
-# http://wiki.tcl.tk/9223 |
|
17 |
-#------------------------------------- |
|
18 |
-# sframe.tcl |
|
19 |
-# Paul Walton |
|
20 |
-# Create a ttk-compatible, scrollable frame widget. |
|
21 |
-# Usage: |
|
22 |
-# sframe new <path> ?-toplevel true? ?-anchor nsew? |
|
23 |
-# -> <path> |
|
24 |
-# |
|
25 |
-# sframe content <path> |
|
26 |
-# -> <path of child frame where the content should go> |
|
27 |
- |
|
28 |
-namespace eval sframe { |
|
29 |
- namespace ensemble create |
|
30 |
- namespace export * |
|
31 |
- |
|
32 |
- # Create a scrollable frame or window. |
|
33 |
- proc new {path args} { |
|
34 |
- # Use the ttk theme's background for the canvas and toplevel |
|
35 |
- set bg [ttk::style lookup TFrame -background] |
|
36 |
- if { [ttk::style theme use] eq "aqua" } { |
|
37 |
- # Use a specific color on the aqua theme as 'ttk::style lookup' is not accurate. |
|
38 |
- set bg "#e9e9e9" |
|
39 |
- } |
|
40 |
- |
|
41 |
- # Create the main frame or toplevel. |
|
42 |
- if { [dict exists $args -toplevel] && [dict get $args -toplevel] } { |
|
43 |
- toplevel $path -bg $bg |
|
44 |
- } else { |
|
45 |
- ttk::frame $path |
|
46 |
- } |
|
47 |
- |
|
48 |
- # Create a scrollable canvas with scrollbars which will always be the same size as the main frame. |
|
49 |
- set canvas [canvas $path.canvas -bg $bg -bd 0 -highlightthickness 0 -yscrollcommand [list $path.scrolly set] -xscrollcommand [list $path.scrollx set]] |
|
50 |
- ttk::scrollbar $path.scrolly -orient vertical -command [list $canvas yview] |
|
51 |
- ttk::scrollbar $path.scrollx -orient horizontal -command [list $canvas xview] |
|
52 |
- |
|
53 |
- # Create a container frame which will always be the same size as the canvas or content, whichever is greater. |
|
54 |
- # This allows the child content frame to be properly packed and also is a surefire way to use the proper ttk background. |
|
55 |
- set container [ttk::frame $canvas.container] |
|
56 |
- pack propagate $container 0 |
|
57 |
- |
|
58 |
- # Create the content frame. Its size will be determined by its contents. This is useful for determining if the |
|
59 |
- # scrollbars need to be shown. |
|
60 |
- set content [ttk::frame $container.content] |
|
61 |
- |
|
62 |
- # Pack the content frame and place the container as a canvas item. |
|
63 |
- set anchor "n" |
|
64 |
- if { [dict exists $args -anchor] } { |
|
65 |
- set anchor [dict get $args -anchor] |
|
66 |
- } |
|
67 |
- pack $content -anchor $anchor |
|
68 |
- $canvas create window 0 0 -window $container -anchor nw |
|
69 |
- |
|
70 |
- # Grid the scrollable canvas sans scrollbars within the main frame. |
|
71 |
- grid $canvas -row 0 -column 0 -sticky nsew |
|
72 |
- grid rowconfigure $path 0 -weight 1 |
|
73 |
- grid columnconfigure $path 0 -weight 1 |
|
74 |
- |
|
75 |
- # Make adjustments when the the sframe is resized or the contents change size. |
|
76 |
- bind $path.canvas <Expose> [list [namespace current]::resize $path] |
|
77 |
- |
|
78 |
- # Mousewheel bindings for scrolling. |
|
79 |
- bind [winfo toplevel $path] <MouseWheel> [list +[namespace current] scroll $path yview %W %D] |
|
80 |
- bind [winfo toplevel $path] <Shift-MouseWheel> [list +[namespace current] scroll $path xview %W %D] |
|
81 |
- |
|
82 |
- return $path |
|
83 |
- } |
|
84 |
- |
|
85 |
- |
|
86 |
- # Given the toplevel path of an sframe widget, return the path of the child frame suitable for content. |
|
87 |
- proc content {path} { |
|
88 |
- return $path.canvas.container.content |
|
89 |
- } |
|
90 |
- |
|
91 |
- |
|
92 |
- # Make adjustments when the the sframe is resized or the contents change size. |
|
93 |
- proc resize {path} { |
|
94 |
- set canvas $path.canvas |
|
95 |
- set container $canvas.container |
|
96 |
- set content $container.content |
|
97 |
- |
|
98 |
- # Set the size of the container. At a minimum use the same width & height as the canvas. |
|
99 |
- set width [winfo width $canvas] |
|
100 |
- set height [winfo height $canvas] |
|
101 |
- |
|
102 |
- # If the requested width or height of the content frame is greater then use that width or height. |
|
103 |
- if { [winfo reqwidth $content] > $width } { |
|
104 |
- set width [winfo reqwidth $content] |
|
105 |
- } |
|
106 |
- if { [winfo reqheight $content] > $height } { |
|
107 |
- set height [winfo reqheight $content] |
|
108 |
- } |
|
109 |
- $container configure -width $width -height $height |
|
110 |
- |
|
111 |
- # Configure the canvas's scroll region to match the height and width of the container. |
|
112 |
- $canvas configure -scrollregion "0 0 $width $height" |
|
113 |
- |
|
114 |
- # Show or hide the scrollbars as necessary. |
|
115 |
- # Horizontal scrolling. |
|
116 |
- if { [winfo reqwidth $content] > [winfo width $canvas] } { |
|
117 |
- grid $path.scrollx -row 1 -column 0 -sticky ew |
|
118 |
- } else { |
|
119 |
- grid forget $path.scrollx |
|
120 |
- } |
|
121 |
- # Vertical scrolling. |
|
122 |
- if { [winfo reqheight $content] > [winfo height $canvas] } { |
|
123 |
- grid $path.scrolly -row 0 -column 1 -sticky ns |
|
124 |
- } else { |
|
125 |
- grid forget $path.scrolly |
|
126 |
- } |
|
127 |
- return |
|
128 |
- } |
|
129 |
- |
|
130 |
- |
|
131 |
- # Handle mousewheel scrolling. |
|
132 |
- proc scroll {path view W D} { |
|
133 |
- if { [winfo exists $path.canvas] && [string match $path.canvas* $W] } { |
|
134 |
- $path.canvas $view scroll [expr {-$D}] units |
|
135 |
- } |
|
136 |
- return |
|
137 |
- } |
|
138 |
-} |
|
139 |
-#------------------------------------- |
|
140 |
-# End of Scrolled frame implementation |
|
141 |
-#------------------------------------- |
|
142 |
- |
|
143 |
-#------------------------------------- |
|
144 |
-# Read png header implementation |
|
145 |
-# http://wiki.tcl.tk/759 |
|
146 |
-#------------------------------------- |
|
147 |
-proc read_png_header {file} { |
|
148 |
- set fh [open $file r] |
|
149 |
- fconfigure $fh -encoding binary -translation binary -eofchar {} |
|
150 |
- if {[read $fh 8] != "\x89PNG\r\n\x1a\n"} { close $fh; return } |
|
151 |
- binary scan [read $fh 8] Ia4 len type |
|
152 |
- set r [read $fh $len] |
|
153 |
- if {![eof $fh] && $type == "IHDR"} { |
|
154 |
- binary scan $r IIccccc width height depth color compression filter interlace |
|
155 |
- close $fh |
|
156 |
- return [list $width $height $depth $color $compression $filter $interlace] |
|
157 |
- } |
|
158 |
- close $fh |
|
159 |
- return |
|
160 |
-} |
|
161 |
-#------------------------------------- |
|
162 |
-# End of Read png header implementation |
|
163 |
-#------------------------------------- |
|
164 |
- |
|
165 |
- |
|
166 | 13 |
# files locations |
14 |
+set small 1 |
|
167 | 15 |
set mameconf "/etc/mame/mame.ini" |
168 | 16 |
set snapsdir "/usr/local/share/games/mame/snaps/" |
169 | 17 |
set catverini "/usr/local/share/gnome-video-arcade/catver.ini" |
... | ... |
@@ -172,13 +20,15 @@ set nplayersini "/usr/share/games/mame/data/nplayers.ini" |
172 | 20 |
|
173 | 21 |
set rompaths [split [regsub {\$HOME} [lindex [split [exec grep ^rompath $mameconf ] " "] end] "$env(HOME)\1"] ";"] |
174 | 22 |
|
175 |
-set games "dynablst gauntlet snowbro2" |
|
23 |
+set games "dynablst gauntlet snowbro2 trog sprint4 rampage ssprint sonic hotrod" |
|
176 | 24 |
|
177 |
-set gameslist [split [exec sh -c "grep =4P.sim $nplayersini | cut -d '=' -f 1 | tr '\n' ':' | head -20"] ":"] |
|
25 |
+set gameslist4 [split [exec sh -c "grep =4P.sim $nplayersini | cut -d '=' -f 1 | tr '\n' ':' | head -20"] ":"] |
|
26 |
+set gameslist3 [split [exec sh -c "grep =3P.sim $nplayersini | cut -d '=' -f 1 | tr '\n' ':' | head -20"] ":"] |
|
27 |
+set gameslist2 [split [exec sh -c "grep =2P.sim $nplayersini | cut -d '=' -f 1 | tr '\n' ':' | head -20"] ":"] |
|
178 | 28 |
|
179 | 29 |
set gamesnoalt [lsort [split [exec sh -c " cat $historydat | grep \"^.info=\" | cut -d '=' -f 2 | cut -d ',' -f 1 | tr '\n' ':'"] ":"]] |
180 | 30 |
|
181 |
-foreach i $gameslist { |
|
31 |
+foreach i [concat $gameslist4 $gameslist3 $gameslist2 $gamesnoalt] { |
|
182 | 32 |
if {[lsearch -glob $games $i]==-1 && [lsearch -glob -sort $gamesnoalt $i]!=-1} { |
183 | 33 |
lappend games $i |
184 | 34 |
} |
... | ... |
@@ -206,53 +56,214 @@ proc add_navibuttons { page pagesize parent} { |
206 | 56 |
|
207 | 57 |
} |
208 | 58 |
|
209 |
-proc redraw_list { page } { |
|
210 |
- global games snapsdir |
|
211 |
- catch { destroy .gameslist } |
|
212 |
- # Use the -toplevel option to create a scrollable toplevel window. |
|
213 |
- sframe new .gameslist -anchor w |
|
214 |
- pack .gameslist -side top -fill both -expand true |
|
59 |
+set gameslist_lasth 0 |
|
60 |
+proc gameslist_wmevent { win width height x y e} { |
|
61 |
+ global gameslist_lasth |
|
62 |
+ if { [calcwidth_list] != [spacer cget -width] } { |
|
63 |
+ setwidth_list [calcwidth_list] |
|
64 |
+ } |
|
65 |
+ set total [winfo height .gameslist] |
|
66 |
+ if { $total != $gameslist_lasth } { |
|
67 |
+ set gameslist_lasth $total |
|
68 |
+ gameslist_adjustsb |
|
69 |
+ } |
|
70 |
+} |
|
71 |
+ |
|
72 |
+set adjustpending 0 |
|
73 |
+proc gameslist_adjustsb { args } { |
|
74 |
+ global adjustpending |
|
75 |
+ if { [llength $args] == 0 } { |
|
76 |
+ if { $adjustpending == 0 } { |
|
77 |
+ set adjustpending 1 |
|
78 |
+ after 100 gameslist_adjustsb 1 |
|
79 |
+ } |
|
80 |
+ } else { |
|
81 |
+ set adjustpending 0 |
|
82 |
+ gameslist_adjustsb_real |
|
83 |
+ } |
|
84 |
+} |
|
85 |
+ |
|
86 |
+set gameslist_scrollpos 0 |
|
87 |
+proc gameslist_adjustsb_real { } { |
|
88 |
+ global ntestwidget |
|
89 |
+ global gameslist_scrollpos |
|
90 |
+ update idletasks |
|
91 |
+ set height [winfo reqheight .gameslist.scrolled] |
|
92 |
+ set hviewport [winfo height .gameslist] |
|
93 |
+ if { [expr $gameslist_scrollpos+$hviewport]>$height } { |
|
94 |
+ set gameslist_scrollpos [expr $height - $hviewport] |
|
95 |
+ if { $gameslist_scrollpos<0 } { |
|
96 |
+ set gameslist_scrollpos 0 |
|
97 |
+ } |
|
98 |
+ } |
|
99 |
+ place .gameslist.scrolled -in .gameslist -x 0 -y -$gameslist_scrollpos |
|
100 |
+ if { $height<$hviewport } { |
|
101 |
+ .vs set 0 1 |
|
102 |
+ } else { |
|
103 |
+ set offset [expr 1.0*$gameslist_scrollpos/$height] |
|
104 |
+ .vs set $offset [expr $offset+1.0*$hviewport/$height] |
|
105 |
+ } |
|
106 |
+} |
|
107 |
+ |
|
108 |
+proc gameslist_yview { cmd args } { |
|
109 |
+ global gameslist_scrollpos |
|
110 |
+ #puts "$cmd $args" |
|
111 |
+ update idletasks |
|
112 |
+ set height [winfo reqheight .gameslist.scrolled] |
|
113 |
+ set hviewport [winfo height .gameslist] |
|
114 |
+ if { [string compare $cmd "moveto" ] == 0 } { |
|
115 |
+ set amount [lindex $args 0] |
|
116 |
+ if { $height<$hviewport } { |
|
117 |
+ set gameslist_scrollpos 0 |
|
118 |
+ } else { |
|
119 |
+ set fraccion [expr 1.0*$hviewport/$height] |
|
120 |
+ if { $amount<0.0 } { |
|
121 |
+ set gameslist_scrollpos 0 |
|
122 |
+ } elseif { $amount > [expr 1.0-$fraccion ] } { |
|
123 |
+ set gameslist_scrollpos [expr $height-$hviewport] |
|
124 |
+ } else { |
|
125 |
+ set gameslist_scrollpos [expr $height*$amount] |
|
126 |
+ } |
|
127 |
+ } |
|
128 |
+ } elseif { [string compare $cmd "scroll" ] == 0 } { |
|
129 |
+ set amount [lindex $args 0] |
|
130 |
+ set unit [lindex $args 1] |
|
131 |
+ if { [string compare $unit "pages"]==0 } { |
|
132 |
+ set gameslist_scrollpos [expr $gameslist_scrollpos + $amount * $hviewport] |
|
133 |
+ if { $gameslist_scrollpos < 0 } { |
|
134 |
+ set gameslist_scrollpos 0 |
|
135 |
+ } |
|
136 |
+ } elseif { [string compare $unit "units"]==0 } { |
|
137 |
+ set unit 30 |
|
138 |
+ set gameslist_scrollpos [expr $gameslist_scrollpos + $amount * $unit] |
|
139 |
+ if { $gameslist_scrollpos < 0 } { |
|
140 |
+ set gameslistgameslist_scrollpos 0 |
|
141 |
+ } |
|
142 |
+ } elseif { [string compare $unit "mousies"]==0 } { |
|
143 |
+ set unit 120 |
|
144 |
+ if { $amount<0 } { |
|
145 |
+ set amount 1 |
|
146 |
+ } else { |
|
147 |
+ set amount -1 |
|
148 |
+ } |
|
149 |
+ set gameslist_scrollpos [expr $gameslist_scrollpos + $amount * $unit] |
|
150 |
+ if { $gameslist_scrollpos < 0 } { |
|
151 |
+ set gameslist_scrollpos 0 |
|
152 |
+ } |
|
153 |
+ } else { |
|
154 |
+ } |
|
155 |
+ } else { |
|
156 |
+ #puts "ERROR: gameslist_yview $cmd $args" |
|
157 |
+ } |
|
158 |
+ gameslist_adjustsb |
|
159 |
+} |
|
160 |
+ |
|
161 |
+proc calcwidth_list { } { |
|
162 |
+ set width [expr [winfo width .]-[.vs cget -width]-2] |
|
163 |
+ return $width |
|
164 |
+} |
|
165 |
+ |
|
166 |
+proc setwidth_list { width } { |
|
167 |
+ if { $width<=0 } { |
|
168 |
+ return |
|
169 |
+ } |
|
170 |
+ catch { image delete spacer } |
|
171 |
+ image create photo spacer |
|
172 |
+ spacer put gray -to [expr $width -1] 0 |
|
173 |
+ .gameslist.scrolled.spacer configure -image spacer |
|
174 |
+} |
|
215 | 175 |
|
216 |
- # Retrieve the path where the scrollable contents go. |
|
217 |
- set sf [sframe content .gameslist] |
|
218 | 176 |
|
219 |
- set pagesize 30 |
|
177 |
+set imagelist [list] |
|
178 |
+proc redraw_list { page } { |
|
179 |
+ global games snapsdir imagelist small |
|
180 |
+ set w . |
|
181 |
+ catch {destroy .gameslist} |
|
182 |
+ catch {destroy .vs} |
|
183 |
+ catch { foreach i $imagelist { image delete $i } } |
|
184 |
+ set imagelist [list] |
|
185 |
+ frame .gameslist |
|
186 |
+ scrollbar .vs -command gameslist_yview -width 10 |
|
187 |
+ pack .gameslist -side left -expand true -fill both |
|
188 |
+ pack .vs -side left -expand false -fill y |
|
189 |
+ set sf [frame .gameslist.scrolled -borderwidth 0] |
|
190 |
+ catch { image delete spacer } |
|
191 |
+ image create photo spacer |
|
192 |
+ label $sf.spacer -image spacer |
|
193 |
+ grid $sf.spacer -column 0 -row 0 |
|
194 |
+ setwidth_list [calcwidth_list] |
|
195 |
+ place $sf -in .gameslist -x 0 -y 0 |
|
196 |
+ focus $sf |
|
197 |
+ bind $sf <MouseWheel> "gameslist_yview %D mousies" |
|
198 |
+ bind all <Button-4> \ |
|
199 |
+ {event generate [focus -displayof %W] <MouseWheel> -delta 120} |
|
200 |
+ bind all <Button-5> \ |
|
201 |
+ {event generate [focus -displayof %W] <MouseWheel> -delta -120} |
|
202 |
+ .vs set 0 1 |
|
203 |
+ bind . <Configure> "" |
|
204 |
+ if { $small == 0 } { |
|
205 |
+ set pagesize 30 |
|
206 |
+ } else { |
|
207 |
+ set pagesize 4 |
|
208 |
+ } |
|
220 | 209 |
frame $sf.buttonstop |
221 | 210 |
add_navibuttons $page $pagesize $sf.buttonstop |
222 |
- pack $sf.buttonstop -side top -fill x -expand true |
|
223 |
- |
|
211 |
+ grid $sf.buttonstop -row 0 -column 0 |
|
212 |
+ set cf [frame $sf.content] |
|
213 |
+ grid $cf -row 1 -column 0 |
|
224 | 214 |
set n 0 |
225 | 215 |
foreach i $games { |
226 | 216 |
if { $n<[expr $page*$pagesize] || $n>=[expr $page*$pagesize+$pagesize] } { |
227 | 217 |
incr n |
228 | 218 |
continue |
229 | 219 |
} |
230 |
- set f [frame $sf.f$n -relief raised -borderwidth 15] |
|
231 |
- button $f.nombre -text "$i" -command "exec mame $i" |
|
232 |
- pack $f.nombre -side left -fill both -expand true |
|
233 |
- bind $f <1> "event generate $f.nombre <1> |
|
234 |
- $f.nombre invoke |
|
235 |
- after 100 \"event generate $f.nombre <ButtonRelease-1>\"" |
|
220 |
+ set f [frame $cf.f$n -relief raised -borderwidth 15] |
|
236 | 221 |
set imgfile $snapsdir/[set i].png |
222 |
+ set hasimg 0 |
|
223 |
+ set im1 "" |
|
237 | 224 |
if { [file isfile $imgfile] } { |
238 | 225 |
puts "$n $imgfile" |
239 | 226 |
set im1 [image create photo -file $imgfile] |
240 |
- set xsize [lindex [read_png_header $imgfile] 0] |
|
227 |
+ set xsize [image width $im1] |
|
241 | 228 |
if { $xsize<=384 } { |
242 |
- set im2 [image create photo] |
|
243 |
- $im2 copy $im1 -zoom 2 2 |
|
244 |
- label $f.img -image $im2 |
|
245 |
- } else { |
|
246 |
- label $f.img -image $im1 |
|
247 |
- } |
|
248 |
- pack $f.img -side left -fill none -expand false |
|
229 |
+ set oldim1 $im1 |
|
230 |
+ set im1 [image create photo] |
|
231 |
+ $im1 copy $oldim1 -zoom 2 2 |
|
232 |
+ catch { image delete $oldim1} |
|
233 |
+ } |
|
234 |
+ lappend imagelist $im1 |
|
235 |
+ set hasimg 1 |
|
249 | 236 |
} |
250 |
- pack $f -side top -fill x -expand true |
|
237 |
+ if { $small != 0 } { |
|
238 |
+ if { $hasimg != 0 } { |
|
239 |
+ button $f.img -image $im1 -command "exec mame $i" |
|
240 |
+ pack $f.img -side left -fill both -expand true |
|
241 |
+ } else { |
|
242 |
+ button $f.nombre -text "$i" -command "exec mame $i" |
|
243 |
+ pack $f.nombre -side left -fill both -expand true |
|
244 |
+ } |
|
245 |
+ bind $f <1> "event generate $f.nombre <1> |
|
246 |
+ $f.nombre invoke |
|
247 |
+ after 100 \"event generate $f.nombre <ButtonRelease-1>\"" |
|
248 |
+ grid $f -column [expr $n%2] -row [expr $n/2] |
|
249 |
+ } else { |
|
250 |
+ button $f.nombre -text "$i" -command "exec mame $i" |
|
251 |
+ pack $f.nombre -side left -fill both -expand true |
|
252 |
+ bind $f <1> "event generate $f.nombre <1> |
|
253 |
+ $f.nombre invoke |
|
254 |
+ after 100 \"event generate $f.nombre <ButtonRelease-1>\"" |
|
255 |
+ if { $hasimg != 0 } { |
|
256 |
+ label $f.img -image $im1 |
|
257 |
+ pack $f.img -side left -fill none -expand false |
|
258 |
+ } |
|
259 |
+ pack $f -side top -fill x -expand true |
|
260 |
+ } |
|
251 | 261 |
incr n |
252 | 262 |
} |
253 | 263 |
frame $sf.buttonsbottom |
254 | 264 |
add_navibuttons $page $pagesize $sf.buttonsbottom |
255 |
- pack $sf.buttonsbottom -side top -fill x -expand true |
|
265 |
+ grid $sf.buttonsbottom -row 2 -column 0 |
|
266 |
+ bind . <Configure> "gameslist_wmevent $w %w %h %x %y %d" |
|
256 | 267 |
} |
257 | 268 |
|
258 | 269 |
redraw_list 0 |
1 | 1 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,260 @@ |
1 |
+#!/usr/bin/wish |
|
2 |
+ |
|
3 |
+# apt-get install libtk-img |
|
4 |
+package require Img |
|
5 |
+ |
|
6 |
+ |
|
7 |
+option add *font "-*-*-*-*-*-*-34-*-*-*-*-*-*-*" |
|
8 |
+option add *.borderwidth 1 |
|
9 |
+set tk_strictMotif |
|
10 |
+ |
|
11 |
+wm title . "mamegui.tcl" |
|
12 |
+ |
|
13 |
+ |
|
14 |
+#------------------------------------- |
|
15 |
+# Scrolled frame implementation |
|
16 |
+# http://wiki.tcl.tk/9223 |
|
17 |
+#------------------------------------- |
|
18 |
+# sframe.tcl |
|
19 |
+# Paul Walton |
|
20 |
+# Create a ttk-compatible, scrollable frame widget. |
|
21 |
+# Usage: |
|
22 |
+# sframe new <path> ?-toplevel true? ?-anchor nsew? |
|
23 |
+# -> <path> |
|
24 |
+# |
|
25 |
+# sframe content <path> |
|
26 |
+# -> <path of child frame where the content should go> |
|
27 |
+ |
|
28 |
+namespace eval sframe { |
|
29 |
+ namespace ensemble create |
|
30 |
+ namespace export * |
|
31 |
+ |
|
32 |
+ # Create a scrollable frame or window. |
|
33 |
+ proc new {path args} { |
|
34 |
+ # Use the ttk theme's background for the canvas and toplevel |
|
35 |
+ set bg [ttk::style lookup TFrame -background] |
|
36 |
+ if { [ttk::style theme use] eq "aqua" } { |
|
37 |
+ # Use a specific color on the aqua theme as 'ttk::style lookup' is not accurate. |
|
38 |
+ set bg "#e9e9e9" |
|
39 |
+ } |
|
40 |
+ |
|
41 |
+ # Create the main frame or toplevel. |
|
42 |
+ if { [dict exists $args -toplevel] && [dict get $args -toplevel] } { |
|
43 |
+ toplevel $path -bg $bg |
|
44 |
+ } else { |
|
45 |
+ ttk::frame $path |
|
46 |
+ } |
|
47 |
+ |
|
48 |
+ # Create a scrollable canvas with scrollbars which will always be the same size as the main frame. |
|
49 |
+ set canvas [canvas $path.canvas -bg $bg -bd 0 -highlightthickness 0 -yscrollcommand [list $path.scrolly set] -xscrollcommand [list $path.scrollx set]] |
|
50 |
+ ttk::scrollbar $path.scrolly -orient vertical -command [list $canvas yview] |
|
51 |
+ ttk::scrollbar $path.scrollx -orient horizontal -command [list $canvas xview] |
|
52 |
+ |
|
53 |
+ # Create a container frame which will always be the same size as the canvas or content, whichever is greater. |
|
54 |
+ # This allows the child content frame to be properly packed and also is a surefire way to use the proper ttk background. |
|
55 |
+ set container [ttk::frame $canvas.container] |
|
56 |
+ pack propagate $container 0 |
|
57 |
+ |
|
58 |
+ # Create the content frame. Its size will be determined by its contents. This is useful for determining if the |
|
59 |
+ # scrollbars need to be shown. |
|
60 |
+ set content [ttk::frame $container.content] |
|
61 |
+ |
|
62 |
+ # Pack the content frame and place the container as a canvas item. |
|
63 |
+ set anchor "n" |
|
64 |
+ if { [dict exists $args -anchor] } { |
|
65 |
+ set anchor [dict get $args -anchor] |
|
66 |
+ } |
|
67 |
+ pack $content -anchor $anchor |
|
68 |
+ $canvas create window 0 0 -window $container -anchor nw |
|
69 |
+ |
|
70 |
+ # Grid the scrollable canvas sans scrollbars within the main frame. |
|
71 |
+ grid $canvas -row 0 -column 0 -sticky nsew |
|
72 |
+ grid rowconfigure $path 0 -weight 1 |
|
73 |
+ grid columnconfigure $path 0 -weight 1 |
|
74 |
+ |
|
75 |
+ # Make adjustments when the the sframe is resized or the contents change size. |
|
76 |
+ bind $path.canvas <Expose> [list [namespace current]::resize $path] |
|
77 |
+ |
|
78 |
+ # Mousewheel bindings for scrolling. |
|
79 |
+ bind [winfo toplevel $path] <MouseWheel> [list +[namespace current] scroll $path yview %W %D] |
|
80 |
+ bind [winfo toplevel $path] <Shift-MouseWheel> [list +[namespace current] scroll $path xview %W %D] |
|
81 |
+ |
|
82 |
+ return $path |
|
83 |
+ } |
|
84 |
+ |
|
85 |
+ |
|
86 |
+ # Given the toplevel path of an sframe widget, return the path of the child frame suitable for content. |
|
87 |
+ proc content {path} { |
|
88 |
+ return $path.canvas.container.content |
|
89 |
+ } |
|
90 |
+ |
|
91 |
+ |
|
92 |
+ # Make adjustments when the the sframe is resized or the contents change size. |
|
93 |
+ proc resize {path} { |
|
94 |
+ set canvas $path.canvas |
|
95 |
+ set container $canvas.container |
|
96 |
+ set content $container.content |
|
97 |
+ |
|
98 |
+ # Set the size of the container. At a minimum use the same width & height as the canvas. |
|
99 |
+ set width [winfo width $canvas] |
|
100 |
+ set height [winfo height $canvas] |
|
101 |
+ |
|
102 |
+ # If the requested width or height of the content frame is greater then use that width or height. |
|
103 |
+ if { [winfo reqwidth $content] > $width } { |
|
104 |
+ set width [winfo reqwidth $content] |
|
105 |
+ } |
|
106 |
+ if { [winfo reqheight $content] > $height } { |
|
107 |
+ set height [winfo reqheight $content] |
|
108 |
+ } |
|
109 |
+ $container configure -width $width -height $height |
|
110 |
+ |
|
111 |
+ # Configure the canvas's scroll region to match the height and width of the container. |
|
112 |
+ $canvas configure -scrollregion "0 0 $width $height" |
|
113 |
+ |
|
114 |
+ # Show or hide the scrollbars as necessary. |
|
115 |
+ # Horizontal scrolling. |
|
116 |
+ if { [winfo reqwidth $content] > [winfo width $canvas] } { |
|
117 |
+ grid $path.scrollx -row 1 -column 0 -sticky ew |
|
118 |
+ } else { |
|
119 |
+ grid forget $path.scrollx |
|
120 |
+ } |
|
121 |
+ # Vertical scrolling. |
|
122 |
+ if { [winfo reqheight $content] > [winfo height $canvas] } { |
|
123 |
+ grid $path.scrolly -row 0 -column 1 -sticky ns |
|
124 |
+ } else { |
|
125 |
+ grid forget $path.scrolly |
|
126 |
+ } |
|
127 |
+ return |
|
128 |
+ } |
|
129 |
+ |
|
130 |
+ |
|
131 |
+ # Handle mousewheel scrolling. |
|
132 |
+ proc scroll {path view W D} { |
|
133 |
+ if { [winfo exists $path.canvas] && [string match $path.canvas* $W] } { |
|
134 |
+ $path.canvas $view scroll [expr {-$D}] units |
|
135 |
+ } |
|
136 |
+ return |
|
137 |
+ } |
|
138 |
+} |
|
139 |
+#------------------------------------- |
|
140 |
+# End of Scrolled frame implementation |
|
141 |
+#------------------------------------- |
|
142 |
+ |
|
143 |
+#------------------------------------- |
|
144 |
+# Read png header implementation |
|
145 |
+# http://wiki.tcl.tk/759 |
|
146 |
+#------------------------------------- |
|
147 |
+proc read_png_header {file} { |
|
148 |
+ set fh [open $file r] |
|
149 |
+ fconfigure $fh -encoding binary -translation binary -eofchar {} |
|
150 |
+ if {[read $fh 8] != "\x89PNG\r\n\x1a\n"} { close $fh; return } |
|
151 |
+ binary scan [read $fh 8] Ia4 len type |
|
152 |
+ set r [read $fh $len] |
|
153 |
+ if {![eof $fh] && $type == "IHDR"} { |
|
154 |
+ binary scan $r IIccccc width height depth color compression filter interlace |
|
155 |
+ close $fh |
|
156 |
+ return [list $width $height $depth $color $compression $filter $interlace] |
|
157 |
+ } |
|
158 |
+ close $fh |
|
159 |
+ return |
|
160 |
+} |
|
161 |
+#------------------------------------- |
|
162 |
+# End of Read png header implementation |
|
163 |
+#------------------------------------- |
|
164 |
+ |
|
165 |
+ |
|
166 |
+# files locations |
|
167 |
+set mameconf "/etc/mame/mame.ini" |
|
168 |
+set snapsdir "/usr/local/share/games/mame/snaps/" |
|
169 |
+set catverini "/usr/local/share/gnome-video-arcade/catver.ini" |
|
170 |
+set historydat "/usr/local/share/gnome-video-arcade/history.dat" |
|
171 |
+set nplayersini "/usr/share/games/mame/data/nplayers.ini" |
|
172 |
+ |
|
173 |
+set rompaths [split [regsub {\$HOME} [lindex [split [exec grep ^rompath $mameconf ] " "] end] "$env(HOME)\1"] ";"] |
|
174 |
+ |
|
175 |
+set games "dynablst gauntlet snowbro2" |
|
176 |
+ |
|
177 |
+set gameslist [split [exec sh -c "grep =4P.sim $nplayersini | cut -d '=' -f 1 | tr '\n' ':' | head -20"] ":"] |
|
178 |
+ |
|
179 |
+set gamesnoalt [lsort [split [exec sh -c " cat $historydat | grep \"^.info=\" | cut -d '=' -f 2 | cut -d ',' -f 1 | tr '\n' ':'"] ":"]] |
|
180 |
+ |
|
181 |
+foreach i $gameslist { |
|
182 |
+ if {[lsearch -glob $games $i]==-1 && [lsearch -glob -sort $gamesnoalt $i]!=-1} { |
|
183 |
+ lappend games $i |
|
184 |
+ } |
|
185 |
+} |
|
186 |
+ |
|
187 |
+foreach i $rompaths { |
|
188 |
+ puts $i |
|
189 |
+} |
|
190 |
+ |
|
191 |
+# The UI |
|
192 |
+proc add_navibuttons { page pagesize parent} { |
|
193 |
+ global games |
|
194 |
+ set n [llength $games] |
|
195 |
+ if { $page>0 } { |
|
196 |
+ button $parent.prev -text "<<< [expr $page-1+1] <<< " -command "redraw_list [expr $page-1]" |
|
197 |
+ pack $parent.prev -side left -fill none -expand false |
|
198 |
+ } |
|
199 |
+ set totalpages [expr $n/$pagesize] |
|
200 |
+ label $parent.current -text "[expr $page+1] of [expr $totalpages+1]" |
|
201 |
+ pack $parent.current -side left -fill none -expand false |
|
202 |
+ if { $page<$totalpages } { |
|
203 |
+ button $parent.next -text ">>> [expr $page+1+1] >>>" -command "redraw_list [expr $page+1]" |
|
204 |
+ pack $parent.next -side left -fill none -expand false |
|
205 |
+ } |
|
206 |
+ |
|
207 |
+} |
|
208 |
+ |
|
209 |
+proc redraw_list { page } { |
|
210 |
+ global games snapsdir |
|
211 |
+ catch { destroy .gameslist } |
|
212 |
+ # Use the -toplevel option to create a scrollable toplevel window. |
|
213 |
+ sframe new .gameslist -anchor w |
|
214 |
+ pack .gameslist -side top -fill both -expand true |
|
215 |
+ |
|
216 |
+ # Retrieve the path where the scrollable contents go. |
|
217 |
+ set sf [sframe content .gameslist] |
|
218 |
+ |
|
219 |
+ set pagesize 30 |
|
220 |
+ frame $sf.buttonstop |
|
221 |
+ add_navibuttons $page $pagesize $sf.buttonstop |
|
222 |
+ pack $sf.buttonstop -side top -fill x -expand true |
|
223 |
+ |
|
224 |
+ set n 0 |
|
225 |
+ foreach i $games { |
|
226 |
+ if { $n<[expr $page*$pagesize] || $n>=[expr $page*$pagesize+$pagesize] } { |
|
227 |
+ incr n |
|
228 |
+ continue |
|
229 |
+ } |
|
230 |
+ set f [frame $sf.f$n -relief raised -borderwidth 15] |
|
231 |
+ button $f.nombre -text "$i" -command "exec mame $i" |
|
232 |
+ pack $f.nombre -side left -fill both -expand true |
|
233 |
+ bind $f <1> "event generate $f.nombre <1> |
|
234 |
+ $f.nombre invoke |
|
235 |
+ after 100 \"event generate $f.nombre <ButtonRelease-1>\"" |
|
236 |
+ set imgfile $snapsdir/[set i].png |
|
237 |
+ if { [file isfile $imgfile] } { |
|
238 |
+ puts "$n $imgfile" |
|
239 |
+ set im1 [image create photo -file $imgfile] |
|
240 |
+ set xsize [lindex [read_png_header $imgfile] 0] |
|
241 |
+ if { $xsize<=384 } { |
|
242 |
+ set im2 [image create photo] |
|
243 |
+ $im2 copy $im1 -zoom 2 2 |
|
244 |
+ label $f.img -image $im2 |
|
245 |
+ } else { |
|
246 |
+ label $f.img -image $im1 |
|
247 |
+ } |
|
248 |
+ pack $f.img -side left -fill none -expand false |
|
249 |
+ } |
|
250 |
+ pack $f -side top -fill x -expand true |
|
251 |
+ incr n |
|
252 |
+ } |
|
253 |
+ frame $sf.buttonsbottom |
|
254 |
+ add_navibuttons $page $pagesize $sf.buttonsbottom |
|
255 |
+ pack $sf.buttonsbottom -side top -fill x -expand true |
|
256 |
+} |
|
257 |
+ |
|
258 |
+redraw_list 0 |
|
259 |
+bind . <Escape> { exit 0 } |
|
260 |
+ |