ActiveHelp.st
changeset 100 0300e64bb883
parent 98 ab8ed9e213d0
child 101 44a6c9a92c00
--- a/ActiveHelp.st	Wed Aug 30 19:54:43 1995 +0200
+++ b/ActiveHelp.st	Sat Sep 09 04:30:16 1995 +0200
@@ -24,7 +24,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libview2/ActiveHelp.st,v 1.4 1995-08-29 23:42:57 claus Exp $
+$Header: /cvs/stx/stx/libview2/ActiveHelp.st,v 1.5 1995-09-09 02:29:12 claus Exp $
 "
 !
 
@@ -33,13 +33,107 @@
     The active help listener.
     The one and only instance of myself intercepts incoming mouse & keyboard 
     events for the display device, being especially interested in view-enter/
-    leave ebents. When such an event arrives, it asks the corresponding view
+    leave enents. When such an event arrives, it asks the corresponding view
     or its model for a help message and display it via an ActiveHelpView.
+    This query is repeated along the views superView chain, until any model or
+    view returns a nonNil answer for the #helpTextFor:at or #helpTextFor
+    message.
+
     All I need for automatic help is some model/view/applicationModel along
     the superview chain of the entered component, which responds to the
     #helpTextFor: message with a non-nil (string-) answer.
     I close down the help view after a while, if a key is pressed or the mouse
     moved to another view.
+
+    Who should provide the helpText:
+
+	the best place is the application object (an instance of ApplicationModel)
+	or the topView, if its a derived class of StandardSystemView.
+	This should know about its components and return the string
+	when asked via #helpTextFor:aComponent.
+	See examples in FileBrowser, NewLauncher etc.
+
+    Be aware, that for applicationModels, there must be a link from the
+    topView to this applicationModel 
+    (set via: aTopView application:anApplicationModel)
+    otherwise, the helpManager has no means of finding the application which
+    corresponds to a view.
+
+    Who should display the helpText:
+
+	by default, the helpListener opens a little popup view, which displays the
+	returned help message. However, a nice trick which can be used by applications
+	is to create an infoLabel as a subview of the topFrame (a la windows)
+	and display the text right in the #helpTextFor: method. To cheat the
+	help listener, this method should then return nil, to keep it silent.
+"
+!
+
+examples
+"
+    (make certain that activeHelp is turned on ...)
+
+    the following example uses a Plug as a model replacement.
+    In concrete application, you would create a method to implement the helpText
+    query message.
+
+	|app top button1 button2|
+
+	app := Plug new.
+	app respondTo:#helpTextFor:
+		 with:[:view | 
+			       view == button1 ifTrue:[
+				 'this is button1'
+			       ] ifFalse:[
+				 view == button2 ifTrue:[
+				   'some help for button2'
+				 ] ifFalse:[
+				   nil
+				 ]
+			       ]
+		      ].
+
+	top := StandardSystemView new.
+	top extent:300@100.
+	button1 := Button label:'b1' in:top.
+	button1 origin:0.0@0.0 corner:0.5@30. 
+	button2 := Button label:'b2' in:top.
+	button2 origin:0.5@0.0 corner:1.0@30.
+	top model:app. '<-- normally this would be: top application:app'.
+	top open
+
+    alternative, display of the helpMessage in a local, private view:
+
+	|app top button1 button2 infoView|
+
+	app := Plug new.
+	app respondTo:#helpTextFor:
+		 with:[:view | infoView label:'info ...'.
+			       view == button1 ifTrue:[
+				 infoView label:'this is button1'
+			       ].
+			       view == button2 ifTrue:[
+				 infoView label:'some help for button2'
+			       ].
+			       nil
+		      ].
+
+	top := StandardSystemView new.
+	top extent:300@100.
+	button1 := Button label:'b1' in:top.
+	button1 origin:0.0@0.0 corner:0.5@30. 
+	button2 := Button label:'b2' in:top.
+	button2 origin:0.5@0.0 corner:1.0@30.
+	infoView := Label label:'info ...' in:top.
+	infoView level:-1; origin:0.0@1.0 corner:1.0@1.0.
+	infoView topInset:(infoView preferredExtent y negated - 3);
+		 leftInset:3; 
+		 rightInset:3; 
+		 bottomInset:3;
+		 adjust:#left.
+	top model:app. '<-- normally this would be: top application:app'.
+	top open
+
 "
 !
 
@@ -62,13 +156,41 @@
 
 initialize
     ShowTime := 15.
-    DelayTime := 1.
+    DelayTime := 2.
 
     "
      ActiveHelp initialize
     "
 ! !
 
+!ActiveHelp class methodsFor:'times'!
+
+showTime:numberOfSeconds
+    "set the number of seconds, a help messages is to be shown.
+     The default is 15 seconds."
+
+    ShowTime := numberOfSeconds
+
+    "
+     ActiveHelp showTime:10
+     ActiveHelp showTime:99999 
+     ActiveHelp showTime:30
+    "
+!
+
+delayTime:numberOfSeconds
+    "set the delay (the time, the cursor has to be in the view
+     before help is shown). The default is 2 seconds."
+
+    DelayTime := numberOfSeconds
+
+    "
+     ActiveHelp delayTime:0.5
+     ActiveHelp delayTime:2
+     ActiveHelp delayTime:10
+    "
+! !
+
 !ActiveHelp class methodsFor:'startup'!
 
 start
@@ -100,12 +222,17 @@
 !ActiveHelp methodsFor:'private'!
 
 helpTextFor:aView atX:x y:y
+    "pointer entered aView; 
+     walk along the views superView chain,
+     asking models and views encountered while walking.
+     The first one who understands and returns a nonNil answer to the
+     #helpTextFor:at: or #helpTextFor: message ends this walk and the
+     returned string is returned."
+
     |model text view org found v sv|
 
     view := aView.
-
     (model := aView model) notNil ifTrue:[
-"/ model printNL.
 	(model respondsTo:#helpTextFor:at:) ifTrue:[
 	    text := model helpTextFor:aView at:x@y.
 	    text notNil ifTrue:[^ text].
@@ -145,12 +272,61 @@
 	 v := sv.
     ].
 
+    (v notNil and:[v respondsTo:#application]) ifTrue:[
+	(model := v application) notNil ifTrue:[
+	    (model respondsTo:#helpTextFor:at:) ifTrue:[
+		text := model helpTextFor:aView at:x@y.
+		text notNil ifTrue:[^ text].
+	    ].
+	    (model respondsTo:#helpTextFor:) ifTrue:[
+		text := model helpTextFor:aView.
+		text notNil ifTrue:[^ text].
+	    ]
+	]
+    ].
+    (v notNil and:[v respondsTo:#model]) ifTrue:[
+	(model := v model) notNil ifTrue:[
+	    (model respondsTo:#helpTextFor:at:) ifTrue:[
+		text := model helpTextFor:aView at:x@y.
+		text notNil ifTrue:[^ text].
+	    ].
+	    (model respondsTo:#helpTextFor:) ifTrue:[
+		text := model helpTextFor:aView.
+		text notNil ifTrue:[^ text].
+	    ]
+	]
+    ].
+
     (view class respondsTo:#helpText) ifTrue:[
 	text := view class helpText.
 	text notNil ifTrue:[^ text].
     ].
 
     ^ nil
+
+    "Modified: 31.8.1995 / 20:38:00 / claus"
+!
+
+initiateHelpFor:aView atX:x y:y
+    |text p|
+
+    text := self helpTextFor:aView atX:x y:y.
+
+    text notNil ifTrue:[
+	DelayTime > 0 ifTrue:[
+	    showProcess notNil ifTrue:[
+		p := showProcess. showProcess := nil.
+		p terminate.
+	    ].
+	    showProcess := [
+		    (Delay forSeconds:DelayTime) wait.
+		    showProcess := nil.
+		    self showHelp:text for:aView
+	    ] forkAt:(Processor userSchedulingPriority + 1).
+	] ifFalse:[
+	    self showHelp:text for:aView
+	]
+    ].
 !
 
 hideIfPointerLeft:aView
@@ -189,24 +365,7 @@
 	^ true
     ].
 
-    text := self helpTextFor:aView atX:x y:y.
-
-    text notNil ifTrue:[
-	DelayTime > 0 ifTrue:[
-	    showProcess notNil ifTrue:[
-		p := showProcess. showProcess := nil.
-		p terminate.
-	    ].
-	    showProcess := [
-		    (Delay forSeconds:DelayTime) wait.
-		    showProcess := nil.
-		    self showHelp:text for:aView
-	    ] forkAt:(Processor userSchedulingPriority + 1).
-	] ifFalse:[
-	    self showHelp:text for:aView
-	]
-    ].
-
+    self initiateHelpFor:aView atX:x y:y.
     ^ false
 !
 
@@ -249,7 +408,7 @@
 !
 
 showHelp:aHelpText for:view
-    |org p|
+    |org p v|
 
     view == currentView ifTrue:[^ self].
 
@@ -265,22 +424,23 @@
     currentFrame := org extent:view extent.
     org :=org + (view extent // 2).
 
-    currentHelpView := ActiveHelpView for:aHelpText withCRs.
+    v := ActiveHelpView for:aHelpText withCRs.
 
     org := view device pointerPosition.
-    org := org + (20@20).
-    (org x + currentHelpView width) > view device width ifTrue:[
-	org := (org x - currentHelpView width) @ org y
+    org := org + (10@10).
+    (org x + v width) > view device width ifTrue:[
+	org := (org x - v width) @ org y
     ].
-    (org y + currentHelpView height) > view device height ifTrue:[
-	org := org x @ (org y - currentHelpView height).
+    (org y + v height) > view device height ifTrue:[
+	org := org x @ (org y - v height).
     ].
 
-    currentHelpView origin:org.
+    v origin:org.
 "/    currentHelpView open.
-    currentHelpView realize.
-    currentHelpView enableButtonMotionEvents.
-    currentHelpView enableMotionEvents.
+    v realize.
+    v enableButtonMotionEvents.
+    v enableMotionEvents.
+    currentHelpView := v.
 
     currentView := view.
     closeProcess := [
@@ -296,6 +456,8 @@
 	    ] valueUninterruptably
 	].
     ] forkAt:(Processor userSchedulingPriority + 1).
+
+    "Modified: 31.8.1995 / 19:20:45 / claus"
 ! !
 
 ActiveHelp initialize!