Ignore:
Timestamp:
May 7, 2015, 2:17:22 PM (9 years ago)
Author:
mmh
Message:

Revert ScreenSize? not that it is fixed in Tk. Rewrite balloon code to get the best possible placement

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/uq/gui/scripts/balloon.tcl

    r5315 r5468  
    4747
    4848    protected method _createStems {}
     49    protected method _place {where placement w h sw sh}
    4950
    5051    protected variable _stems   ;# windows for cartoon balloon stems
     
    123124}
    124125
     126
     127# ----------------------------------------------------------------------
     128# USAGE: _place <where> <place> <pw> <ph> <screenw> <screenh>
     129#
     130# Called by activate. Returns the exact location information given
     131# the parameters.  If the window will not fit on the screen with the
     132# requested placement, will loop through all possible placements to
     133# find the best alternative.
     134# ----------------------------------------------------------------------
     135itcl::body Rappture::Balloon::_place {where place pw ph screenw screenh} {
     136    # pw and ph are requested balloon window size
     137
     138    # set placement preference order
     139    switch $place {
     140        left {set plist {left above below right}}
     141        right {set plist {right above below left}}
     142        above {set plist {above below right left}}
     143        below {set plist {below above right left}}
     144    }
     145
     146    set ph_orig $ph
     147    set pw_orig $pw
     148
     149    foreach placement $plist {
     150        set pw $pw_orig
     151        set ph $ph_orig
     152        if {[winfo exists $where]} {
     153            # location of top-left corner of root window
     154            set rx [winfo rootx $where]
     155            set ry [winfo rooty $where]
     156
     157            # size of widget we want to popup over
     158            set width  [winfo width $where]
     159            set height [winfo height $where]
     160
     161            # x and y will be location for popup
     162            set x [expr {$rx + $width/2}]
     163            set y [expr {$ry + $height/2}]
     164
     165            switch -- $placement {
     166                left { set x [expr {$rx + 5}] }
     167                right { set x [expr {$rx + $width - 5}] }
     168                above { set y [expr {$ry + 5}] }
     169                below { set y [expr {$ry + $height - 5}] }
     170            }
     171        } elseif {[regexp {^@([0-9]+),([0-9]+)$} $where match x y]} {
     172            # got x and y
     173        } else {
     174            error "bad location \"$where\": should be widget or @x,y"
     175        }
     176
     177        # compute stem image size
     178        set s $_stems($placement)
     179        set sw [image width $_fills($placement)]
     180        set sh [image height $_fills($placement)]
     181        set offscreen 0
     182
     183        switch -- $placement {
     184            left {
     185                set sx [expr {$x-$sw+3}]
     186                set sy [expr {$y-$sh/2}]
     187                set px [expr {$sx-$pw+3}]
     188                set py [expr {$y-$ph/2}]
     189
     190                # make sure that the panel doesn't go off-screen
     191                if {$py < 0} {
     192                    incr offscreen [expr -$py]
     193                    set py 0
     194                }
     195                if {$py+$ph > $screenh} {
     196                    incr offscreen [expr {$py + $ph - $screenh}]
     197                    set py [expr {$screenh - $ph}]
     198                }
     199                if {$px < 0} {
     200                    incr offscreen [expr -$px]
     201                    set pw [expr {$pw + $px}]
     202                    set px 0
     203                }
     204            }
     205            right {
     206                set sx $x
     207                set sy [expr {$y-$sh/2}]
     208                set px [expr {$x+$sw-3}]
     209                set py [expr {$y-$ph/2}]
     210
     211                # make sure that the panel doesn't go off-screen
     212                if {$py < 0} {
     213                    incr offscreen [expr -$py]
     214                    set py 0
     215                }
     216                if {$py+$ph > $screenh} {
     217                    incr offscreen [expr {$py + $ph - $screenh}]
     218                    set py [expr {$screenh-$ph}]
     219                }
     220                if {$px+$pw > $screenw} {
     221                    incr offscreen [expr {$px + $pw - $screenw}]
     222                    set pw [expr {$screenw-$px}]
     223                }
     224            }
     225            above {
     226                set sx [expr {$x-$sw/2}]
     227                set sy [expr {$y-$sh+3}]
     228                set px [expr {$x-$pw/2}]
     229                set py [expr {$sy-$ph+3}]
     230
     231                # make sure that the panel doesn't go off-screen
     232                if {$px < 0} {
     233                    incr offscreen [expr -$px]
     234                    set px 0
     235                }
     236                if {$px+$pw > $screenw} {
     237                    incr offscreen [expr {$px + $pw - $screenw}]
     238                    set px [expr {$screenw-$pw}]
     239                }
     240                if {$py < 0} {
     241                    incr offscreen [expr -$py]
     242                    set ph [expr {$ph+$py}]
     243                    set py 0
     244                }
     245            }
     246            below {
     247                set sx [expr {$x-$sw/2}]
     248                set sy $y
     249                set px [expr {$x-$pw/2}]
     250                set py [expr {$y+$sh-3}]
     251
     252                # make sure that the panel doesn't go off-screen
     253                if {$px < 0} {
     254                    incr offscreen [expr -$px]
     255                    set px 0
     256                }
     257                if {$px+$pw > $screenw} {
     258                    incr offscreen [expr {$px + $pw - $screenw}]
     259                    set px [expr {$screenw-$pw}]
     260                }
     261                if {$py+$ph > $screenh} {
     262                    incr offscreen [expr {$py + $py - $screenh}]
     263                    set ph [expr {$screenh-$py}]
     264                }
     265            }
     266        }
     267        set res($placement) [list $placement $offscreen $pw $ph $px $py $sx $sy]
     268        if {$offscreen == 0} {
     269            return "$placement $pw $ph $px $py $sx $sy"
     270        }
     271    }
     272
     273    # In the unlikely event that we arrived here, it is because no
     274    # placement allowed the entire balloon window to be displayed.
     275    # Loop through the results and return the best-case placement.
     276    set _min 10000
     277    foreach pl $plist {
     278        set offscreen [lindex $res($pl) 1]
     279        if {$offscreen < $_min} {
     280            set _min $offscreen
     281            set _min_pl $pl
     282        }
     283    }
     284    return "$_min_pl [lrange $res($_min_pl) 2 end]"
     285}
     286
    125287# ----------------------------------------------------------------------
    126288# USAGE: activate <where> <placement>
     
    129291# <where> location, which should be a widget name or @X,Y.  The
    130292# <placement> indicates whether the panel should be left, right,
    131 # above, or below the <where> coordinate.
     293# above, or below the <where> coordinate. Plecement is considered
     294# a suggestion and may be changed to fit the popup in the screen.
    132295# ----------------------------------------------------------------------
    133296itcl::body Rappture::Balloon::activate {where placement} {
     
    135298        error "bad placement \"$placement\": should be [join [lsort [array names _stems]] {, }]"
    136299    }
    137     set s $_stems($placement)
    138     set sw [image width $_fills($placement)]
    139     set sh [image height $_fills($placement)]
    140     set p $itk_component(hull)
    141 
    142     # set screenw [winfo screenwidth $p]
    143     # set screenh [winfo screenheight $p]
    144     foreach {screenw screenh} [Rappture::ScreenSize] break
    145 
    146     if {[winfo exists $where]} {
    147         set x [expr {[winfo rootx $where]+[winfo width $where]/2}]
    148         set y [expr {[winfo rooty $where]+[winfo height $where]/2}]
    149         switch -- $placement {
    150             left { set x [expr {[winfo rootx $where]+5}] }
    151             right { set x [expr {[winfo rootx $where]+[winfo width $where]-5}] }
    152             above { set y [expr {[winfo rooty $where]+5}] }
    153             below { set y [expr {[winfo rooty $where]+[winfo height $where]-5}] }
    154         }
    155     } elseif {[regexp {^@([0-9]+),([0-9]+)$} $where match x y]} {
    156         # got x and y
    157     } else {
    158         error "bad location \"$where\": should be widget or @x,y"
    159     }
    160300
    161301    # if the panel is already up, take it down
    162302    deactivate
     303
     304    set p $itk_component(hull)
     305    set screenw [winfo screenwidth $p]
     306    set screenh [winfo screenheight $p]
    163307
    164308    set pw [winfo reqwidth $p]
     
    167311    if {$ph > $screenh} { set ph [expr {$screenh-10}] }
    168312
    169     switch -- $placement {
    170         left {
    171             set sx [expr {$x-$sw+3}]
    172             set sy [expr {$y-$sh/2}]
    173             set px [expr {$sx-$pw+3}]
    174             set py [expr {$y-$ph/2}]
    175 
    176             # make sure that the panel doesn't go off-screen
    177             if {$py < 0} { set py 0 }
    178             if {$py+$ph > $screenh} { set py [expr {$screenh-$ph}] }
    179             if {$px < 0} { set pw [expr {$pw+$px}]; set px 0 }
    180         }
    181         right -
    182         above {
    183             if {$placement == "right"} {
    184                 set sx $x
    185                 set sy [expr {$y-$sh/2}]
    186                 set px [expr {$x+$sw-3}]
    187                 set py [expr {$y-$ph/2}]
    188 
    189                 # make sure that the panel doesn't go off-screen
    190                 if {$py < 0} { set py 0 }
    191                 if {$py+$ph > $screenh} { set py [expr {$screenh-$ph}] }
    192                 if {$px+$pw > $screenw} { set placement above }
    193             }
    194             if {$placement == "above"} {
    195                 set sx [expr {$x-$sw/2}]
    196                 set sy [expr {$y-$sh+3}]
    197                 set px [expr {$x-$pw/2}]
    198                 set py [expr {$sy-$ph+3}]
    199 
    200                 # make sure that the panel doesn't go off-screen
    201                 if {$px < 0} { set px 0 }
    202                 if {$px+$pw > $screenw} { set px [expr {$screenw-$pw}] }
    203                 if {$py < 0} { set ph [expr {$ph+$py}]; set py 0 }
    204             }
    205         }
    206         below {
    207             set sx [expr {$x-$sw/2}]
    208             set sy $y
    209             set px [expr {$x-$pw/2}]
    210             set py [expr {$y+$sh-3}]
    211 
    212             # make sure that the panel doesn't go off-screen
    213             if {$px < 0} { set px 0 }
    214             if {$px+$pw > $screenw} { set px [expr {$screenw-$pw}] }
    215             if {$py+$ph > $screenh} { set ph [expr {$screenh-$py}] }
    216         }
    217     }
    218     if {[info exists _masks($placement)]} {
    219         shape set $s -bound photo $_masks($placement)
    220     }
     313    foreach {place pw ph px py sx sy} [_place $where $placement $pw $ph $screenw $screenh] break
     314
     315    set s $_stems($place)
     316    if {[info exists _masks($place)]} {
     317        shape set $s -bound photo $_masks($place)
     318    }
     319
    221320    if { $pw < 1 || $ph < 1 }  {
    222321        # I really don't know why this is happenning.  I believe this occurs
Note: See TracChangeset for help on using the changeset viewer.