~ubuntu-branches/ubuntu/gutsy/amsn/gutsy

« back to all changes in this revision

Viewing changes to plugins/BWidget-1.7.0/utils.tcl

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Karkoulis
  • Date: 2006-01-04 15:26:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104152602-ipe1yg00rl3nlklv
Tags: 0.95-1
New Upstream Release (closes: #345052, #278575).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# ----------------------------------------------------------------------------
2
 
#  utils.tcl
3
 
#  This file is part of Unifix BWidget Toolkit
4
 
#  $Id: utils.tcl,v 1.1 2004/03/04 00:39:57 airadier Exp $
5
 
# ----------------------------------------------------------------------------
6
 
#  Index of commands:
7
 
#     - GlobalVar::exists
8
 
#     - GlobalVar::setvarvar
9
 
#     - GlobalVar::getvarvar
10
 
#     - BWidget::assert
11
 
#     - BWidget::clonename
12
 
#     - BWidget::get3dcolor
13
 
#     - BWidget::XLFDfont
14
 
#     - BWidget::place
15
 
#     - BWidget::grab
16
 
#     - BWidget::focus
17
 
# ----------------------------------------------------------------------------
18
 
 
19
 
namespace eval GlobalVar {
20
 
    proc use {} {}
21
 
}
22
 
 
23
 
 
24
 
namespace eval BWidget {
25
 
    variable _top
26
 
    variable _gstack {}
27
 
    variable _fstack {}
28
 
    proc use {} {}
29
 
}
30
 
 
31
 
 
32
 
# ----------------------------------------------------------------------------
33
 
#  Command GlobalVar::exists
34
 
# ----------------------------------------------------------------------------
35
 
proc GlobalVar::exists { varName } {
36
 
    return [uplevel \#0 [list info exists $varName]]
37
 
}
38
 
 
39
 
 
40
 
# ----------------------------------------------------------------------------
41
 
#  Command GlobalVar::setvar
42
 
# ----------------------------------------------------------------------------
43
 
proc GlobalVar::setvar { varName value } {
44
 
    return [uplevel \#0 [list set $varName $value]]
45
 
}
46
 
 
47
 
 
48
 
# ----------------------------------------------------------------------------
49
 
#  Command GlobalVar::getvar
50
 
# ----------------------------------------------------------------------------
51
 
proc GlobalVar::getvar { varName } {
52
 
    return [uplevel \#0 [list set $varName]]
53
 
}
54
 
 
55
 
 
56
 
# ----------------------------------------------------------------------------
57
 
#  Command GlobalVar::tracevar
58
 
# ----------------------------------------------------------------------------
59
 
proc GlobalVar::tracevar { cmd varName args } {
60
 
    return [uplevel \#0 [list trace $cmd $varName] $args]
61
 
}
62
 
 
63
 
 
64
 
 
65
 
# ----------------------------------------------------------------------------
66
 
#  Command BWidget::lreorder
67
 
# ----------------------------------------------------------------------------
68
 
proc BWidget::lreorder { list neworder } {
69
 
    set pos     0
70
 
    set newlist {}
71
 
    foreach e $neworder {
72
 
        if { [lsearch -exact $list $e] != -1 } {
73
 
            lappend newlist $e
74
 
            set tabelt($e)  1
75
 
        }
76
 
    }
77
 
    set len [llength $newlist]
78
 
    if { !$len } {
79
 
        return $list
80
 
    }
81
 
    if { $len == [llength $list] } {
82
 
        return $newlist
83
 
    }
84
 
    set pos 0
85
 
    foreach e $list {
86
 
        if { ![info exists tabelt($e)] } {
87
 
            set newlist [linsert $newlist $pos $e]
88
 
        }
89
 
        incr pos
90
 
    }
91
 
    return $newlist
92
 
}
93
 
 
94
 
 
95
 
# ----------------------------------------------------------------------------
96
 
#  Command BWidget::assert
97
 
# ----------------------------------------------------------------------------
98
 
proc BWidget::assert { exp {msg ""}} {
99
 
    set res [uplevel 1 expr $exp]
100
 
    if { !$res} {
101
 
        if { $msg == "" } {
102
 
            return -code error "Assertion failed: {$exp}"
103
 
        } else {
104
 
            return -code error $msg
105
 
        }
106
 
    }
107
 
}
108
 
 
109
 
 
110
 
# ----------------------------------------------------------------------------
111
 
#  Command BWidget::clonename
112
 
# ----------------------------------------------------------------------------
113
 
proc BWidget::clonename { menu } {
114
 
    set path     ""
115
 
    set menupath ""
116
 
    set found    0
117
 
    foreach widget [lrange [split $menu "."] 1 end] {
118
 
        if { $found || [winfo class "$path.$widget"] == "Menu" } {
119
 
            set found 1
120
 
            append menupath "#" $widget
121
 
            append path "." $menupath
122
 
        } else {
123
 
            append menupath "#" $widget
124
 
            append path "." $widget
125
 
        }
126
 
    }
127
 
    return $path
128
 
}
129
 
 
130
 
 
131
 
# ----------------------------------------------------------------------------
132
 
#  Command BWidget::getname
133
 
# ----------------------------------------------------------------------------
134
 
proc BWidget::getname { name } {
135
 
    if { [string length $name] } {
136
 
        set text [option get . "${name}Name" ""]
137
 
        if { [string length $text] } {
138
 
            return [parsetext $text]
139
 
        }
140
 
    }
141
 
    return {}
142
 
 }
143
 
 
144
 
 
145
 
# ----------------------------------------------------------------------------
146
 
#  Command BWidget::parsetext
147
 
# ----------------------------------------------------------------------------
148
 
proc BWidget::parsetext { text } {
149
 
    set result ""
150
 
    set index  -1
151
 
    set start  0
152
 
    while { [string length $text] } {
153
 
        set idx [string first "&" $text]
154
 
        if { $idx == -1 } {
155
 
            append result $text
156
 
            set text ""
157
 
        } else {
158
 
            set char [string index $text [expr {$idx+1}]]
159
 
            if { $char == "&" } {
160
 
                append result [string range $text 0 $idx]
161
 
                set    text   [string range $text [expr {$idx+2}] end]
162
 
                set    start  [expr {$start+$idx+1}]
163
 
            } else {
164
 
                append result [string range $text 0 [expr {$idx-1}]]
165
 
                set    text   [string range $text [expr {$idx+1}] end]
166
 
                incr   start  $idx
167
 
                set    index  $start
168
 
            }
169
 
        }
170
 
    }
171
 
    return [list $result $index]
172
 
}
173
 
 
174
 
 
175
 
# ----------------------------------------------------------------------------
176
 
#  Command BWidget::get3dcolor
177
 
# ----------------------------------------------------------------------------
178
 
proc BWidget::get3dcolor { path bgcolor } {
179
 
    foreach val [winfo rgb $path $bgcolor] {
180
 
        lappend dark [expr {60*$val/100}]
181
 
        set tmp1 [expr {14*$val/10}]
182
 
        if { $tmp1 > 65535 } {
183
 
            set tmp1 65535
184
 
        }
185
 
        set tmp2 [expr {(65535+$val)/2}]
186
 
        lappend light [expr {($tmp1 > $tmp2) ? $tmp1:$tmp2}]
187
 
    }
188
 
    return [list [eval format "#%04x%04x%04x" $dark] [eval format "#%04x%04x%04x" $light]]
189
 
}
190
 
 
191
 
 
192
 
# ----------------------------------------------------------------------------
193
 
#  Command BWidget::XLFDfont
194
 
# ----------------------------------------------------------------------------
195
 
proc BWidget::XLFDfont { cmd args } {
196
 
    switch -- $cmd {
197
 
        create {
198
 
            set font "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
199
 
        }
200
 
        configure {
201
 
            set font [lindex $args 0]
202
 
            set args [lrange $args 1 end]
203
 
        }
204
 
        default {
205
 
            return -code error "XLFDfont: commande incorrect: $cmd"
206
 
        }
207
 
    }
208
 
    set lfont [split $font "-"]
209
 
    if { [llength $lfont] != 15 } {
210
 
        return -code error "XLFDfont: description XLFD incorrect: $font"
211
 
    }
212
 
 
213
 
    foreach {option value} $args {
214
 
        switch -- $option {
215
 
            -foundry { set index 1 }
216
 
            -family  { set index 2 }
217
 
            -weight  { set index 3 }
218
 
            -slant   { set index 4 }
219
 
            -size    { set index 7 }
220
 
            default  { return -code error "XLFDfont: option incorrecte: $option" }
221
 
        }
222
 
        set lfont [lreplace $lfont $index $index $value]
223
 
    }
224
 
    return [join $lfont "-"]
225
 
}
226
 
 
227
 
 
228
 
 
229
 
# ----------------------------------------------------------------------------
230
 
#  Command BWidget::place
231
 
# ----------------------------------------------------------------------------
232
 
#
233
 
# Notes:
234
 
#  For Windows systems with more than one monitor the available screen area may
235
 
#  have negative positions. Geometry settings with negative numbers are used
236
 
#  under X to place wrt the right or bottom of the screen. On windows, Tk
237
 
#  continues to do this. However, a geometry such as 100x100+-200-100 can be
238
 
#  used to place a window onto a secondary monitor. Passing the + gets Tk
239
 
#  to pass the remainder unchanged so the Windows manager then handles -200
240
 
#  which is a position on the left hand monitor.
241
 
#  I've tested this for left, right, above and below the primary monitor.
242
 
#  Currently there is no way to ask Tk the extent of the Windows desktop in 
243
 
#  a multi monitor system. Nor what the legal co-ordinate range might be.
244
 
#
245
 
proc BWidget::place { path w h args } {
246
 
    variable _top
247
 
 
248
 
    update idletasks
249
 
    set reqw [winfo reqwidth  $path]
250
 
    set reqh [winfo reqheight $path]
251
 
    if { $w == 0 } {set w $reqw}
252
 
    if { $h == 0 } {set h $reqh}
253
 
 
254
 
    set arglen [llength $args]
255
 
    if { $arglen > 3 } {
256
 
        return -code error "BWidget::place: bad number of argument"
257
 
    }
258
 
 
259
 
    if { $arglen > 0 } {
260
 
        set where [lindex $args 0]
261
 
        set list  [list "at" "center" "left" "right" "above" "below"]
262
 
        set idx   [lsearch $list $where]
263
 
        if { $idx == -1 } {
264
 
            return -code error [BWidget::badOptionString position $where $list]
265
 
        }
266
 
        if { $idx == 0 } {
267
 
            set err [catch {
268
 
                # purposely removed the {} around these expressions - [PT]
269
 
                set x [expr int([lindex $args 1])]
270
 
                set y [expr int([lindex $args 2])]
271
 
            }]
272
 
            if { $err } {
273
 
                return -code error "BWidget::place: incorrect position"
274
 
            }
275
 
            if {$::tcl_platform(platform) == "windows"} {
276
 
                # handle windows multi-screen. -100 != +-100
277
 
                if {[string index [lindex $args 1] 0] != "-"} {
278
 
                    set x "+$x"
279
 
                }
280
 
                if {[string index [lindex $args 2] 0] != "-"} {
281
 
                    set y "+$y"
282
 
                }
283
 
            } else {
284
 
                if { $x >= 0 } {
285
 
                    set x "+$x"
286
 
                }
287
 
                if { $y >= 0 } {
288
 
                    set y "+$y"
289
 
                }
290
 
            }
291
 
        } else {
292
 
            if { $arglen == 2 } {
293
 
                set widget [lindex $args 1]
294
 
                if { ![winfo exists $widget] } {
295
 
                    return -code error "BWidget::place: \"$widget\" does not exist"
296
 
                }
297
 
            } else {
298
 
                set widget .
299
 
            }
300
 
            set sw [winfo screenwidth  $path]
301
 
            set sh [winfo screenheight $path]
302
 
            if { $idx == 1 } {
303
 
                if { $arglen == 2 } {
304
 
                    # center to widget
305
 
                    set x0 [expr {[winfo rootx $widget] + ([winfo width  $widget] - $w)/2}]
306
 
                    set y0 [expr {[winfo rooty $widget] + ([winfo height $widget] - $h)/2}]
307
 
                } else {
308
 
                    # center to screen
309
 
                    set x0 [expr {([winfo screenwidth  $path] - $w)/2 - [winfo vrootx $path]}]
310
 
                    set y0 [expr {([winfo screenheight $path] - $h)/2 - [winfo vrooty $path]}]
311
 
                }
312
 
                set x "+$x0"
313
 
                set y "+$y0"
314
 
                if {$::tcl_platform(platform) != "windows"} {
315
 
                    if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]}
316
 
                    if { $x0 < 0 }      {set x "+0"}
317
 
                    if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]}
318
 
                    if { $y0 < 0 }      {set y "+0"}
319
 
                }
320
 
            } else {
321
 
                set x0 [winfo rootx $widget]
322
 
                set y0 [winfo rooty $widget]
323
 
                set x1 [expr {$x0 + [winfo width  $widget]}]
324
 
                set y1 [expr {$y0 + [winfo height $widget]}]
325
 
                if { $idx == 2 || $idx == 3 } {
326
 
                    set y "+$y0"
327
 
                    if {$::tcl_platform(platform) != "windows"} {
328
 
                        if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]}
329
 
                        if { $y0 < 0 }      {set y "+0"}
330
 
                    }
331
 
                    if { $idx == 2 } {
332
 
                        # try left, then right if out, then 0 if out
333
 
                        if { $x0 >= $w } {
334
 
                            set x "+[expr {$x0-$sw}]"
335
 
                        } elseif { $x1+$w <= $sw } {
336
 
                            set x "+$x1"
337
 
                        } else {
338
 
                            set x "+0"
339
 
                        }
340
 
                    } else {
341
 
                        # try right, then left if out, then 0 if out
342
 
                        if { $x1+$w <= $sw } {
343
 
                            set x "+$x1"
344
 
                        } elseif { $x0 >= $w } {
345
 
                            set x "+[expr {$x0-$sw}]"
346
 
                        } else {
347
 
                            set x "-0"
348
 
                        }
349
 
                    }
350
 
                } else {
351
 
                    set x "+$x0"
352
 
                    if {$::tcl_platform(platform) != "windows"} {
353
 
                        if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]}
354
 
                        if { $x0 < 0 }      {set x "+0"}
355
 
                    }
356
 
                    if { $idx == 4 } {
357
 
                        # try top, then bottom, then 0
358
 
                        if { $h <= $y0 } {
359
 
                            set y "+[expr {$y0-$sh}]"
360
 
                        } elseif { $y1+$h <= $sh } {
361
 
                            set y "+$y1"
362
 
                        } else {
363
 
                            set y "+0"
364
 
                        }
365
 
                    } else {
366
 
                        # try bottom, then top, then 0
367
 
                        if { $y1+$h <= $sh } {
368
 
                            set y "+$y1"
369
 
                        } elseif { $h <= $y0 } {
370
 
                            set y "+[expr {$y0-$sh}]"
371
 
                        } else {
372
 
                            set y "-0"
373
 
                        }
374
 
                    }
375
 
                }
376
 
            }
377
 
        }
378
 
        wm geometry $path "${w}x${h}${x}${y}"
379
 
    } else {
380
 
        wm geometry $path "${w}x${h}"
381
 
    }
382
 
    update idletasks
383
 
}
384
 
 
385
 
 
386
 
# ----------------------------------------------------------------------------
387
 
#  Command BWidget::grab
388
 
# ----------------------------------------------------------------------------
389
 
proc BWidget::grab { option path } {
390
 
    variable _gstack
391
 
 
392
 
    if { $option == "release" } {
393
 
        catch {::grab release $path}
394
 
        while { [llength $_gstack] } {
395
 
            set grinfo  [lindex $_gstack end]
396
 
            set _gstack [lreplace $_gstack end end]
397
 
            foreach {oldg mode} $grinfo {
398
 
                if { ![string equal $oldg $path] && [winfo exists $oldg] } {
399
 
                    if { $mode == "global" } {
400
 
                        catch {::grab -global $oldg}
401
 
                    } else {
402
 
                        catch {::grab $oldg}
403
 
                    }
404
 
                    return
405
 
                }
406
 
            }
407
 
        }
408
 
    } else {
409
 
        set oldg [::grab current]
410
 
        if { $oldg != "" } {
411
 
            lappend _gstack [list $oldg [::grab status $oldg]]
412
 
        }
413
 
        if { $option == "global" } {
414
 
            ::grab -global $path
415
 
        } else {
416
 
            ::grab $path
417
 
        }
418
 
    }
419
 
}
420
 
 
421
 
 
422
 
# ----------------------------------------------------------------------------
423
 
#  Command BWidget::focus
424
 
# ----------------------------------------------------------------------------
425
 
proc BWidget::focus { option path {refocus 1} } {
426
 
    variable _fstack
427
 
 
428
 
    if { $option == "release" } {
429
 
        while { [llength $_fstack] } {
430
 
            set oldf [lindex $_fstack end]
431
 
            set _fstack [lreplace $_fstack end end]
432
 
            if { ![string equal $oldf $path] && [winfo exists $oldf] } {
433
 
                if {$refocus} {catch {::focus -force $oldf}}
434
 
                return
435
 
            }
436
 
        }
437
 
    } elseif { $option == "set" } {
438
 
        lappend _fstack [::focus]
439
 
        ::focus -force $path
440
 
    }
441
 
}
442
 
 
443
 
# BWidget::refocus --
444
 
#
445
 
#       Helper function used to redirect focus from a container frame in 
446
 
#       a megawidget to a component widget.  Only redirects focus if
447
 
#       focus is already on the container.
448
 
#
449
 
# Arguments:
450
 
#       container       container widget to redirect from.
451
 
#       component       component widget to redirect to.
452
 
#
453
 
# Results:
454
 
#       None.
455
 
 
456
 
proc BWidget::refocus {container component} {
457
 
    if { [string equal $container [::focus]] } {
458
 
        ::focus $component
459
 
    }
460
 
    return
461
 
}
462
 
 
463
 
# BWidget::badOptionString --
464
 
#
465
 
#       Helper function to return a proper error string when an option
466
 
#       doesn't match a list of given options.
467
 
#
468
 
# Arguments:
469
 
#       type    A string that represents the type of option.
470
 
#       value   The value that is in-valid.
471
 
#       list    A list of valid options.
472
 
#
473
 
# Results:
474
 
#       None.
475
 
proc BWidget::badOptionString {type value list} {
476
 
    set last [lindex $list end]
477
 
    set list [lreplace $list end end]
478
 
    return "bad $type \"$value\": must be [join $list ", "], or $last"
479
 
}
480
 
 
481
 
 
482
 
proc BWidget::wrongNumArgsString { string } {
483
 
    return "wrong # args: should be \"$string\""
484
 
}
485
 
 
486
 
 
487
 
proc BWidget::read_file { file } {
488
 
    set fp [open $file]
489
 
    set x  [read $fp [file size $file]]
490
 
    close $fp
491
 
    return $x
492
 
}
493
 
 
494
 
 
495
 
proc BWidget::classes { class } {
496
 
    variable use
497
 
 
498
 
    ${class}::use
499
 
    set classes [list $class]
500
 
    if {![info exists use($class)]} { return }
501
 
    foreach class $use($class) {
502
 
        eval lappend classes [classes $class]
503
 
    }
504
 
    return [lsort -unique $classes]
505
 
}
506
 
 
507
 
 
508
 
proc BWidget::library { args } {
509
 
    variable use
510
 
 
511
 
    set libs    [list widget init utils]
512
 
    set classes [list]
513
 
    foreach class $args {
514
 
        ${class}::use
515
 
        eval lappend classes [classes $class]
516
 
    }
517
 
 
518
 
    eval lappend libs [lsort -unique $classes]
519
 
 
520
 
    set library ""
521
 
    foreach lib $libs {
522
 
        if {![info exists use($lib,file)]} {
523
 
            set file [file join $::BWIDGET::LIBRARY $lib.tcl]
524
 
        } else {
525
 
            set file [file join $::BWIDGET::LIBRARY $use($lib,file).tcl]
526
 
        }
527
 
        append library [read_file $file]
528
 
    }
529
 
 
530
 
    return $library
531
 
}
532
 
 
533
 
 
534
 
proc BWidget::inuse { class } {
535
 
    variable ::Widget::_inuse
536
 
 
537
 
    if {![info exists _inuse($class)]} { return 0 }
538
 
    return [expr $_inuse($class) > 0]
539
 
}
540
 
 
541
 
 
542
 
proc BWidget::write { filename {mode w} } {
543
 
    variable use
544
 
 
545
 
    if {![info exists use(classes)]} { return }
546
 
 
547
 
    set classes [list]
548
 
    foreach class $use(classes) {
549
 
        if {![inuse $class]} { continue }
550
 
        lappend classes $class
551
 
    }
552
 
 
553
 
    set fp [open $filename $mode]
554
 
    puts $fp [eval library $classes]
555
 
    close $fp
556
 
 
557
 
    return
558
 
}
559
 
 
560
 
 
561
 
# BWidget::bindMouseWheel --
562
 
#
563
 
#       Bind mouse wheel actions to a given widget.
564
 
#
565
 
# Arguments:
566
 
#       widget - The widget to bind.
567
 
#
568
 
# Results:
569
 
#       None.
570
 
proc BWidget::bindMouseWheel { widget } {
571
 
    bind $widget <MouseWheel>         {%W yview scroll [expr {-%D/24}]  units}
572
 
    bind $widget <Shift-MouseWheel>   {%W yview scroll [expr {-%D/120}] pages}
573
 
    bind $widget <Control-MouseWheel> {%W yview scroll [expr {-%D/120}] units}
574
 
 
575
 
    bind $widget <Button-4> {event generate %W <MouseWheel> -delta  120}
576
 
    bind $widget <Button-5> {event generate %W <MouseWheel> -delta -120}
577
 
}