eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'BlockValue':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: BlockValue


Inheritance:

   Object
   |
   +--Model
      |
      +--ValueModel
         |
         +--BlockValue
            |
            +--BooleanBlockValue

Package:
stx:libview2
Category:
Interface-Support-Models
Version:
rev: 1.42 date: 2023/07/15 18:33:51
user: cg
file: BlockValue.st directory: libview2
module: stx stc-classLibrary: libview2

Description:


BlockValues depend on one or more other objects (typically valueHolders)
and recompute a value whenever one of them changes.
If the recomputed new value is different, it triggers itself a change to its dependents.

A typical example use is to base an enableChannel's value on multiple other 
boolean (or non-boolean) values. (See example for how this is done)

Notice, that a BlockValue can also be created without depending on any other
object (i.e. BlockValue with:aBlock). In this case, a recomputation must be explicitly
triggered by sending #recomputeValue to the blockValue instance.

BlockValues cannot be used to write into an aspect; they are typically used
in GUI components to present an alternative view on some other aspect.

Notice: 
    this class was implemented using protocol information
    from alpha testers - it may not be complete or compatible to
    the corresponding ST-80 class. 
    If you encounter any incompatibilities, please forward a note 
    describing the incompatibility verbal (i.e. no code) to the ST/X team.

Warning:
    BlockValues only work ine one direction; changing the blockValue's value
    does not affect the original model's value.

copyright

COPYRIGHT (c) 1995 by Claus Gittinger All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

initialization
o  initialize
(comment from inherited method)
called only once - initialize signals

instance creation
o  block: aBlock arguments: aCollectionOfValueModels
return a new BlockValue computing aBlock whenever one of aCollectionOfValueModels changes.
Same as #with:arguments: for ST80 compatibility

o  with: aBlock
return a new BlockValue computing aBlock

o  with: aBlock argument: aValueModel
return a new BlockValue computing aBlock whenever aValueModel changes

o  with: aBlock argument: valueModel1 argument: valueModel2
return a new BlockValue computing aBlock whenever one of the value models changes

o  with: aBlock argument: valueModel1 argument: valueModel2 argument: valueModel3
return a new BlockValue computing aBlock whenever one of the value models changes

o  with: aBlock argument: valueModel1 argument: valueModel2 argument: valueModel3 argument: valueModel4
return a new BlockValue computing aBlock whenever one of the value models changes

o  with: aBlock arguments: aCollectionOfValueModels
return a new BlockValue computing aBlock whenever one of the value models changes

instance creation - useful BlockValues
o  forLogical: valueModel1 and: valueModel2
return a new BlockValue computing the logical AND of its args
(which are usually other valueHolders)

o  forLogical: valueModel1 and: valueModel2 and: valueModel3
return a new BlockValue computing the logical AND of its args
(which are usually other valueHolders)

o  forLogical: valueModel1 or: valueModel2
return a new BlockValue computing the logical OR of its args
(which are usually other valueHolders)

o  forLogical: valueModel1 or: valueModel2 or: valueModel3
return a new BlockValue computing the logical OR of its args
(which are usually other valueHolders)

o  forLogicalAndAll: arrayOfValueModels
return a new BlockValue computing the logical AND of all elements
in the passed argArray (which are usually other valueHolders)

o  forLogicalNot: aValueModel
return a new BlockValue computing the logical NOT of its arg
(which is usually another valueHolder)

Usage example(s):

        |v1 v2|

        v1 := ValueHolder new.
        v1 value:true.

        v2 := BlockValue forLogicalNot:v1.
        v2 onChangeEvaluate:[ Transcript showCR:v2 value].
        Transcript showCR:v2 value.         'shows a false already'. 

        v1 value:true.                      'no change signalled here'.
        v1 value:false.
        v1 value:true.

o  forLogicalOrAll: arrayOfValueModels
return a new BlockValue computing the logical OR of all elements
in the passed argArray (which are usually other valueHolders)

o  forTrueIfNotNil: valueModel
return a new BlockValue generating true of valueModel holds on a non-nil value,
false otherwise.

o  forValue: someValueModel equalTo: someConstant
return a new BlockValue generating a true,
if someValue (usually another holder) contains a value equal to someConstant.
Useful, if the other valueHolder is a radioButton group model,
and you want to automatically enable/disable other items based on the value
(i.e. via the enableChannel)

Usage example(s):

        |v1 v2|

        v1 := ValueHolder new.
        v1 value:'blah'.

        v2 := BlockValue forValue:v1 equalTo:'hello'.
        v2 onChangeEvaluate:[ Transcript showCR:v2 value].
        Transcript showCR:v2 value.         'shows a false already'. 

        v1 value:'blah'.                      'no change signalled here'.
        v1 value:'oops'.                      'remains false'.
        v1 value:'hello'.                     'changes to true'.
        v2 value      


Instance protocol:

accessing
o  setArguments: aCollectionOfArguments
set the receiver's arguments to be passed to it.
A change in any of the arguments will force reevaluation of the action
block - possibly generating another change from myself

o  setBlock: aBlock
set the receiver's action block

o  setBlock: aBlock argumentArray: anArgumentCollection
set the receiver's action block, and define an arguments collection
to be passed to it.
A change in any element of the collection will force reevaluation of the
action block (passing the collection as a single argument)
- possibly generating another change from myself

o  setBlock: aBlock arguments: aCollectionOfArguments
set the receiver's action block, and define arguments to be passed to it.
A change in any of the arguments will force reevaluation of the action
block - possibly generating another change from myself

o  setValue: newValue
physically set my value, without change notifications.
This is a noop here, since my value is computed.

o  value
retrieve my value - this does not always evaluate the action block,
since the returned value is cached internally

change & update
o  recomputeValue
force reevaluation of my actionBlock,
and possibly send a change notification to my dependents

o  update: something with: aParameter from: someone
the one I depend on has changed - reevaluate my actionBlock,
and possibly send a change notification to my dependents

dependents access
o  release
release any dependencies upon the arguments

misc
o  computeValue
evaluate the receiver's action block

o  dependOn: someObject
arrange for the blockValue to be reevaluated, whenever someObject
changes (i.e. sends a change notification)

o  resetValue
evaluate the receiver's action block

printing
o  displayOn: aStreamOrGC
(comment from inherited method)
Compatibility
append a printed desription on some stream (Dolphin, Squeak)
OR:
display the receiver in a graphicsContext at 0@0 (ST80).
This method allows for any object to be displayed in some view
(although the fallBack is to display its printString ...)

Notice: displayString and displayOn: are for developers, debugging and inspectors,
whereas printString and printOn: are for the program to print data.


Examples:


checkToggle 3 shows the value of toggle1 AND toggle2
    |val1 val2 both box|

    val1 := false asValue.
    val2 := false asValue.
    both := BlockValue 
                with:[:v1 :v2 | 
                        Transcript showCR:'evaluating ...'.
                        v1 value and:[v2 value]
                     ] 
                arguments:(Array with:val1 with:val2).

    box := Dialog new.
    box addCheckBox:'one' on:val1.
    box addCheckBox:'two' on:val2.
    box addHorizontalLine.
    box addCheckBox:'both' on:both.
    box addOkButton.
    box open
the same, using a convenient instance creation message:
    |val1 val2 both box|

    val1 := false asValue.
    val2 := false asValue.
    both := BlockValue forLogical:val1 and:val2.

    box := Dialog new.
    box addCheckBox:'one' on:val1.
    box addCheckBox:'two' on:val2.
    box addHorizontalLine.
    (box addCheckBox:'both' on:both) disable.
    box addOkButton.
    box open
logical or:
    |val1 val2 both box|

    val1 := false asValue.
    val2 := false asValue.
    both := BlockValue forLogical:val1 or:val2.

    box := Dialog new.
    box addCheckBox:'one' on:val1.
    box addCheckBox:'two' on:val2.
    box addHorizontalLine.
    box addCheckBox:'both' on:both.
    box addOkButton.
    box open
example use: enabling an element depending on two others:
    |val1 val2 enabler val3 box|

    val1 := false asValue.
    val2 := false asValue.
    val3 := false asValue.
    enabler := BlockValue forLogical:val1 and:val2.

    box := Dialog new.
    box addCheckBox:'one' on:val1.
    box addCheckBox:'two' on:val2.
    box addHorizontalLine.
    (box addCheckBox:'three (both of the above)' on:val3) enableChannel:enabler.
    box addOkButton.
    box open
like above, using a logical-or block:
    |val1 val2 enabler val3 box|

    val1 := false asValue.
    val2 := false asValue.
    val3 := false asValue.
    enabler := BlockValue forLogical:val1 or:val2.

    box := Dialog new.
    box addCheckBox:'one' on:val1.
    box addCheckBox:'two' on:val2.
    box addHorizontalLine.
    (box addCheckBox:'three (any of the above)' on:val3) enableChannel:enabler.
    box addOkButton.
    box open
like above, using a bunch of toggles:
    |values anyValue box|

    values := (1 to:10) collect:[:i | false asValue].
    anyValue := BlockValue forLogicalOrAll:values.
    anyValue onChangeSend:#value to:[Transcript showCR:'any is true'].

    box := Dialog new.
    values keysAndValuesDo:[:index :aValueHolder |
        box addCheckBox:index printString on:aValueHolder.
    ].
    box addHorizontalLine.
    (box addOkButton) enableChannel:anyValue.
    box open
a logical-not block:
    |val1 valNot box|

    val1 := false asValue.
    valNot := BlockValue forLogicalNot:val1.

    box := Dialog new.
    box addCheckBox:'one' on:val1.
    box addHorizontalLine.
    (box addCheckBox:'not one' on:valNot) enabled:false
    box addOkButton.
    box open


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sat, 27 Jul 2024 02:36:56 GMT