| 1 | package require Metawidget |
|---|
| 2 | |
|---|
| 3 | # name: Document |
|---|
| 4 | # args: args: option-value pairs |
|---|
| 5 | # defines icons for the window title bar. defines a default menu and creates |
|---|
| 6 | # all standard window elements (MS Windows look&feel). declares option values. |
|---|
| 7 | metawidget create Document { |
|---|
| 8 | # if first object is being created, define some icons etc. |
|---|
| 9 | if { ! [ourinfo exists lAllDocs] } { |
|---|
| 10 | our lAllDocs {} ;# list of all document windows |
|---|
| 11 | our wFocus {} ;# topmost window (drawn active) |
|---|
| 12 | |
|---|
| 13 | # set platform dependend colors and cursor shapes |
|---|
| 14 | if { $::tcl_platform(platform) == "windows" } { |
|---|
| 15 | ourarray set aColors {gray50 SystemDisabledText white SystemWindow darkblue SystemHighlight gray SystemButtonFace} |
|---|
| 16 | ourarray set aCursors {{} {} nw size_nw_se ne size_ne_sw sw size_ne_sw se size_nw_se n size_ns s size_ns w size_we e size_we} |
|---|
| 17 | } else { |
|---|
| 18 | ourarray set aColors {gray50 gray50 white white darkblue darkblue gray gray} |
|---|
| 19 | ourarray set aCursors {{} {} nw top_left_corner ne top_right_corner sw bottom_left_corner se bottom_right_corner n sb_v_double_arrow s sb_v_double_arrow w sb_h_double_arrow e sb_h_double_arrow} |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | # x/y-offset from top left corner |
|---|
| 23 | our iOffset 0 |
|---|
| 24 | |
|---|
| 25 | our pIconMin [image create bitmap -data { |
|---|
| 26 | #define _width 8 |
|---|
| 27 | #define _height 8 |
|---|
| 28 | static char _bits[] = { 0x00,0x00,0x00,0x00,0x00,0x3e,0x3e,0x00 }; |
|---|
| 29 | }] |
|---|
| 30 | our pIconMax [image create bitmap -data { |
|---|
| 31 | #define _width 8 |
|---|
| 32 | #define _height 8 |
|---|
| 33 | static char _bits[] = { 0x7f,0x7f,0x41,0x41,0x41,0x41,0x7f,0x00 }; |
|---|
| 34 | }] |
|---|
| 35 | our pIconRestore [image create bitmap -data { |
|---|
| 36 | #define _width 8 |
|---|
| 37 | #define _height 8 |
|---|
| 38 | static char _bits[] = { 0x7c,0x7c,0x44,0x5f,0x5f,0x71,0x11,0x1f }; |
|---|
| 39 | }] |
|---|
| 40 | our pIconClose [image create bitmap -data { |
|---|
| 41 | #define _width 8 |
|---|
| 42 | #define _height 8 |
|---|
| 43 | static char _bits[] = { 0x00,0x63,0x36,0x1c,0x1c,0x36,0x63,0x00 }; |
|---|
| 44 | }] |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | # define popup menu |
|---|
| 48 | menu $this.menu -tearoff 0 |
|---|
| 49 | # $this.menu add command -label Restore -command "$this _restore" |
|---|
| 50 | # $this.menu add command -label Minimize -command "$this _minimize" |
|---|
| 51 | # $this.menu add command -label Maximize -command "$this _maximize" |
|---|
| 52 | # $this.menu add command -label Restore -command "::${this}::_restore" |
|---|
| 53 | $this.menu add command -label Minimize -command "::${this}::_minimize" |
|---|
| 54 | $this.menu add command -label Maximize -command "::${this}::_maximize" |
|---|
| 55 | $this.menu add separator |
|---|
| 56 | $this.menu add command -label Close -command "destroy $this" |
|---|
| 57 | |
|---|
| 58 | # create title bar elements |
|---|
| 59 | pack [frame $this.head -border 0] -padx 2 -pady 2 -fill x |
|---|
| 60 | pack [label $this.head.icon -border 0] -side left -padx 1 |
|---|
| 61 | pack [label $this.head.clob -border 2 -relief raised -image [our pIconClose]] -side right -pady 2 -padx 2 |
|---|
| 62 | pack [label $this.head.maxb -border 2 -relief raised -image [our pIconMax]] -side right -pady 2 |
|---|
| 63 | pack [label $this.head.minb -border 2 -relief raised -image [our pIconMin]] -side right -pady 2 |
|---|
| 64 | pack [label $this.head.text -border 0 -anchor w] -side left -fill x -expand 1 |
|---|
| 65 | |
|---|
| 66 | # work area where all inner widgets will be go |
|---|
| 67 | pack [frame $this.work -border 0] -fill both -expand 1 -padx 2 -pady 2 |
|---|
| 68 | |
|---|
| 69 | # make sure mouse cursor resets when not over the boarder |
|---|
| 70 | bind $this.work <Enter> "$this config -cursor {}" |
|---|
| 71 | bind $this.head <Enter> "$this config -cursor {}" |
|---|
| 72 | |
|---|
| 73 | # option values, self explaining |
|---|
| 74 | my -title $this |
|---|
| 75 | my -foreground [our aColors(white)] |
|---|
| 76 | my -background [our aColors(darkblue)] |
|---|
| 77 | my -font [$this.head.text cget -font] |
|---|
| 78 | my -minsize {100 30} |
|---|
| 79 | my -icontext {} |
|---|
| 80 | my -state normal |
|---|
| 81 | my -image {} |
|---|
| 82 | |
|---|
| 83 | # position and size of the window. note that later on, -x and -y contain |
|---|
| 84 | # either the icon or the window position, depending on the window's state. |
|---|
| 85 | my iNormX [our iOffset] |
|---|
| 86 | my iNormY [our iOffset] |
|---|
| 87 | my -width 250 |
|---|
| 88 | my -height 150 |
|---|
| 89 | |
|---|
| 90 | # bind menu to icon and close button |
|---|
| 91 | bind $this.head.icon <1> "$this _showMenu" |
|---|
| 92 | bind $this.head.icon <Double-1> "$this.menu invoke Close" |
|---|
| 93 | bind $this.head.clob <1> "$this.menu invoke Close" |
|---|
| 94 | |
|---|
| 95 | # increase offset for next window |
|---|
| 96 | our iOffset [expr [our iOffset]+16] |
|---|
| 97 | if { [expr [our iOffset]+64] > [winfo height [winfo parent $this]] } { |
|---|
| 98 | our iOffset 0 |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | # show in normal mode and put it on top |
|---|
| 102 | _restore |
|---|
| 103 | raise_ |
|---|
| 104 | |
|---|
| 105 | # add it to the list of all documents |
|---|
| 106 | _register |
|---|
| 107 | } { |
|---|
| 108 | if { [our wFocus] == $this } { |
|---|
| 109 | our wFocus {} |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | # remove it from all documents |
|---|
| 113 | _unregister |
|---|
| 114 | } -border 2 -relief raised |
|---|
| 115 | |
|---|
| 116 | # name: _register |
|---|
| 117 | # args: o Document object to register |
|---|
| 118 | # adds the current object to a list. required for geometry management. |
|---|
| 119 | metawidget proc Document _register {} { |
|---|
| 120 | our lAllDocs [linsert [our lAllDocs] end $this] |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | # name: _unregister |
|---|
| 124 | # args: o Document object to unregister |
|---|
| 125 | # removes the object from this list. |
|---|
| 126 | metawidget proc Document _unregister {} { |
|---|
| 127 | our lAllDocs [mkw.lshrink [our lAllDocs] $this] |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | # name: _showMenu |
|---|
| 131 | # args: - |
|---|
| 132 | # displays the popup menu right under the document's icon |
|---|
| 133 | metawidget proc Document _showMenu {} { |
|---|
| 134 | $this.menu post [winfo rootx $this.head.icon] \ |
|---|
| 135 | [expr [winfo height $this.head.icon] + [winfo rooty $this.head.icon]] |
|---|
| 136 | |
|---|
| 137 | bind $this.menu <FocusOut> "$this.menu unpost" |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | # name: _getEdge |
|---|
| 141 | # args: iXp, iYp: mouse position |
|---|
| 142 | # called only when the mouse is over the document's border. returns an area |
|---|
| 143 | # indicator of the mouse position, e.g. sw for south-west = bottom left. |
|---|
| 144 | # used to set the mouse cursor and to determine the resize mode. |
|---|
| 145 | metawidget proc Document _getEdge { iXp iYp } { |
|---|
| 146 | incr iXp -[winfo rootx $this] |
|---|
| 147 | incr iYp -[winfo rooty $this] |
|---|
| 148 | |
|---|
| 149 | # allow max. 16 pixel for edge detection |
|---|
| 150 | set iXEdge [expr ([my -width ] < 32)?[my -width ]>>1:16] |
|---|
| 151 | set iYEdge [expr ([my -height] < 32)?[my -height]>>1:16] |
|---|
| 152 | |
|---|
| 153 | # detect if mouse is on one of the edges (x coordinate) |
|---|
| 154 | if { $iXp < $iXEdge } { |
|---|
| 155 | set sPosH w |
|---|
| 156 | } elseif { $iXp > [expr [my -width]-$iXEdge] } { |
|---|
| 157 | set sPosH e |
|---|
| 158 | } else { |
|---|
| 159 | set sPosH {} |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | # detect if mouse is on one of the edges (y coordinate) |
|---|
| 163 | if { $iYp < $iYEdge } { |
|---|
| 164 | set sPosV n |
|---|
| 165 | } elseif { $iYp > [expr [my -height]-$iYEdge] } { |
|---|
| 166 | set sPosV s |
|---|
| 167 | } else { |
|---|
| 168 | set sPosV {} |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | return $sPosV$sPosH |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | # name: _motion |
|---|
| 175 | # args: iXp, iYp: mouse position (from the %X and %Y fields of an event) |
|---|
| 176 | # called by a <Motion> binding over the document frame. Sets the mouse cursor |
|---|
| 177 | # to show arrows depending on the region of the mouse. _getEdge returns an |
|---|
| 178 | # area (e.g. ne for north-east = upper right corner), the aCursor array |
|---|
| 179 | # maps this to a valid cursor name (depending on platform). |
|---|
| 180 | metawidget proc Document _motion { iXp iYp } { |
|---|
| 181 | $this config -cursor [our aCursors([_getEdge $iXp $iYp])] |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | # name: _move1 |
|---|
| 185 | # args: iXp, iYp: mouse position (from the %X and %Y fields of an event) |
|---|
| 186 | # called on a <Button-1> event on the title bar. stores the current mouse |
|---|
| 187 | # pointer position. raises the document. |
|---|
| 188 | metawidget proc Document _move1 { iXp iYp } { |
|---|
| 189 | raise_ |
|---|
| 190 | |
|---|
| 191 | set wParent [winfo parent $this] |
|---|
| 192 | my iXr1 [winfo rootx $wParent] |
|---|
| 193 | my iYr1 [winfo rooty $wParent] |
|---|
| 194 | my iXr2 [expr [my iXr1]+[winfo width $wParent]] |
|---|
| 195 | my iYr2 [expr [my iYr1]+[winfo height $wParent]] |
|---|
| 196 | |
|---|
| 197 | my iXp0 $iXp |
|---|
| 198 | my iYp0 $iYp |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | # name: _move2 |
|---|
| 202 | # args: iXp, iYp: mouse position (from the %X and %Y fields of an event) |
|---|
| 203 | # called on a <B1-Motion> event on the title bar. calculates the new |
|---|
| 204 | # window position and places it there. |
|---|
| 205 | metawidget proc Document _move2 { iXp iYp } { |
|---|
| 206 | if { $iXp < [my iXr1] } { set iXp [my iXr1] } |
|---|
| 207 | if { $iYp < [my iYr1] } { set iYp [my iYr1] } |
|---|
| 208 | if { $iXp > [my iXr2] } { set iXp [my iXr2] } |
|---|
| 209 | if { $iYp > [my iYr2] } { set iYp [my iYr2] } |
|---|
| 210 | |
|---|
| 211 | place $this -x [expr [my -x]-[my iXp0]+$iXp] -y [expr [my -y]-[my iYp0]+$iYp] |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | # name: _move3 |
|---|
| 215 | # args: - |
|---|
| 216 | # called on a <ButtonRelease-1> event on the title bar. stores the actual |
|---|
| 217 | # window position in some private variables. |
|---|
| 218 | metawidget proc Document _move3 {} { |
|---|
| 219 | my -x [winfo x $this] |
|---|
| 220 | my -y [winfo y $this] |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | # name: _resize1 |
|---|
| 224 | # args: iXp, iYp: mouse position (from the %X and %Y fields of an event) |
|---|
| 225 | # called on a <1> event on one of the borders. stores the current mouse |
|---|
| 226 | # position. depending on the mouse position (at an edge or not), the |
|---|
| 227 | # resize mode is determined. |
|---|
| 228 | metawidget proc Document _resize1 { iXp iYp } { |
|---|
| 229 | raise_ |
|---|
| 230 | |
|---|
| 231 | my iWMin [lindex [my -minsize] 0] |
|---|
| 232 | my iHMin [lindex [my -minsize] 1] |
|---|
| 233 | |
|---|
| 234 | my iXMax [expr [my -x]+[my -width] -[my iWMin]] |
|---|
| 235 | my iYMax [expr [my -y]+[my -height]-[my iHMin]] |
|---|
| 236 | |
|---|
| 237 | my iXp0 $iXp |
|---|
| 238 | my iYp0 $iYp |
|---|
| 239 | |
|---|
| 240 | set sPos [_getEdge $iXp $iYp] |
|---|
| 241 | set sXPos {}; regexp {[we]} $sPos sXPos; my sXPos $sXPos |
|---|
| 242 | set sYPos {}; regexp {[ns]} $sPos sYPos; my sYPos $sYPos |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | # name: _resize2 |
|---|
| 246 | # args: iXp, iYp: mouse position (from the %X and %Y fields of an event) |
|---|
| 247 | # called on a <B1-Motion> event on the borders. calculates the new |
|---|
| 248 | # Document sizes and position and places it depending on the resize mode. |
|---|
| 249 | metawidget proc Document _resize2 { iXp iYp } { |
|---|
| 250 | # sometimes the <1> event and _resize1 didn't precede this one... |
|---|
| 251 | if { ! [myinfo exists sXPos] } { |
|---|
| 252 | return |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | if { [my sXPos] == "w" } { |
|---|
| 256 | set iX [expr [my -x]-[my iXp0]+$iXp] |
|---|
| 257 | if { $iX > [my iXMax] } { set iX [my iXMax] } |
|---|
| 258 | |
|---|
| 259 | set iW [expr [my -width]+[my iXp0]-$iXp] |
|---|
| 260 | if { $iW < [my iWMin] } { set iW [my iWMin] } |
|---|
| 261 | |
|---|
| 262 | place $this -x $iX -width $iW |
|---|
| 263 | } elseif { [my sXPos] == "e" } { |
|---|
| 264 | set iW [expr [my -width]-[my iXp0]+$iXp] |
|---|
| 265 | if { $iW < [my iWMin] } { set iW [my iWMin] } |
|---|
| 266 | |
|---|
| 267 | place $this -width $iW |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | if { [my sYPos] == "n" } { |
|---|
| 271 | set iY [expr [my -y]-[my iYp0]+$iYp] |
|---|
| 272 | if { $iY > [my iYMax] } { set iY [my iYMax] } |
|---|
| 273 | |
|---|
| 274 | set iH [expr [my -height]+[my iYp0]-$iYp] |
|---|
| 275 | if { $iH < [my iHMin] } { set iH [my iHMin] } |
|---|
| 276 | |
|---|
| 277 | place $this -y $iY -height $iH |
|---|
| 278 | } elseif { [my sYPos] == "s" } { |
|---|
| 279 | set iH [expr [my -height]-[my iYp0]+$iYp] |
|---|
| 280 | if { $iH < [my iHMin] } { set iH [my iHMin] } |
|---|
| 281 | |
|---|
| 282 | place $this -height $iH |
|---|
| 283 | } |
|---|
| 284 | } |
|---|
| 285 | |
|---|
| 286 | # name: _resize3 |
|---|
| 287 | # args: - |
|---|
| 288 | # called on a <ButtonRelease-1> event on the borders. stores the actual |
|---|
| 289 | # window size and position in some private variables. |
|---|
| 290 | metawidget proc Document _resize3 {} { |
|---|
| 291 | my -x [winfo x $this] |
|---|
| 292 | my -y [winfo y $this] |
|---|
| 293 | my -width [winfo width $this] |
|---|
| 294 | my -height [winfo height $this] |
|---|
| 295 | } |
|---|
| 296 | |
|---|
| 297 | # name: _withdraw |
|---|
| 298 | # args: - |
|---|
| 299 | # simply lets the Document disappear. |
|---|
| 300 | metawidget proc Document _withdraw {} { |
|---|
| 301 | place forget $this |
|---|
| 302 | my -state withdrawn |
|---|
| 303 | } |
|---|
| 304 | |
|---|
| 305 | # name: _maximize |
|---|
| 306 | # args: - |
|---|
| 307 | # maximizes the document. exchanges the icon for the maximize button. |
|---|
| 308 | # deletes bindings for resize and move. |
|---|
| 309 | metawidget proc Document _maximize {} { |
|---|
| 310 | # if it was minimized or withdrawn: set to default |
|---|
| 311 | # if we come from normal state, store the window position |
|---|
| 312 | if { [my -state] == "normal" } { |
|---|
| 313 | my iNormX [my -x] |
|---|
| 314 | my iNormY [my -y] |
|---|
| 315 | } else { |
|---|
| 316 | _restore |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | # place it to fill entirely its master |
|---|
| 320 | place $this -x 0 -y 0 -width 0 -height 0 -relwidth 1 -relheight 1 |
|---|
| 321 | $this.head.maxb configure -image [our pIconRestore] |
|---|
| 322 | $this.menu entryconf Maximize -state disabled |
|---|
| 323 | $this configure -border 0 |
|---|
| 324 | |
|---|
| 325 | # delete bindings for resizing |
|---|
| 326 | bind $this <1> {} |
|---|
| 327 | bind $this <B1-Motion> {} |
|---|
| 328 | bind $this <ButtonRelease-1> {} |
|---|
| 329 | |
|---|
| 330 | # modify/delete bindings for moving |
|---|
| 331 | bind $this.head.text <1> "$this raise" |
|---|
| 332 | bind $this.head.text <B1-Motion> {} |
|---|
| 333 | bind $this.head.text <ButtonRelease-1> {} |
|---|
| 334 | |
|---|
| 335 | # delete binding for mouse cursor changes over borders |
|---|
| 336 | bind $this <Motion> {} |
|---|
| 337 | |
|---|
| 338 | # change bindings for maximize button and title bar |
|---|
| 339 | bind $this.head.text <Double-1> "$this _restore" |
|---|
| 340 | bind $this.head.maxb <1> "$this _restore" |
|---|
| 341 | |
|---|
| 342 | my -state maximized |
|---|
| 343 | } |
|---|
| 344 | |
|---|
| 345 | # name: _minimize |
|---|
| 346 | # args: - |
|---|
| 347 | # minimizes the document. exchanges the icon for the minimize button. |
|---|
| 348 | # deletes bindings for resize. |
|---|
| 349 | metawidget proc Document _minimize {} { |
|---|
| 350 | # if it was maximized or withdrawn: set to default |
|---|
| 351 | # if we come from normal state, store the window position |
|---|
| 352 | if { [my -state] == "normal" } { |
|---|
| 353 | my iNormX [my -x] |
|---|
| 354 | my iNormY [my -y] |
|---|
| 355 | } else { |
|---|
| 356 | _restore |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| 359 | # morph -x and -y to contain the icon position |
|---|
| 360 | if { [myinfo exists iIconX] } { |
|---|
| 361 | my -x [my iIconX] |
|---|
| 362 | my -y [my iIconY] |
|---|
| 363 | } else { |
|---|
| 364 | my -x [my iNormX] |
|---|
| 365 | my -y [my iNormY] |
|---|
| 366 | } |
|---|
| 367 | |
|---|
| 368 | # withdraw the document's working area |
|---|
| 369 | pack forget $this.work |
|---|
| 370 | $this.head.minb configure -image [our pIconRestore] |
|---|
| 371 | $this.menu entryconf Minimize -state disabled |
|---|
| 372 | |
|---|
| 373 | # eventually change title text |
|---|
| 374 | if { [my -icontext] != {} } { |
|---|
| 375 | $this.head.text configure -text [my -icontext] |
|---|
| 376 | } |
|---|
| 377 | |
|---|
| 378 | place $this -x [my -x] -y [my -y] -width 128 -height [expr [winfo reqheight $this.head] + 8] -relwidth 0 -relheight 0 |
|---|
| 379 | |
|---|
| 380 | # delete bindings for resizing |
|---|
| 381 | bind $this <1> {} |
|---|
| 382 | bind $this <B1-Motion> {} |
|---|
| 383 | bind $this <ButtonRelease-1> {} |
|---|
| 384 | |
|---|
| 385 | # delete binding for mouse cursor changes over borders |
|---|
| 386 | bind $this <Motion> {} |
|---|
| 387 | |
|---|
| 388 | # change bindings for minimize button and title bar |
|---|
| 389 | bind $this.head.text <Double-1> "$this _restore" |
|---|
| 390 | bind $this.head.minb <1> "$this _restore" |
|---|
| 391 | |
|---|
| 392 | my -state minimized |
|---|
| 393 | } |
|---|
| 394 | |
|---|
| 395 | # name: _restore |
|---|
| 396 | # args: - |
|---|
| 397 | # restores a Document from any of the other states. assigns the regular |
|---|
| 398 | # bindings to all widgets. |
|---|
| 399 | metawidget proc Document _restore {} { |
|---|
| 400 | # if we come from iconized state, store the icon position |
|---|
| 401 | if { [my -state] == "minimized" } { |
|---|
| 402 | my iIconX [my -x] |
|---|
| 403 | my iIconY [my -y] |
|---|
| 404 | } |
|---|
| 405 | |
|---|
| 406 | # morph -x and -y to contain the window position |
|---|
| 407 | my -x [my iNormX] |
|---|
| 408 | my -y [my iNormY] |
|---|
| 409 | |
|---|
| 410 | # show the working area and place Document on last known position |
|---|
| 411 | pack $this.work -fill both -expand 1 -padx 2 -pady 2 |
|---|
| 412 | place $this -x [my -x] -y [my -y] -width [my -width] -height [my -height] -relwidth 0 -relheight 0 |
|---|
| 413 | |
|---|
| 414 | # restore icons and menu entries for all title bar elements |
|---|
| 415 | $this.head.minb configure -image [our pIconMin] |
|---|
| 416 | $this.head.maxb configure -image [our pIconMax] |
|---|
| 417 | $this.head.text configure -text [my -title] |
|---|
| 418 | $this.menu entryconf Minimize -state normal |
|---|
| 419 | $this.menu entryconf Maximize -state normal |
|---|
| 420 | ::${this}::$this config -border 2 |
|---|
| 421 | |
|---|
| 422 | # restore resize bindings |
|---|
| 423 | bind $this <1> "$this _resize1 %X %Y" |
|---|
| 424 | bind $this <B1-Motion> "$this _resize2 %X %Y" |
|---|
| 425 | bind $this <ButtonRelease-1> "$this _resize3" |
|---|
| 426 | |
|---|
| 427 | # restore move bindings |
|---|
| 428 | bind $this.head.text <1> "$this _move1 %X %Y" |
|---|
| 429 | bind $this.head.text <B1-Motion> "$this _move2 %X %Y" |
|---|
| 430 | bind $this.head.text <ButtonRelease-1> "$this _move3" |
|---|
| 431 | |
|---|
| 432 | # restore maximize and minimize bindings |
|---|
| 433 | bind $this.head.maxb <1> "$this _maximize" |
|---|
| 434 | bind $this.head.minb <1> "$this _minimize" |
|---|
| 435 | bind $this.head.text <Double-1> "$this _maximize" |
|---|
| 436 | |
|---|
| 437 | # restore binding for mouse cursor changes over borders |
|---|
| 438 | bind $this <Motion> "$this _motion %X %Y" |
|---|
| 439 | |
|---|
| 440 | my -state normal |
|---|
| 441 | } |
|---|
| 442 | |
|---|
| 443 | # name: -x et al. |
|---|
| 444 | # args: iX, iY, iWidth iHeight: geometry values |
|---|
| 445 | # sets a new size or position of the Document window. -x and -y apply |
|---|
| 446 | # regardless if the window is iconified or not, but -width and -height |
|---|
| 447 | # only affect the window in normal state. |
|---|
| 448 | metawidget proc Document -x { iX } { |
|---|
| 449 | my -x $iX |
|---|
| 450 | place $this -x [my -x] |
|---|
| 451 | } |
|---|
| 452 | metawidget proc Document -y { iY } { |
|---|
| 453 | my -y $iY |
|---|
| 454 | place $this -y [my -y] |
|---|
| 455 | } |
|---|
| 456 | metawidget proc Document -width { iWidth } { |
|---|
| 457 | my -width $iWidth |
|---|
| 458 | |
|---|
| 459 | if { [my -state] == "normal" } { |
|---|
| 460 | place $this -width [my -width] |
|---|
| 461 | } |
|---|
| 462 | } |
|---|
| 463 | metawidget proc Document -height { iHeight } { |
|---|
| 464 | my -height $iHeight |
|---|
| 465 | |
|---|
| 466 | if { [my -state] == "normal" } { |
|---|
| 467 | place $this -height [my -height] |
|---|
| 468 | } |
|---|
| 469 | } |
|---|
| 470 | |
|---|
| 471 | # name: -font |
|---|
| 472 | # args: sFont: font to set |
|---|
| 473 | # option handler. sets the title font. |
|---|
| 474 | metawidget proc Document -font { sFont } { |
|---|
| 475 | my -font $sFont |
|---|
| 476 | $this.head.text configure -font $sFont |
|---|
| 477 | } |
|---|
| 478 | |
|---|
| 479 | # name: -image |
|---|
| 480 | # args: sImage: image to set |
|---|
| 481 | # option handler. sets the image in the title bar. |
|---|
| 482 | metawidget proc Document -image { sImage } { |
|---|
| 483 | my -image $sImage |
|---|
| 484 | $this.head.icon configure -image $sImage |
|---|
| 485 | } |
|---|
| 486 | |
|---|
| 487 | # name: -title |
|---|
| 488 | # args: sTitle: title to set |
|---|
| 489 | # option handler. sets title text. |
|---|
| 490 | metawidget proc Document -title { sTitle } { |
|---|
| 491 | my -title $sTitle |
|---|
| 492 | $this.head.text configure -text $sTitle |
|---|
| 493 | } |
|---|
| 494 | |
|---|
| 495 | # name: -state |
|---|
| 496 | # args: sState: new Document state |
|---|
| 497 | # option handler. sets the state for the document. the variable -state |
|---|
| 498 | # is set in the respective (private) member functions. |
|---|
| 499 | metawidget proc Document -state { sState } { |
|---|
| 500 | switch -- [mkw.complete $sState {normal minimized maximized withdrawn}] { |
|---|
| 501 | normal { _restore } |
|---|
| 502 | minimized { _minimize } |
|---|
| 503 | maximized { _maximize } |
|---|
| 504 | withdrawn { _withdraw } |
|---|
| 505 | } |
|---|
| 506 | } |
|---|
| 507 | |
|---|
| 508 | # name: menu |
|---|
| 509 | # args: args: arguments for the regular menu command. |
|---|
| 510 | # simply passes all arguments to the popup menu. |
|---|
| 511 | metawidget proc Document menu_ { args } { |
|---|
| 512 | eval $this.menu $args |
|---|
| 513 | } |
|---|
| 514 | |
|---|
| 515 | # name: lower |
|---|
| 516 | # args: - |
|---|
| 517 | # draws the title bar in grey. |
|---|
| 518 | metawidget proc Document lower_ {} { |
|---|
| 519 | $this.head configure -bg [our aColors(gray50)] |
|---|
| 520 | $this.head.icon configure -bg [our aColors(gray50)] |
|---|
| 521 | $this.head.text configure -bg [our aColors(gray50)] -fg [our aColors(gray)] |
|---|
| 522 | } |
|---|
| 523 | |
|---|
| 524 | # name: raise |
|---|
| 525 | # args: - |
|---|
| 526 | # puts the Document on top and draws the title bar in different colors. |
|---|
| 527 | metawidget proc Document raise_ {} { |
|---|
| 528 | catch { [our wFocus] lower } |
|---|
| 529 | our wFocus $this |
|---|
| 530 | |
|---|
| 531 | $this.head configure -bg [my -background] |
|---|
| 532 | $this.head.icon configure -bg [my -background] |
|---|
| 533 | $this.head.text configure -bg [my -background] -fg [my -foreground] |
|---|
| 534 | |
|---|
| 535 | raise $this |
|---|
| 536 | } |
|---|
| 537 | |
|---|
| 538 | # name: pack |
|---|
| 539 | # args: sWindow: widget to be packed |
|---|
| 540 | # args: option-value pairs |
|---|
| 541 | # redirects packing to the work area widget. the binding is required |
|---|
| 542 | # to reset the mouse cursor when it enters the work area. this is |
|---|
| 543 | # only required if the packed widget is a logical child. |
|---|
| 544 | metawidget proc Document pack_ { sWindow args } { |
|---|
| 545 | eval pack $sWindow -in $this.work $args |
|---|
| 546 | |
|---|
| 547 | if { [winfo parent $sWindow] == $this } { |
|---|
| 548 | bind $sWindow <Enter> "+$this config -cursor {}" |
|---|
| 549 | } |
|---|
| 550 | } |
|---|
| 551 | |
|---|
| 552 | # name: grid |
|---|
| 553 | # args: sWindow: widget to be gridded |
|---|
| 554 | # args: option-value pairs |
|---|
| 555 | # redirects gridding to the work area widget. |
|---|
| 556 | metawidget proc Document grid_ { sWindow args } { |
|---|
| 557 | eval grid $sWindow -in $this.work $args |
|---|
| 558 | |
|---|
| 559 | if { [winfo parent $sWindow] == $this } { |
|---|
| 560 | bind $sWindow <Enter> "+$this config -cursor {}" |
|---|
| 561 | } |
|---|
| 562 | } |
|---|
| 563 | |
|---|
| 564 | # name: place |
|---|
| 565 | # args: sWindow: widget to be placed |
|---|
| 566 | # args: option-value pairs |
|---|
| 567 | # redirects placing to the work area widget. |
|---|
| 568 | metawidget proc Document place_ { sWindow args } { |
|---|
| 569 | eval place $sWindow -in $this.work $args |
|---|
| 570 | |
|---|
| 571 | if { [winfo parent $sWindow] == $this } { |
|---|
| 572 | bind $sWindow <Enter> "+$this config -cursor {}" |
|---|
| 573 | } |
|---|
| 574 | } |
|---|
| 575 | |
|---|
| 576 | # name: Arrange |
|---|
| 577 | # args: sHow: arrange mode |
|---|
| 578 | # sParent: a valid parent widget of document windows(s). |
|---|
| 579 | # static member function. resizes and repositions all Document objects |
|---|
| 580 | # in one of several ways. it always arrange iconfied windows before |
|---|
| 581 | # it repositions the non-iconfied windows. |
|---|
| 582 | metawidget proc Document Arrange { sHow } { |
|---|
| 583 | variable lAllDocs |
|---|
| 584 | |
|---|
| 585 | set sHow [mkw.complete $sHow {horizontally vertically cascade tile icons maximize minimize}] |
|---|
| 586 | |
|---|
| 587 | # first check if at least one document window exists |
|---|
| 588 | if { ! [info exists lAllDocs] || ! [llength $lAllDocs] } return |
|---|
| 589 | |
|---|
| 590 | # get a list of all iconified windows and a list of all others |
|---|
| 591 | set lDocs {} |
|---|
| 592 | set lIcon {} |
|---|
| 593 | foreach sDoc $lAllDocs { |
|---|
| 594 | if { [$sDoc cget -state] == "minimized" } { |
|---|
| 595 | lappend lIcon $sDoc |
|---|
| 596 | } else { |
|---|
| 597 | lappend lDocs $sDoc |
|---|
| 598 | } |
|---|
| 599 | } |
|---|
| 600 | |
|---|
| 601 | # get parent window's dimensions for later calculation |
|---|
| 602 | set sParent [winfo parent [lindex $lAllDocs 0]] |
|---|
| 603 | set iW [winfo width $sParent] |
|---|
| 604 | set iH [winfo height $sParent] |
|---|
| 605 | |
|---|
| 606 | # if there are iconfied windows, arrange them first and reduce iH |
|---|
| 607 | set iXd 0 |
|---|
| 608 | foreach sDoc $lIcon { |
|---|
| 609 | set iWd [winfo width $sDoc] |
|---|
| 610 | if { [expr $iXd+$iWd] > $iW } { |
|---|
| 611 | set iXd 0 |
|---|
| 612 | } |
|---|
| 613 | if { $iXd == 0 } { |
|---|
| 614 | incr iH -[winfo height $sDoc] |
|---|
| 615 | } |
|---|
| 616 | $sDoc configure -x $iXd -y $iH |
|---|
| 617 | incr iXd $iWd |
|---|
| 618 | } |
|---|
| 619 | |
|---|
| 620 | # how many non-iconified windows? just exit when none |
|---|
| 621 | set iDocs [llength $lDocs] |
|---|
| 622 | if { $iDocs == 0 } return |
|---|
| 623 | |
|---|
| 624 | switch $sHow { |
|---|
| 625 | horizontally { |
|---|
| 626 | set iStep [expr $iH/$iDocs] |
|---|
| 627 | for { set i 0 } { $i < $iDocs } { incr i } { |
|---|
| 628 | set sDoc [lindex $lDocs $i] |
|---|
| 629 | $sDoc configure -x 0 -y [expr $i*$iStep] -width $iW -height $iStep |
|---|
| 630 | } |
|---|
| 631 | } |
|---|
| 632 | |
|---|
| 633 | vertically { |
|---|
| 634 | set iStep [expr $iW/$iDocs] |
|---|
| 635 | for { set i 0 } { $i < $iDocs } { incr i } { |
|---|
| 636 | set sDoc [lindex $lDocs $i] |
|---|
| 637 | $sDoc configure -x [expr $i*$iStep] -y 0 -width $iStep -height $iH |
|---|
| 638 | } |
|---|
| 639 | } |
|---|
| 640 | |
|---|
| 641 | cascade { |
|---|
| 642 | set iStep 24 |
|---|
| 643 | for { set i 0 } { $i < $iDocs } { incr i } { |
|---|
| 644 | set sDoc [lindex $lDocs $i] |
|---|
| 645 | $sDoc configure -x [expr $i*$iStep] -y [expr $i*$iStep] -width [expr $iW*2/3] -height [expr $iH*2/3] |
|---|
| 646 | $sDoc raise |
|---|
| 647 | } |
|---|
| 648 | } |
|---|
| 649 | |
|---|
| 650 | tile { |
|---|
| 651 | for { set i 0 } { $i <= 100 } { incr i } { |
|---|
| 652 | set iHor [expr ($i+3)/2] |
|---|
| 653 | set iVer [expr ($i+2)/2] |
|---|
| 654 | if { [expr $iHor*$iVer] >= $iDocs } break |
|---|
| 655 | } |
|---|
| 656 | |
|---|
| 657 | set iXStep [expr $iW/$iHor] |
|---|
| 658 | set iYStep [expr $iH/$iVer] |
|---|
| 659 | for { set i 0 } { $i < $iDocs } { incr i } { |
|---|
| 660 | set sDoc [lindex $lDocs $i] |
|---|
| 661 | $sDoc configure -x [expr ($i%$iHor)*$iXStep] -y [expr ($i/$iHor)*$iYStep] -width $iXStep -height $iYStep |
|---|
| 662 | } |
|---|
| 663 | } |
|---|
| 664 | |
|---|
| 665 | maximize { |
|---|
| 666 | foreach sDoc $lDocs { |
|---|
| 667 | $sDoc _maximize |
|---|
| 668 | } |
|---|
| 669 | } |
|---|
| 670 | |
|---|
| 671 | minimize { |
|---|
| 672 | foreach sDoc $lDocs { |
|---|
| 673 | $sDoc _minimize |
|---|
| 674 | } |
|---|
| 675 | } |
|---|
| 676 | } |
|---|
| 677 | } |
|---|
| 678 | |
|---|
| 679 | metawidget command Document _showMenu _showMenu |
|---|
| 680 | metawidget command Document _move1 _move1 |
|---|
| 681 | metawidget command Document _move2 _move2 |
|---|
| 682 | metawidget command Document _move3 _move3 |
|---|
| 683 | metawidget command Document _resize1 _resize1 |
|---|
| 684 | metawidget command Document _resize2 _resize2 |
|---|
| 685 | metawidget command Document _resize3 _resize3 |
|---|
| 686 | metawidget command Document _withdraw _withdraw |
|---|
| 687 | metawidget command Document _maximize _maximize |
|---|
| 688 | metawidget command Document _minimize _minimize |
|---|
| 689 | metawidget command Document _restore _restore |
|---|
| 690 | metawidget command Document _motion _motion |
|---|
| 691 | |
|---|
| 692 | metawidget command Document menu menu_ |
|---|
| 693 | metawidget command Document lower lower_ |
|---|
| 694 | metawidget command Document raise raise_ |
|---|
| 695 | metawidget command Document pack pack_ |
|---|
| 696 | metawidget command Document grid grid_ |
|---|
| 697 | metawidget command Document place place_ |
|---|
| 698 | metawidget command Document Arrange Arrange |
|---|
| 699 | |
|---|
| 700 | metawidget option Document -x -x |
|---|
| 701 | metawidget option Document -y -y |
|---|
| 702 | metawidget option Document -width -width |
|---|
| 703 | metawidget option Document -height -height |
|---|
| 704 | metawidget option Document -font -font |
|---|
| 705 | metawidget option Document -image -image |
|---|
| 706 | metawidget option Document -title -title |
|---|
| 707 | metawidget option Document -state -state |
|---|
| 708 | metawidget option Document -foreground |
|---|
| 709 | metawidget option Document -background |
|---|
| 710 | metawidget option Document -minsize |
|---|
| 711 | metawidget option Document -icontext |
|---|
| 712 | |
|---|
| 713 | proc test {} { |
|---|
| 714 | pack [frame .w -back darkgray] -fill both -expand 1 |
|---|
| 715 | document .w.d1 |
|---|
| 716 | document .w.d2 |
|---|
| 717 | document .w.d3 |
|---|
| 718 | |
|---|
| 719 | .w.d3 pack [label .w.d3.f -border 2 -relief sunken -text "1"] -fill both -expand 1 |
|---|
| 720 | pack [label .w.d3.f.f -border 2 -relief raised -text "2"] -fill both -expand 1 |
|---|
| 721 | } |
|---|
| 722 | |
|---|
| 723 | #test |
|---|