WindowGroup.st
changeset 90 b1f1d7fc96eb
parent 86 032006651226
child 103 6156d12a414d
equal deleted inserted replaced
89:ea2bf46eb669 90:b1f1d7fc96eb
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 Object subclass:#WindowGroup
    13 Object subclass:#WindowGroup
    14 	 instanceVariableNames:'views topViews myProcess mySensor isModal previousGroup'
    14 	 instanceVariableNames:'views topViews myProcess mySensor isModal previousGroup 
       
    15 				focusView focusSequence'
    15 	 classVariableNames:'ActiveGroup ScheduledWindowGroups LeaveSignal'
    16 	 classVariableNames:'ActiveGroup ScheduledWindowGroups LeaveSignal'
    16 	 poolDictionaries:''
    17 	 poolDictionaries:''
    17 	 category:'Interface-Support'
    18 	 category:'Interface-Support'
    18 !
    19 !
    19 
    20 
    20 WindowGroup comment:'
    21 WindowGroup comment:'
    21 COPYRIGHT (c) 1993 by Claus Gittinger
    22 COPYRIGHT (c) 1993 by Claus Gittinger
    22 	      All Rights Reserved
    23 	      All Rights Reserved
    23 
    24 
    24 $Header: /cvs/stx/stx/libview/WindowGroup.st,v 1.16 1994-11-28 21:01:20 claus Exp $
    25 $Header: /cvs/stx/stx/libview/WindowGroup.st,v 1.17 1995-02-06 00:39:42 claus Exp $
    25 '!
    26 '!
    26 
    27 
    27 !WindowGroup class methodsFor:'documentation'!
    28 !WindowGroup class methodsFor:'documentation'!
    28 
    29 
    29 copyright
    30 copyright
    40 "
    41 "
    41 !
    42 !
    42 
    43 
    43 version
    44 version
    44 "
    45 "
    45 $Header: /cvs/stx/stx/libview/WindowGroup.st,v 1.16 1994-11-28 21:01:20 claus Exp $
    46 $Header: /cvs/stx/stx/libview/WindowGroup.st,v 1.17 1995-02-06 00:39:42 claus Exp $
    46 "
    47 "
    47 !
    48 !
    48 
    49 
    49 documentation
    50 documentation
    50 "
    51 "
   188     "set the windowGroups sensor"
   189     "set the windowGroups sensor"
   189 
   190 
   190     mySensor := aSensor
   191     mySensor := aSensor
   191 ! !
   192 ! !
   192 
   193 
   193 !WindowGroup methodsFor:'enumeration'!
   194 !WindowGroup methodsFor:'enumerating'!
   194 
   195 
   195 allViewsDo:aBlock
   196 allViewsDo:aBlock
   196     "evaluate aBlock for all views & topviews in this group"
   197     "evaluate aBlock for all views & topviews in this group"
   197 
   198 
   198     topViews notNil ifTrue:[topViews do:aBlock].
   199     topViews notNil ifTrue:[topViews do:aBlock].
   263 
   264 
   264 processEvent
   265 processEvent
   265     "process a single event from either the damage- or user input queues.
   266     "process a single event from either the damage- or user input queues.
   266      Debugger abort brings us back here."
   267      Debugger abort brings us back here."
   267 
   268 
   268     |event|
   269     |event ignore|
   269 
   270 
   270     self processExposeEvents.
   271     self processExposeEvents.
   271     [mySensor hasEvents] whileTrue:[
   272     [mySensor hasEvents] whileTrue:[
   272 	event := mySensor nextEvent.
   273 	event := mySensor nextEvent.
   273 	(views isNil and:[topViews isNil]) ifFalse:[
   274 	event notNil ifTrue:[
   274 	    event sendEvent.
   275 	    (views isNil and:[topViews isNil]) ifFalse:[
       
   276 
       
   277 		ignore := false.
       
   278 		event isKeyPressEvent ifTrue:[
       
   279 		    event key == #FocusNext ifTrue:[
       
   280 			self focusNext.
       
   281 			ignore := true
       
   282 		    ].
       
   283 		    event key == #FocusPrevious ifTrue:[
       
   284 			self focusPrevious.
       
   285 			ignore := true
       
   286 		    ].
       
   287 		].
       
   288 		"
       
   289 		 button events turn off explicit focus, and revert
       
   290 		 to implicit focus control
       
   291 		"
       
   292 		(focusView notNil
       
   293 		and:[event isButtonEvent]) ifTrue:[
       
   294 		    self focusView:nil
       
   295 		].
       
   296 
       
   297 		ignore ifFalse:[
       
   298 		    AbortSignal catch:[
       
   299 			event sendEventWithFocusOn:focusView.
       
   300 		    ]
       
   301 		]
       
   302 	    ]
   275 	].
   303 	].
   276     ]
   304     ]
   277 !
   305 !
   278 
   306 
   279 processExposeEvents
   307 processExposeEvents
   280     "process all expose events from the damage queue"
   308     "process all expose events from the damage queue"
   281 
   309 
   282     |event view rect oldActive|
   310     |event view rect oldActive x y w h|
   283 
   311 
   284     oldActive := ActiveGroup.
   312     oldActive := ActiveGroup.
   285     ActiveGroup := self.
   313     [
   286     [mySensor notNil and:[mySensor hasDamage]] whileTrue:[
   314 	[mySensor notNil and:[mySensor hasDamage]] whileTrue:[
   287 	event := mySensor nextDamage.
   315 	    ActiveGroup := self.
   288 	event notNil ifTrue:[
   316 	    event := mySensor nextDamage.
   289 	    (views isNil and:[topViews isNil]) ifFalse:[
   317 	    event notNil ifTrue:[
   290 		event isDamage ifTrue:[
   318 		(views isNil and:[topViews isNil]) ifFalse:[
   291 		    view := event view.
   319 		    event isDamage ifTrue:[
   292 		    rect := event rectangle.
   320 			view := event view.
   293 		    view shown ifTrue:[
   321 			rect := event rectangle.
   294 			view transformation notNil ifTrue:[
   322 			view shown ifTrue:[
   295 			    view deviceExposeX:(rect left) y:(rect top) width:(rect width) height:(rect height)
   323 			    rect := event rectangle.
   296 			] ifFalse:[
   324 			    x := rect left.
   297 			    view exposeX:(rect left) y:(rect top) width:(rect width) height:(rect height)
   325 			    y := rect top.
       
   326 			    w := rect width.
       
   327 			    h := rect height.
       
   328 			    view transformation notNil ifTrue:[
       
   329 				view deviceExposeX:x y:y width:w height:h
       
   330 			    ] ifFalse:[
       
   331 				view exposeX:x y:y width:w height:h
       
   332 			    ]
   298 			]
   333 			]
       
   334 		    ] ifFalse:[
       
   335 			"
       
   336 			 mhmh - could we possibly arrive here ?
       
   337 			"
       
   338 			event sendEvent.
   299 		    ]
   339 		    ]
   300 		] ifFalse:[
       
   301 		    event sendEvent.
       
   302 		]
   340 		]
   303 	    ]
   341 	    ]
   304 	]
   342 	]
   305     ].
   343     ] valueNowOrOnUnwindDo:[
   306     ActiveGroup := oldActive
   344 	ActiveGroup := oldActive.
       
   345 	oldActive := nil
       
   346     ]
   307 !
   347 !
   308 
   348 
   309 eventLoop
   349 eventLoop
   310     "loop executed by windowGroup process;
   350     "loop executed by windowGroup process;
   311      wait-for and process events forever"
   351      wait-for and process events forever"
   312 
   352 
   313    self eventLoopWhile:[true]
   353    self eventLoopWhile:[true]
   314 !
   354 !
   315 
   355 
   316 eventLoopWhile:aBlock
   356 eventLoopWhile:aBlock
   317     "wait-for and process events while aBlock evaluates to true."
   357     "wait-for and process events. 
   318 
   358      Stay in this loop while there are still any views to dispatch for,
   319     |abortSignal|
   359      and aBlock evaluates to true."
   320 
   360 
   321     abortSignal := Object abortSignal.
   361     |oldActive|
   322     "/ ScheduledWindowGroups add:self.
   362 
   323 
   363     oldActive := ActiveGroup.
   324     (SignalSet with:LeaveSignal with:abortSignal)
   364 "/     ScheduledWindowGroups add:self.
   325     handle:[:ex |
   365 
   326 	ex return
   366     [
   327     ] do:[
   367 	(SignalSet with:LeaveSignal with:AbortSignal)
   328 	|p g oldActive mainGroup|
   368 	handle:[:ex |
   329 
   369 "/            ActiveGroup := oldActive.
   330 	isModal ifTrue:[
   370 "/            oldActive := nil.
   331 	    mainGroup := self mainGroup.
   371 	    ex return
       
   372 	] do:[
       
   373 	    |p g mainGroup|
       
   374 
       
   375 	    isModal ifTrue:[
       
   376 		mainGroup := self mainGroup.
       
   377 	    ].
       
   378 
       
   379 	    aBlock whileTrue:[ 
       
   380 		(views isNil and:[topViews isNil]) ifTrue:[
       
   381 "/                     ScheduledWindowGroups remove:self ifAbsent:[].
       
   382 		    myProcess notNil ifTrue:[
       
   383 			p := myProcess.
       
   384 			myProcess := nil.
       
   385 			p terminate.
       
   386 			"not reached - there is no life after death"
       
   387 		     ].
       
   388 		     "
       
   389 		      this is the end of a modal loop
       
   390 		      (not having a private process ...)
       
   391 		     "
       
   392 		     ^ self
       
   393 		].
       
   394 
       
   395 		AbortSignal handle:[:ex |
       
   396 "/                    ActiveGroup := oldActive.
       
   397 "/                    oldActive := nil.
       
   398 		    ex return
       
   399 		] do:[
       
   400 		    "
       
   401 		     if modal, break out of the wait after some time
       
   402 		     to allow servicing update-events of the blocked
       
   403 		     windowgroup.
       
   404 		    "
       
   405 		    Processor activeProcess setStateTo:#eventWait if:#active.
       
   406 		    isModal ifTrue:[
       
   407 			mySensor eventSemaphore waitWithTimeout:0.2.
       
   408 		    ] ifFalse:[
       
   409 			mySensor eventSemaphore wait.
       
   410 		    ].
       
   411 		    ActiveGroup := self.
       
   412 		    self processEvent
       
   413 		].
       
   414 "/                ActiveGroup := oldActive.
       
   415 
       
   416 		"
       
   417 		 if modal, also check for redraw events in my maingroup
       
   418 		 (we arrive here after every event for myself or after the
       
   419 		  above timeout)
       
   420 		"
       
   421 		mainGroup notNil ifTrue:[
       
   422 		    mainGroup processExposeEvents.
       
   423 		]
       
   424 	    ]
   332 	].
   425 	].
   333 
   426     ] valueNowOrOnUnwindDo:[
   334 	aBlock whileTrue:[ 
   427 "/     ScheduledWindowGroups remove:self ifAbsent:[].
   335 	    (views isNil and:[topViews isNil]) ifTrue:[
   428 	ActiveGroup := oldActive.
   336 		"/ ScheduledWindowGroups remove:self ifAbsent:[].
   429 	oldActive := nil.
   337 		myProcess notNil ifTrue:[
   430     ].
   338 		    p := myProcess.
       
   339 		    myProcess := nil.
       
   340 		    p terminate.
       
   341 		    "not reached - there is no life after death"
       
   342 		 ].
       
   343 		 "
       
   344 		  this is the end of a modal loop
       
   345 		  (not having a private process ...)
       
   346 		 "
       
   347 		 ^ self
       
   348 	    ].
       
   349 	    abortSignal handle:[:ex |
       
   350 		ex return
       
   351 	    ] do:[
       
   352 		"
       
   353 		 if modal, break out of the wait after some time
       
   354 		 to allow servicing update-events of the blocked
       
   355 		 windowgroup.
       
   356 		"
       
   357 		isModal ifTrue:[
       
   358 		    mySensor eventSemaphore waitWithTimeout:0.2.
       
   359 		] ifFalse:[
       
   360 		    Processor activeProcess setStateTo:#eventWait if:#active.
       
   361 		    mySensor eventSemaphore wait.
       
   362 		].
       
   363 		oldActive := ActiveGroup.
       
   364 		ActiveGroup := self.
       
   365 		self processEvent
       
   366 	    ].
       
   367 	    ActiveGroup := oldActive.
       
   368 	    oldActive := nil.
       
   369 
       
   370 	    "
       
   371 	     if modal, also check for redraw events in my maingroup
       
   372 	     (we arrive here after every event for myself or after the
       
   373 	      above timeout)
       
   374 	    "
       
   375 	    mainGroup notNil ifTrue:[
       
   376 		mainGroup processExposeEvents.
       
   377 	    ]
       
   378 	]
       
   379     ].
       
   380     "/ ScheduledWindowGroups remove:self ifAbsent:[].
       
   381 !
   431 !
   382 
   432 
   383 waitForExposeFor:aView
   433 waitForExposeFor:aView
   384     "wait for a noExpose on aView, then process all exposes.
   434     "wait for a noExpose on aView, then process all exposes.
   385      To be used after a scroll"
   435      To be used after a scroll"
   386 
   436 
   387     mySensor waitForExposeFor:aView.
   437     mySensor waitForExposeFor:aView.
   388     self processExposeEvents
   438     AbortSignal catch:[
       
   439 	self processExposeEvents
       
   440     ]
   389 !
   441 !
   390 
   442 
   391 leaveEventLoop
   443 leaveEventLoop
   392     ^ LeaveSignal raise
   444     ^ LeaveSignal raise
   393 ! !
   445 ! !
   417     |nm|
   469     |nm|
   418 
   470 
   419     previousGroup := nil.
   471     previousGroup := nil.
   420     myProcess isNil ifTrue:[
   472     myProcess isNil ifTrue:[
   421 	isModal := false.
   473 	isModal := false.
   422 	"/ ScheduledWindowGroups add:self.
       
   423 	myProcess := [
   474 	myProcess := [
   424 	    topViews notNil ifTrue:[
   475 	    topViews notNil ifTrue:[
   425 		topViews do:[:aView |
   476 		topViews do:[:aView |
   426 		    aView realize
   477 		    aView realize
   427 		].
   478 		].
   496     topViews notNil ifTrue:[
   547     topViews notNil ifTrue:[
   497 	topViews do:[:aTopView | aTopView destroy]
   548 	topViews do:[:aTopView | aTopView destroy]
   498     ].
   549     ].
   499     views := nil.
   550     views := nil.
   500     topViews := nil.
   551     topViews := nil.
   501     "/ ScheduledWindowGroups remove:self ifAbsent:[].
   552 "/     ScheduledWindowGroups remove:self ifAbsent:[].
   502 !
   553 !
   503 
   554 
   504 shutdown
   555 shutdown
   505     "shutdow the window group; close all views and
   556     "shutdow the window group; close all views and
   506      terminate process"
   557      terminate process"
   509 
   560 
   510     self closeDownViews.
   561     self closeDownViews.
   511     myProcess notNil ifTrue:[
   562     myProcess notNil ifTrue:[
   512 	p := myProcess.
   563 	p := myProcess.
   513 	myProcess := nil.
   564 	myProcess := nil.
   514 	"/ ScheduledWindowGroups remove:self ifAbsent:[].
   565 "/         ScheduledWindowGroups remove:self ifAbsent:[].
   515 	p terminate.
   566 	p terminate.
   516     ]
   567     ]
   517 ! !
   568 ! !
   518 
   569 
   519 !WindowGroup methodsFor:'initialization'!
   570 !WindowGroup methodsFor:'initialization'!
   542     mySensor := WindowSensor new.
   593     mySensor := WindowSensor new.
   543     mySensor eventSemaphore:Semaphore new.
   594     mySensor eventSemaphore:Semaphore new.
   544     isModal := false.
   595     isModal := false.
   545 ! !
   596 ! !
   546 
   597 
       
   598 !WindowGroup methodsFor:'focus control'!
       
   599 
       
   600 focusSequence:aSequenceableCollection
       
   601     "define the focus sequence for focusNext/focusPrevious.
       
   602      Focus is stepped in the order in which subviews occur in
       
   603      the sequence"
       
   604 
       
   605     focusSequence := aSequenceableCollection
       
   606 !
       
   607 
       
   608 focusView
       
   609     "return the view which has the focus"
       
   610 
       
   611     ^ focusView
       
   612 !
       
   613 
       
   614 focusView:aViewOrNil
       
   615     "give focus to aViewOrNil"
       
   616 
       
   617     focusView notNil ifTrue:[
       
   618 	focusView focusOut.
       
   619     ].
       
   620     focusView := aViewOrNil.
       
   621     focusView notNil ifTrue:[
       
   622 	focusView focusIn
       
   623     ].
       
   624 
       
   625     "
       
   626      |top v1 v2|
       
   627 
       
   628      top := StandardSystemView new.
       
   629      v1 := EditTextView origin:0.0@0.0 corner:1.0@0.5 in:top.
       
   630      v2 := EditTextView origin:0.0@0.5 corner:1.0@1.0 in:top.
       
   631      top open.
       
   632      top windowGroup focusView:v1.
       
   633     "
       
   634 !
       
   635 
       
   636 focusNext
       
   637     "give focus to next view in focusSequence"
       
   638 
       
   639     |index|
       
   640 
       
   641     focusSequence isNil ifTrue:[^ self].
       
   642     focusView notNil ifTrue:[
       
   643 	index := (focusSequence indexOf:focusView) + 1.
       
   644 	index > focusSequence size ifTrue:[index := 1].
       
   645     ] ifFalse:[
       
   646 	index := 1.
       
   647     ].
       
   648     self focusView:(focusSequence at:index)
       
   649 
       
   650     "
       
   651      |top v1 v2|
       
   652 
       
   653      top := StandardSystemView new.
       
   654      v1 := EditTextView origin:0.0@0.0 corner:1.0@0.5 in:top.
       
   655      v2 := EditTextView origin:0.0@0.5 corner:1.0@1.0 in:top.
       
   656      top open.
       
   657      top windowGroup focusSequence:(Array with:v1 with:v2).
       
   658      top windowGroup focusOn:v1.
       
   659      (Delay forSeconds:10) wait.
       
   660      top windowGroup focusNext.
       
   661     "
       
   662 !
       
   663 
       
   664 focusPrevious
       
   665     "give focus to previous view in focusSequence"
       
   666 
       
   667     |index|
       
   668 
       
   669     focusSequence isNil ifTrue:[^ self].
       
   670     focusView notNil ifTrue:[
       
   671 	index := (focusSequence indexOf:focusView) - 1.
       
   672 	index < 1 ifTrue:[index := focusSequence size].
       
   673     ] ifFalse:[
       
   674 	index := focusSequence size.
       
   675     ].
       
   676     self focusView:(focusSequence at:index)
       
   677 ! !
       
   678 
   547 !WindowGroup methodsFor:'printing'!
   679 !WindowGroup methodsFor:'printing'!
   548 
   680 
   549 printString
   681 printOn:aStream
   550     "return a printed representation;
   682     "return a printed representation;
   551      just for more user friendlyness, add name of process."
   683      just for more user friendlyness, add name of process."
   552 
   684 
   553     myProcess isNil ifTrue:[^ super printString].
   685     myProcess isNil ifTrue:[
   554     ^ 'WindowGroup(' , myProcess nameOrId , ')'
   686 	(previousGroup notNil and:[previousGroup process notNil]) ifTrue:[
   555 ! !
   687 	    aStream nextPutAll:('WindowGroup(modal in ' , previousGroup process nameOrId , ')').
       
   688 	    ^ self.
       
   689 	].
       
   690 	^ super printOn:aStream
       
   691     ].
       
   692     aStream nextPutAll:('WindowGroup(' , myProcess nameOrId , ')')
       
   693 ! !