summaryrefslogtreecommitdiff
path: root/gdb/gdbtk/library/managedwin.itb
blob: e1c75669324885715adccebfa8369c33a49f1b64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# Managed window for Insight.
# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License (GPL) as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.


# ------------------------------------------------------------
#  PUBLIC METHOD:  constructor
# ------------------------------------------------------------
itcl::body ManagedWin::constructor {args} {
  #debug "$this args=$args"
  set _top [winfo toplevel $itk_interior]
}

# ------------------------------------------------------------
#  PUBLIC METHOD: destructor
# ------------------------------------------------------------
itcl::body ManagedWin::destructor {} {
  # If no toplevels remain, quit.  However, check the quit_if_last
  # flag since we might be doing something like displaying a 
  # splash screen at startup...

  if {!$numTopWins && [quit_if_last]} {
    if {$::iipc && [pref get gdb/ipc/exit]} {
      $::insight_ipc send quit
    }
    gdb_force_quit
  } else {
    destroy_toplevel
  }
}

# ------------------------------------------------------------
#  PUBLIC METHOD:  window_name - Set the name of the window
#   (and optionally its icon's name).
# ------------------------------------------------------------
itcl::body ManagedWin::window_name {wname {iname ""}} {

  if {$wname != ""} {
    set _wname $wname
  } else {
    set wname $_wname
  }
  if {$iname != ""} {
    set _iname $iname
  } else {
    set iname $_iname
  }

  if {$win_instance != ""} {
    append wname " \[$win_instance\]"
    if {$iname != ""} {
      append iname " \[$win_instance\]"
    }
  }
  wm title $_top $wname
  if {$iname != ""} {
    wm iconname $_top $iname
  } else {
    wm iconname $_top $wname
  }
}

# ------------------------------------------------------------
#  PUBLIC METHOD:  window_instance - Set the string to be
#   appended to each window title for this instance of Insight
# ------------------------------------------------------------
itcl::body ManagedWin::window_instance {ins} {
  set win_instance $ins
  foreach obj [itcl_info objects -isa ManagedWin] {
    debug "$obj ManagedWin::_wname"
    $obj window_name ""
  }
}

# ------------------------------------------------------------
#  PUBLIC METHOD: pickle - This is the base class pickle
#   method.  It returns a command that can be used to recreate
#   this particular window.  
# ------------------------------------------------------------
itcl::body ManagedWin::pickle {} {
  return [list ManagedWin::open [namespace tail [info class]]]
}

# ------------------------------------------------------------
#  PUBLIC METHOD:  reveal
# ------------------------------------------------------------
itcl::body ManagedWin::reveal {} {
  # Do this update to flush all changes before deiconifying the window.
  update idletasks
  
  raise $_top
  wm deiconify $_top

  # Some window managers (on unix) fail to honor the geometry unless
  # the window is visible.
  if {[info exists ::$_top._init_geometry]} {
    upvar ::$_top._init_geometry gm
    if {$::tcl_platform(platform) == "unix"} {
      wm geometry $_top $gm
    }
    unset ::$_top._init_geometry
  }
  
  # There used to be a `focus -force' here, but using -force is
  # unfriendly, so it was removed.  It was then replaced with a simple
  # `focus $top'.  However, this has no useful effect -- it just
  # resets the subwindow of $top which has the `potential' focus.
  # This can actually be confusing to the user.

  # NOT for Windows, though. Without the focus, we get, eg. a
  # register window on top of the source window, but the source window
  # will have the focus. This is not the proper model for Windows.
  if {$::tcl_platform(platform) == "windows"} {
    focus -force [focus -lastfor $_top]
  }
}

# ------------------------------------------------------------
#  PUBLIC PROC:  restart
# ------------------------------------------------------------
itcl::body ManagedWin::restart {} {
  # This is needed in case we've called "gdbtk_busy" before the restart.
  # This will configure the stop/run button as necessary
  after idle gdbtk_idle
  
  # call the reconfig method for each object
  foreach obj [itcl_info objects -isa ManagedWin] {
    if {[catch {$obj reconfig} msg]} {
      dbug W "reconfig failed for $obj - $msg"
    } 
  }
}

# ------------------------------------------------------------------
#  PUBLIC PROC:  shutdown - This writes all the active windows to
#   the preferences file, so they can be restored at startup.
#   FIXME: Currently assumes only ONE window per type...
# ------------------------------------------------------------------
itcl::body ManagedWin::shutdown {} {
  set activeWins {}
  foreach win [itcl_info objects -isa ManagedWin] {
    if {![$win isa ModalDialog] && ![$win _ignore_on_save]} {
      set g [wm geometry [winfo toplevel [namespace tail $win]]]
      pref setd gdb/geometry/[namespace tail $win] $g
      lappend activeWins [$win pickle]
    }
  }
  pref set gdb/window/active $activeWins
}

# ------------------------------------------------------------------
#  PUBLIC PROC:  startup - This restores all the windows that were
#   opened at shutdown.
#   FIXME: Currently assumes only ONE window per type...
# ------------------------------------------------------------------
itcl::body ManagedWin::startup {} {
  debug "Got active list [pref get gdb/window/active]"

  foreach cmd [pref get gdb/window/active] {
    eval $cmd
  }
  # If we open the source window, and a source window already exists,
  # then we end up raising it twice during startup.  This yields an
  # annoying effect for the user: if the user tries the bury the
  # source window during startup, it will raise itself again.  This
  # explains why we first check to see if a source window exists
  # before trying to create it -- raising the window is an inevitable
  # side effect of the creation process.
  if {[llength [find SrcWin]] == 0} {
    ManagedWin::open SrcWin
  }
}

# ------------------------------------------------------------
#  PUBLIC PROC:  open_dlg
# ------------------------------------------------------------
itcl::body ManagedWin::open_dlg {class args} {
  
  set newwin [eval _open $class $args]
  if {$newwin != ""} {
    $newwin reveal
    $newwin post
  }
}

# ------------------------------------------------------------
#  PUBLIC PROC:  open
# ------------------------------------------------------------
itcl::body ManagedWin::open {class args} {
  
  set newwin [eval _open $class $args]
  if {$newwin != ""} {
    if {[$newwin isa ModalDialog]} {
      parse_args [list {expire 0}]
      after idle "$newwin reveal; $newwin post 0 $expire"
    } else {
      after idle "$newwin reveal"
    }
  }
  
  return $newwin
}

# ------------------------------------------------------------
#  PRIVATE PROC:  _open
# ------------------------------------------------------------
itcl::body ManagedWin::_open { class args } {
  debug "$class $args"
  
  parse_args force

  if {!$force} {
    # check all windows for one of this type
    foreach obj [itcl_info objects -isa ManagedWin] {
      if {[$obj isa $class]} {
	$obj reveal
	return $obj
      }
    }
    
  }
  # need to create a new window
  return [eval _create $class $args]
}

# ------------------------------------------------------------
#  PRIVATE PROC:  _create
# ------------------------------------------------------------
itcl::body ManagedWin::_create { class args } {
  
  set win [string tolower $class]
  debug "win=$win args=$args"
  
  parse_args {center transient {over ""}} 
  
  # increment window numbers until we get an unused one
  set i 0
  while {[winfo exists .$win$i]} { incr i }
  
  while { 1 } {
    set top [toplevel .$win$i]
    wm withdraw $top
    wm protocol $top WM_DELETE_WINDOW "destroy $top"
    wm group $top .
    set newwin $top.$win
    if {[catch {uplevel \#0 eval $class $newwin $args} msg]} {
      dbug E "object creation of $class failed: $msg"
      dbug E $::errorInfo
      if {[string first "object already exists" $msg] != -1} {
	# sometimes an object is still really around even though
	# [winfo exists] said it didn't exist.  Check for this case
	# and increment the window number again.
	catch {destroy $top}
	incr i
      } else {
	return ""
      }
    } else {
      break
    }
  }
  
  if {[catch {pack $newwin -expand yes -fill both}]} {
    dbug W "packing of $newwin failed: $::errorInfo"
    return ""
  }
  
  wm maxsize $top $_screenwidth $_screenheight
  wm minsize $top 20 20
  update idletasks

  if {$over != ""} {
    # center new window
    center_window $top -over [winfo toplevel [namespace tail $over]]
  } elseif {$center} {
    center_window $top
  }

  if {$transient} {
    wm resizable $top 0 0

    # If a SrcWin is around, use its toplevel as the master for
    # the transient. Otherwise use ".". (The splash screen will
    # need ".", for example.)
    set srcs [ManagedWin::find SrcWin]
    if {[llength $srcs] > 0} {
      set w [winfo toplevel [namespace tail [lindex $srcs 0]]]
    } else {
      set w .
    }
    wm transient $top $w
  } elseif {$::tcl_platform(platform) == "unix"} {
    # Modal dialogs DONT get Icons...
    if {[pref get gdb/use_icons] && ![$newwin isa ModalDialog]} {
      set icon [_make_icon_window ${top}_icon]
      wm iconwindow $top $icon
      bind $icon <Double-1> "$newwin reveal"
    }
  }
  
  if {[info exists ::env(GDBTK_TEST_RUNNING)] && $::env(GDBTK_TEST_RUNNING)} {
    set g "+100+100"
    wm geometry $top $g
    wm positionfrom $top user
  } else {
    set g [pref getd gdb/geometry/$newwin]
    if {$g == "1x1+0+0"} { 
      dbug E "bad geometry"
      set g ""
    }
    if {$g != ""} {
      # OK. We have a requested geometry. We know that it fits on the screen
      # because we set the maxsize.  Now we have to make sure it will not be
      # displayed off the screen.
      set w 0; set h 0; set x 0; set y 0
      if {![catch {scan $g  "%dx%d%d%d" w h x y} res]} {
	if {$x < 0} {
	  set x [expr $_screenwidth + $x]
	}
	if {$y < 0} {
	  set y [expr $_screenheight + $y]
	}
	
	# If the window is transient, then don't reset its size, since
	# the user didn't set this anyway, and in some cases where the
	# size can change dynamically, like the Global Preferences
	# dialog, this can hide parts of the dialog with no recourse...
	
	# if dont_remember_size is true, don't set size, just like
	# transients
	
	if {$transient || [dont_remember_size]} {
	  set g "+${x}+${y}"
	} else {
	  set g "${w}x${h}+${x}+${y}"
	}
	if {[expr $x+50] < $_screenwidth && [expr $y+20] < $_screenheight} {
	  wm positionfrom $top user
	  wm geometry $top $g
	  set ::$top._init_geometry $g
	}
      }
    }
  }

  bind $top <Alt-F4> [list delete object $newwin]

  return $newwin
}

# ------------------------------------------------------------
#  PUBLIC PROC:  find
# ------------------------------------------------------------
itcl::body ManagedWin::find { win } {
  debug "$win"
  set res ""
  foreach obj [itcl_info objects -isa ManagedWin] {
    if {[$obj isa $win]} {
      lappend res $obj
    }
  }
  return $res
}

# ------------------------------------------------------------
#  PUBLIC PROC:  init
# ------------------------------------------------------------
itcl::body ManagedWin::init {} {
  wm withdraw .
  set _screenheight [winfo screenheight .]
  set _screenwidth [winfo screenwidth .]
}

# ------------------------------------------------------------
#  PUBLIC METHOD:  destroy_toplevel
# ------------------------------------------------------------
itcl::body ManagedWin::destroy_toplevel {} {
  after idle "update idletasks;destroy $_top"
}

# ------------------------------------------------------------
#  PROTECTED METHOD:  _freeze_me
# ------------------------------------------------------------
itcl::body ManagedWin::_freeze_me {} {
  $_top configure -cursor watch
  ::update idletasks
}

# ------------------------------------------------------------
#  PROTECTED METHOD: _thaw_me
# ------------------------------------------------------------
itcl::body ManagedWin::_thaw_me {} {

  $_top configure -cursor {}
  ::update idletasks
}

# ------------------------------------------------------------------
#  PRIVATE PROC: _make_icon_window - create a small window with an
#   icon in it for use by certain Unix window managers.
# ------------------------------------------------------------------
itcl::body ManagedWin::_make_icon_window {name {file "gdbtk_icon"}} {
  if {![winfo exists $name]} {
    toplevel $name
    label $name.im -image \
      [image create photo icon_photo -file [file join $::gdb_ImageDir $file.gif]]
  }
  pack $name.im
  return $name
}