zoukankan      html  css  js  c++  java
  • beamline choose


    class ::DCS::Set {

     # public methods
     public method constructor {} {}
     public method add { member }
     public method remove { member }
     public method get {}
     public method clear {}
     public method isMember { member }
     
     # private data
     private variable memberList {}
    }


    body ::DCS::Set::clear {} {

     # set the list of current members to the null set
     set memberList {}
    }


    body ::DCS::Set::isMember { member } {

     # return TRUE iff member is in the list of current members
     expr [lsearch $memberList $member] != -1
    }

    body ::DCS::Set::add { args } {

     # loop over each potential new member in the argument list
     foreach member $args {
      
      # append current member list with the new member if not in list already
      if { ! [isMember $member] } {
       lappend memberList $member
      }
     }
    }


    body ::DCS::Set::remove { args } {

     # loop over each member to be removed in argument list
     foreach member $args {
      
      # find the member in the list of current members
      set index [lsearch $memberList $member]
      
      # remove it from the list if it was found in the list of current members
      if  { $index != -1 } {
       set memberList [lreplace $memberList $index $index]
      }
     }
    }


    body ::DCS::Set::get {} {
     
     # return the list of current members
     return $memberList
    }


    ##########################################################################
    # The class Bag defines an object that contains a set of counted objects.
    # Objects may be added or removed.  The same object may be added to the Bag
    # any number of times--the Bag keeps a count.  To remove an object from a
    # Bag, the remove operation must be called as many times as the add operation
    # was called for that object.  The get method returns the list of unique
    # members and the clear method removes all objects from the set.
    ##########################################################################


    class ::DCS::Bag {
     
     # public methods
     public method constructor {} {}

     public method add { member }
     public method remove { member }
     public method get {}
     public method clear {}
     public method isMember { member }

     # private data
     private variable memberArray
    }


    body ::DCS::Bag::clear {} {

     # delete all members of the member array
     unset memberArray
    }


    body ::DCS::Bag::isMember { member } {

     # search for the member in the list of current members
     expr [lsearch [get] $member] != -1
    }


    body ::DCS::Bag::add { args } {
     
     # keep track of completely new members added
     set newMembers {}

     # loop over each potential new member in the argument list
     foreach member $args {
      
      # increment the array value for the member if it already exists
      if { [isMember $member] } {
       incr memberArray($member)
      } {
       # otherwise create the array member and initialize it to 1
       set memberArray($member) 1

       # keep track of completely new members added
       lappend newMembers $member
      }
     }

     # return the new list of unique member names
     return $newMembers
    }


    body ::DCS::Bag::remove { args } {

     # keep track of members completely removed
     set oldMembers {}

     # loop over each member to be removed in argument list
     foreach member $args {
      
      if { [isMember $member] } {
       incr memberArray($member) -1
       
       if { $memberArray($member) < 1 } {
        unset memberArray($member)

       # keep track of members completely removed
       lappend oldMembers $member    
       }
      }
     }
      
     # return the new list of unique member names
     return $oldMembers
    }


    body ::DCS::Bag::get {} {
     
     # return the null set if no members in the array
     if { ! [info exists memberArray] } {
      return {}
     } else {
      # otherwise return the list of unique member names
      return [array names memberArray]
     }
    }


    class objectMediator {

     # private data
     private variable _registrationRequests
     private variable futureRequests
     private variable unmatchedTarget
     private variable _debugOn 0

     private variable _initiatorId 1

     # public methods
     public method register { lstnr target attribute callback {alias ""} }
     public method unregister { lstnr target attribute }
     public method announceExistence { newObject }
     public method announceDestruction { destroyedObject }
     public method printStatus { }
     public method getUniqueInitiatorId {} { incr _initiatorId ; return $_initiatorId}

     # constructor
     constructor { args } {}

     # destructor
     destructor { }
    }

    ##########################################################################
    #
    # objectMediator::register
    #
    # This method is used to indicate interest in future updates of an
    # attribute of the "object".  The caller must pass the name of the
    # object to which updates should be directed.  The object of interest
    # need not exist yet.  Furthermore, the object that is registering for
    # interest must announce its existence before the registration actually
    # takes place.
    #
    body objectMediator::register {lstnr target attribute callback {alias ""} } {

     if { $alias == "" } { set alias ${target}~$attribute }

     if { $_debugOn} {puts "!!!!!!!!!!!!!!!!!!!!!!!!! lstnr: $lstnr target: $target $attribute"}

     if { ![info exists ${lstnr}(ready)] } {

      #Have not received a request from this lstnr before
      #We will assume it is not ready to handle updates yet, as it
      #may still be in its constructor.
      #The announceExistence function will set the ready flag to a 1.
      set ${lstnr}(ready) 0
      set futureRequests($lstnr) ""
     }
     

     if { [set ${lstnr}(ready)] == "0" } {
      #The lstnr isn't ready to receive updates yet.
      #puts "CCCC: $lstnr  [set ${lstnr}(ready)]"


      lappend futureRequests($lstnr) [list $target $attribute $callback $alias]
      return
     }

     set newRequest [list $lstnr $attribute $callback $alias]
     if { ! [info exist _registrationRequests($target) ] } {
      #first request for a new target
      lappend _registrationRequests($target) $newRequest
     } elseif { [lsearch $_registrationRequests($target) $newRequest] == -1 } {
      #another registration  for a target
      lappend _registrationRequests($target) $newRequest
     }
     
     if { [info command $target] != "" } {
      #the object of interest exists
      if { [info exist ${target}(ready)] } {
       if { [set ${target}(ready)] == "1" } {
        #the object is ready to receive registrations
        
        if { $_debugOn} {puts "$lstnr REGISTERING DIRECTLY WITH $target $attribute"}
        $target register $lstnr $attribute $callback $alias
        
        array unset unmatchedTarget $target
        
        return
       }
      }
     }
     
     #The object of interest isn't ready yet. Remember and
     #wait for announcement of its existence.

     # let the listener know that the object doesn't exist yet.
     $lstnr $callback $target 0 $alias "$target does not exist." ""

     #puts "$target NOT ready yet"
     lappend unmatchedTarget($target)
    }

    body objectMediator::announceExistence { object } {
     
     #The object is now ready to handle registrations and accept
     #updates from components that it has registered with.
     set ${object}(ready) 1

     #First complete all of the registrations that this
     #new object has already declared interest in.
     if { [info exists futureRequests($object)] } {
      
      if { $_debugOn} {puts "$object can register with other objects now"}

      foreach request $futureRequests($object) {
       foreach {target attribute callback alias} $request {break}
       
       register $object $target $attribute $callback $alias
      }

      #now that the object is ready, we can forget
      array unset futureRequests $object
     }

     #Now complete all registrations for objects that were
     #interested in this object before it existed.
     if { [info exists _registrationRequests($object)] } {

      foreach request $_registrationRequests($object) {
       foreach {lstnr attribute callback alias} $request {}

       register $lstnr $object $attribute $callback $alias
      }
     }
    }

    body objectMediator::announceDestruction { object } {
     
     #The object is no longer exists and the mediator should
     #delete all of its registration requests
     set ${object}(ready) 0

     #First remove all of the registrations that this
     #new object has already declared interest in.
     array unset futureRequests $object

     #Now inform all listeners that this object is destroyed
     if { [info exists _registrationRequests($object)] } {
      foreach request $_registrationRequests($object) {
       foreach {lstnr attribute callback alias} $request break

       #puts "CCCC: $lstnr $attribute $callback $alias"
       
       set temp [set ${lstnr}(ready)]

       if { $temp } {
        if { [info commands $lstnr] != "" } {
         # let the listener know that the object doesn't exist anymore.
         $lstnr $callback $object 0 $alias "$object does not exist" ""
        }
       }
      }
      unset _registrationRequests($object)
     }

     
     #Now unregister from everything that this object was interested in
     #This is the most inefficient step in unregistration.  A search
     #is need through all of the target's registrations to see if
     #this destroyed object was registered.
     foreach target [array names _registrationRequests] {
      foreach request $_registrationRequests($target) {
       foreach {lstnr attribute callback alias} $request {}
       if { $lstnr == $object } {
        #unregister this request
        #puts "CCCC:  $lstnr is unregistering in interest in $target $attribute"
        ::mediator unregister $lstnr $target $attribute
       }
      }
     }

    }

    #The listener is unregistering from interest in the target
    body objectMediator::unregister { unLstnr unTarget unAttribute } {

     if { $_debugOn} {puts "Unregistering $unLstnr $unTarget $unAttribute"}

     if { [info exists futureRequests($unLstnr)]} {
      set tmpRequests ""
      
      foreach registration $futureRequests($unLstnr) {
       foreach {target attribute callback alias} $registration {break}
       if { $target != $unTarget || $attribute != $unAttribute } {
        #this wasn't the unregistration request so we can add it back to the list.
        lappend tmpRequests [list $target $attribute $callback $alias]
       }
      }
      set futureRequests($unLstnr) $tmpRequests
     }
      
     #delete from the list of registration requests
     if { [info exists _registrationRequests($unTarget) ]} {
      #initialize a new list to hold the registration
      set tmpRequests ""
      
      #We had in fact registered with this target before.
      #Search through the registrations for this target for the one that
      #we want to get rid of.
      
      foreach registration $_registrationRequests($unTarget) {
       foreach {lstnr attribute callback alias} $registration {break}
       if { $lstnr != $unLstnr || $attribute != $unAttribute } {
        #this wasn't the unregistration request so we can add it back to the list.
        lappend tmpRequests [list $lstnr $attribute $callback $alias]
       } else {
        if {[ info command $unTarget] != ""} {
         $unTarget unregister $unLstnr $unAttribute $callback $alias
        }
       }
      }
      set _registrationRequests($unTarget) $tmpRequests
     }

    }

    body objectMediator::printStatus { } {

     puts "**********************************************"
     puts "The following objects have outstanding Future requests, but the listener isn't ready yet:"
     foreach lstnr [array name futureRequests] {
      set fullRequest $futureRequests($lstnr)
      puts "$lstnr: $fullRequest"
     }

     puts "The following objects have registration requests, and the listener is ready."
     foreach target [array name _registrationRequests] {
      set fullRequest $_registrationRequests($target)
      puts "$target: $fullRequest"
      puts ""
     }

     puts "The following targets have interested listeners, but they are not ready."
     foreach target [array name unmatchedTarget] {
      puts "$target"
     }

     puts "**********************************************"
    }


    ##########################################################################
    #
    #            Class Component
    #
    # The Component class is meant to be inherited by other classes that
    # will participate in the BLU-ICE component architecture.  Deriving a
    # class from Component makes the class a BLU-ICE component.
    #
    # Currently, the only common functionality associated with BLU-ICE components
    # is related to requesting and providing updates when attributes related
    # to a component changes.
    #
    #### Initializing the base class ###
    #
    # A child of Component must initialize the Component base class
    # by calling the base class constructor explitly.  The first argument to the
    # constructor must be a list specifying the attributes in the child class that
    # should be made available for updates to other components.  Attribute names
    # alternate with accessor functions provided for the attributes.  For example,
    # if the call to base class constructor is:
    #
    #   Component::constructor { position getPosition speed getSpeed }
    #
    # then two attributes are exported, 'position' and 'speed', and the class
    # provides the accessors 'getPosition' and 'getSpeed' for the two attributes
    # respectively.
    #
    # If an exported attribute is a public variable, then the built-in accessor
    # may be specified.  For example, if the 'position' attribute is a public
    # variable, then the base class constructor might be called as follows:
    #
    #   Component::constructor { position {cget -position} speed getSpeed }
    #
    #
    #### Registering for updates of attributes ###
    #
    # Assume that a child class of Component Motor, has been instantiated as
    # an object 'motor'.  Then an object 'lstnr' could register itself for
    # updates of motor's position attribute by issuing the command:
    #
    #   motor register lstnr position
    #
    #
    #### Handling updates of attributes ###
    #
    # Updates of attributes are sent to all registered objects by calling the
    # 'handleUpdateFromComponent' method of the registered object.  This method
    # must take three arguments, the name of the Component providing the update,
    # the name of the attribute being updated, and the new value of the attribute.
    #
    #
    #### Triggering updates of attributes ###
    #
    # Component writers must explicitly indicate when an update for a particular
    # attribute should be sent to all registered objects.  This is done by calling
    # the Component::updateRegisteredComponents function.  For example,
    #
    #   updateRegisteredComponents position
    #
    # will trigger updates of position's value to all registered objects.
    # Alternatively, the updateRegisteredComponentsAsynchronously method
    # may be used.  This function inserts a call to updateRegisteredComponents
    # into the Tcl event queue, allowing the currently active code to complete
    # before the update is actually sent.
    #
    #
    #### Unregistering ###
    #
    # A registered object may unregister by calling the 'unregister' method,
    # passing it's own name and the name of the attribute for which it registered
    # as arguments.  For example:
    #
    #    motor unregister lstnr position
    #
    ##########################################################################

    class DCS::Component {

     # private data
     private variable registeredComponentArray
     private variable accessorArray
     private variable updateScheduled
     private variable constructionComplete  0
     private variable exportedSubComponent

     protected variable _debugOn 0

     # public methods
     public method register { lstner attribute callback {alias ""}}
     public method unregister { name attribute callback {alias ""}}
     public method getUpdateNow { name callback attribute alias }
     public method updateRegisteredComponents
     public method updateRegisteredComponentsNow
     public method announceExist {}
     public method announceDestruction
     public method exportSubComponent { attribute subComponent }
     public method addAttribute

        public proc replace%sInCommandWithValue { command value } {
     set first [string first %s $command]
     if {$first == -1} {
         return $command
     }
     set mapList [list %s $value]
         set replacedStr [string map $mapList $command]

         return $replacedStr
        }

     # protected methods
     protected method sendUpdate

     #first time a Component is instantiated, an object mediator is constructed
     if { [info commands objectMediator] =="" } {objectMediator ::mediator}

     # constructor
     constructor { args } {
      set constructionComplete 0

      if { ! $constructionComplete } {
       
       # first argument is a list of exported variables and associated accessor functions
       set exportedAttributes [lindex $args 0]
       
       # create an empty set of registered objects for each served variable
       foreach {attribute accessor} $exportedAttributes {
        addAttribute $attribute $accessor
       }

       #puts [array names accessorArray]
       set constructionComplete 1
      }

     }

     # destructor
     destructor {
      
      # destroy the Set associated with each exported variable
      foreach attribute [array names registeredComponentArray] {
       delete object $registeredComponentArray($attribute)
      }

      announceDestruction
     }
    }


    body DCS::Component::announceExist {} {

     set _onlineStatus 1

     ::mediator announceExistence $this
    }


    body DCS::Component::announceDestruction {} {
     ::mediator announceDestruction $this
    }

    body DCS::Component::addAttribute { attribute_ accessor_ } {

     #return if this attribute has already been added
     if { [info exists registeredComponentArray($attribute_) ] } {
      return
     }

     # initialize a set to hold the names of the registered components for the variable
     set registeredComponentArray($attribute_) [DCS::Set \#auto]
     
     # store the name of the accessor function used to get new values of the variable
     set accessorArray($attribute_) $accessor_
     
     set updateScheduled($attribute_) 0
    }

    body DCS::Component::exportSubComponent { attribute subComponent } {
     set exportedSubComponent($attribute) $subComponent
    }

    ##########################################################################
    #
    # Component::register
    #
    # This method is used to indicate interest in future updates of an
    # attribute of this component.  The caller must pass the name of the
    # object to which updates
    #
    #
    body DCS::Component::register { lstnr attribute callback {alias ""} } {

     if { $alias == "" } { set alias ${this}~$attribute }
     
     if { $_debugOn} {puts "$lstnr is registering for interest in $this's $attribute"}

     # make sure requested attribute is exported
     if { [info exists registeredComponentArray($attribute)] } {
      # add new object lstnr to registration set for the specified attribute
      $registeredComponentArray($attribute) add [list $lstnr $callback $alias]

      # request an immediate update for the specified attribute
      getUpdateNow $lstnr $callback $attribute $alias

      #puts [array lstnrs registeredComponentArray($attribute)]
      
     } elseif {  [info exists exportedSubComponent($attribute)] } {
      if { $_debugOn} {puts "!!!!EXPORTING SUB COMPONENT: $exportedSubComponent($attribute) == $alias !!!!!!!!!!!!!!"}

      #forward the registration request down to the subcomponent
      ::mediator register $lstnr $exportedSubComponent($attribute) $attribute $callback $alias
      
     } else {
      # return failure
      return -code error "$this does not export attribute '$attribute'"
     }
    }


    body DCS::Component::unregister { lstnr attribute callback {alias ""} } {

     if { $alias == "" } { set alias ${this}~$attribute }

     if { $_debugOn} { puts "$this is unregistering $lstnr $attribute"}

     # remove name from registration set for the specified attribute
     if { [info exists registeredComponentArray($attribute)]} {
      $registeredComponentArray($attribute) remove [list $lstnr $callback $alias]
     } elseif {  [info exists exportedSubComponent($attribute)] } {
      if { $_debugOn} {puts "!!!!UNREGISTERING SUB COMPONENT:"}

      #forward the registration request down to the subcomponent
      ::mediator unregister $lstnr $exportedSubComponent($attribute) $attribute

     } else {
      # return failure
      return -code error "$this does not export attribute '$attribute'"
     }

    }


    body DCS::Component::updateRegisteredComponentsNow { attribute {initiatorId_ ""}} {

     #log_note "$this updating $attribute ($updateScheduled($attribute) requests aggregated)"
     set updateScheduled($attribute) 0

     #puts "$this looping over: [$registeredComponentArray($attribute) get]"

     # send an update to every object in the registration list
     foreach lstnr [$registeredComponentArray($attribute) get] {
      foreach {name callback alias} $lstnr {}
      sendUpdate ${name} ${callback} $attribute $alias $initiatorId_
     }
    }


    proc safeCallback { command_} {
     if [catch {eval $command_} err] {
          global errorInfo
          puts $errorInfo
     }
    }


    body DCS::Component::updateRegisteredComponents { attribute {initiatorId_ ""} } {
     
     if { [catch {
      # count the number of requests to update the attribute
      incr updateScheduled($attribute)
      
      # schedule update of registered components in event queue if this is the first request
      if { $updateScheduled($attribute) == 1 } {
       after idle [list safeCallback "$this updateRegisteredComponentsNow $attribute $initiatorId_"] 
      }
     } errorResult ] } {
      return -code error "$this does not export '$attribute'"
     }

    }

    body DCS::Component::getUpdateNow { name callback attribute alias } {

     # send an update to the requesting object
     sendUpdate $name $callback $attribute $alias
    }

    body DCS::Component::sendUpdate { name callback attribute alias {initiatorId_ ""} } {

     # get the current value of the attribute
     set tempValue [eval $this $accessorArray($attribute)]
     
     # send an update to the specified object
     $name $callback $this 1 $alias $tempValue $initiatorId_

     if { $_debugOn} {puts "$this is sending: $name $callback $this 1 $alias $tempValue"}
    }

    #This class registers for multiple components
    #and calls a member function which can be used to update a status
    #This class can be inherited by widgets that
    #need to watch the status of several components before making
    #a decision regarding state, etc.
    #This class can also be instantiated alone and then used to
    #watch the status of multiple components and update listeners
    #when an interesting event happens.
    #The member function can be overiden by a child class for handling
    #fancy logic.  The default logic is that all of the states must
    #meet the specified trigger state before setting a status
    #to "enabled"
    class DCS::ComponentGate {

     inherit ::DCS::Component

     protected variable _gateOutput 0

     protected variable _blockingValuesArray
     
     public method addInput
     public method deleteInput
     public method getOutputMessage
     public method getOutput

     #override a couple of methods
     public method sendUpdate
     public method announceExist
     public method handleNewOutput

     #array for holding text messages to accompany a input event
     protected variable _inputMessageArray
     protected variable _inputValueArray
     protected variable _inputStatusArray


     protected variable _outputMessage "undefined"
     protected variable _blockingInput ""
     protected variable _blockingValue ""

     protected variable _onlineStatus 0

     public method handleUpdateFromTarget
     protected method calculateOutput

     constructor { args }   {
      ::DCS::Component::constructor {
       gateOutput {getOutput} }
     } {

      #  if {$this == "::dataCollectionActive" } {set _debugOn 1}
      #  if {$this == "::DCS::TitledMotorEntry::.hutchTest.canvas.phi.ring.l.ring.b.c.e" } {set _debugOn 1}
      #if {$this == "::HutchTab::.hutchTest.canvas.automation.ring.b.c.optimize" } {set _debugOn 1}

      if { [namespace tail [$this info class]] == "ComponentGate" } {
       announceExist
      }

     }
     
     public method destructor
    }

    body DCS::ComponentGate::destructor {} {

     # unregister for all of the objects used as inputs
     foreach {alias} [array names _blockingValuesArray] {

      foreach {object attribute} [split $alias ~] break
      
      # unregister for interest in the target
      ::mediator unregister $this $object $attribute
     }

     announceDestruction
    }

    body DCS::ComponentGate::handleUpdateFromTarget { target targetReady alias value initiatorId_} {
     if { $_debugOn} {puts "$this $target $targetReady $alias $value ++++++++++++++++++++++++++"}

     #update the array of input values
     set _inputValueArray($alias) $value
     set _inputStatusArray($alias) $targetReady

     # Check that each input is valid before calculating the output
     foreach {attribute} [array names _blockingValuesArray] {
      
      #check if the target device exists yet
      if { $_debugOn} {puts "$this Checking $attribute status: $_inputStatusArray($attribute)"}
      if { ! $_inputStatusArray($attribute) } {

       set tempOutput "$this reports bad input ($_inputValueArray($attribute))"

       set _onlineStatus 0
       set _outputMessage $tempOutput
       set _blockingValue $tempOutput
       
       #store which was the latest trigger event
       set _blockingInput $attribute

       #this object has changed states, update the registered components
       set _gateOutput $tempOutput

       updateRegisteredComponents gateOutput

       handleNewOutput

       #get out of here without recalculating the output   
       return
      }
     }

     set _onlineStatus 1
     calculateOutput
    }

    body DCS::ComponentGate::handleNewOutput { } {
     #do nothing... virtual function to be overriden
    }

    body DCS::ComponentGate::calculateOutput { } {

     set tempOutput 0
     set _outputMessage "ready"
     set _blockingInput ""
     set _blockingValue ""

     set attributes [array names _blockingValuesArray]

     if { $attributes == ""} {
      set _gateOutput 1
      updateRegisteredComponents gateOutput
      handleNewOutput
      return
     }

     # Check that each relevant target object is in the correct state before
     foreach {attribute} $attributes {

      #remember the wanted trigger value
      set triggerState $_blockingValuesArray($attribute)
      
      if { $_debugOn} {puts "$this Check $_inputValueArray($attribute) == $triggerState ?"}
      
      if { $_inputValueArray($attribute) != $triggerState } {
       set tempOutput 0
       set _outputMessage $_inputMessageArray($attribute)
       set _blockingValue $_inputValueArray($attribute)
       set _blockingInput $attribute

       break
      } else {
       set tempOutput 1
      }
     }

     #this object has changed states, update the registered components
     set _gateOutput $tempOutput

     updateRegisteredComponents gateOutput

     handleNewOutput
    }


    body DCS::ComponentGate::addInput { triggerList } {

     # store the name of the component which can enable this button
     foreach { object attribute filterValue reason } $triggerList {

      set alias ${object}~${attribute}

      # the registration should overwrite these values
      set _inputStatusArray($alias) 0
      set _inputValueArray($alias) ""
      set _blockingValuesArray($alias) $filterValue
      set _inputMessageArray($alias) $reason
      # register for interest in the target
      ::mediator register $this $object $attribute handleUpdateFromTarget
     }
    }

    body DCS::ComponentGate::deleteInput { triggerList  } {

     # store the name of the component which can enable this button
     foreach { object attribute } $triggerList {
      ::mediator unregister $this $object $attribute 
      
      #delete the trigger value from the array
      array unset _blockingValuesArray ${object}~${attribute}
      array unset _inputMessageArray ${object}~${attribute}

     }

     calculateOutput
    }

    body DCS::ComponentGate::getOutput {} {
     return $_gateOutput
    }

    body DCS::ComponentGate::getOutputMessage {} {
     return [list $_gateOutput $_blockingInput $_blockingValue $_outputMessage]
    }


    #set up a singleton object mediator called ::mediator
    if { [info commands ::mediator] == "" } {
     #set up a list of default motors
     objectMediator mediator
    }


    #override this function for the case where an input is causing an ambiguous output
    body DCS::ComponentGate::sendUpdate { name callback attribute alias {initiatorId_ ""}} {
     
     if { $_onlineStatus } {
      DCS::Component::sendUpdate $name $callback $attribute $alias $initiatorId_
     } else {
      if { $_debugOn} {puts "$this is sending: $name $callback $this $_onlineStatus $alias $_blockingValue"}
      
      #ambigous inputs are causing the output to be undefined.
      
      # send an update to the specified object with the blockingValue instead
      $name $callback $this 0 $alias $_blockingValue $initiatorId_
     }
    }


    body DCS::ComponentGate::announceExist {} {
     #first set the default _onlineStatus value

     set _onlineStatus 1
     #then call the base class function
     DCS::Component::announceExist
    }


    class DCS::ComponentORGate {

     inherit ::DCS::ComponentGate
     protected method calculateOutput

     constructor { args }   {
      ::DCS::ComponentGate::constructor {
       gateOutput {getOutput} }
     } {
      if { [namespace tail [$this info class]] == "ComponentORGate" } {
       announceExist
      }
     }

     destructor {
      announceDestruction
     }
    }

    body DCS::ComponentORGate::calculateOutput { } {

     set tempOutput 0
     set _outputMessage "ready"
     set _blockingInput ""
     set _blockingValue ""

     # Check that each relevant target object is in the correct state before
     foreach {attribute} [array names _blockingValuesArray] {

      #remember the wanted trigger value
      set triggerState $_blockingValuesArray($attribute)
      
      if { $_debugOn} {puts "$this Check $_inputValueArray($attribute) == $triggerState ?"}
      
      if { $_inputValueArray($attribute) == $triggerState } {
       set tempOutput 0
       set _outputMessage $_inputMessageArray($attribute)
       set _blockingValue $_inputValueArray($attribute)
       set _blockingInput $attribute
       
       break
      } else {
       set tempOutput 1
      }
     }

     #this object has changed states, update the registered components
     set _gateOutput $tempOutput

     updateRegisteredComponents gateOutput
     handleNewOutput
    }

    #we cannot use itk::Widget in addInput even the object is also sub class
    #from DCS::Component.
    #the object is deleted before the container's destructor being called.
    #We do not have chance to call deleteInput.
    #This will cause error message on the console.
    #so we will create some mediator object for it.

    class DCS::ItkWigetWrapper {
        inherit DCS::Component

        private variable m_obj ""
        private variable m_att ""
        private variable m_value ""

        public method getValue { } {
     return $m_value
        }

        public method handleUpdate { name_ targetReady_ alias_ contents_ - } {
     if {!$targetReady_} return
     set m_value $contents_
     updateRegisteredComponents $m_att
        }

        constructor { object attribute } {
     DCS::Component::constructor "$attribute getValue"
        } {
     #puts "itk wrapper constructor of $this"
     set m_obj $object
     set m_att $attribute
     $m_obj register $this $m_att handleUpdate
     announceExist
        }
        destructor {
     #puts "itk wrapper destructor of $this"
        }
    }
    ####to use something as an input
    class DCS::ManualInputWrapper {
        inherit DCS::Component

        private variable m_value 0

        public method getValue { } {
     return $m_value
        }

        public method setValue { newValue } {
     set m_value $newValue
     updateRegisteredComponents value
        }

        constructor { } {
     DCS::Component::constructor "value getValue"
        } {
     announceExist
        }
        destructor {
        }
    }


    class ::DCS::TitledFrame {

     # inheritance
     inherit ::itk::Widget ::DCS::Component

     # public variables related to the entry widget
     itk_option define -labelFont labelFont LabelFont *-helvetica-bold-r-normal--12-*-*-*-*-*-*-*
     itk_option define -labelText labelText LabelText ""
     itk_option define -labelPadX labelPadx LabelPadx "10"
     itk_option define -configCommands configCommands ConfigCommands ""
     itk_option define -onAnyClick onAnyClick OnAnyClick "" {
     if {$itk_option(-onAnyClick) != ""} {

         $itk_component(configmenu) configure \
         -postcommand $itk_option(-onAnyClick)

         #bind $itk_component(ring) <Button-1> $itk_option(-onAnyClick)
         #bind $itk_component(spacer1) <Button-1> $itk_option(-onAnyClick)
         bind $itk_component(border) <Button-1> $itk_option(-onAnyClick)
         bind $itk_component(spacer2) <Button-1> $itk_option(-onAnyClick)
         bind $itk_component(user) <Button-1> $itk_option(-onAnyClick)
         bind $itk_component(label) <Button-1> $itk_option(-onAnyClick)
     }
        }

     #private methods
     private method updateLabel {}
     private variable _lastCommand ""
     
     # public methods
     public method childsite {}
     public method pushNewCommand
     public method getLastCommand

     # protected methods
     protected method updateWidget {}

     # constructor
     constructor { args } {
      # call base class constructor
      ::DCS::Component::constructor { -command getLastCommand }
     } {
      # create the frames
      itk_component add ring {
       frame $itk_interior.ring
      } { }

      itk_component add spacer1 {
       frame $itk_interior.ring.s
      } { }

      itk_component add border {
       frame $itk_interior.ring.b  -relief groove -borderwidth 2
      } { }

      itk_component add spacer2 {
       frame $itk_interior.ring.b.s 
      } { }

      itk_component add user {
       frame $itk_interior.ring.b.c
      }

      # create the label at the level of the outer hull, allowing
      # it to overwrite the grooved frame of the border component
      itk_component add label {
       menubutton $itk_component(ring).l -relief flat -cursor hand2 -justify left -padx 0 -pady 0 \
         -menu $itk_component(ring).l.menu
      } {
       rename -width -unitsWidth unitswidth UnitsWidth
       rename -foreground -labelForeground foreground Foreground
       rename -background -labelBackground background Background
       rename -disabledforeground -labelForeground foreground Foreground
      }

      itk_component add configmenu {
       menu $itk_component(label).menu -tearoff 0 -activebackground green -background blue
      } {
       keep -background -foreground
      }
      
      pack $itk_component(spacer1)
      pack $itk_component(spacer2)
      pack $itk_component(border) -expand yes -fill both
      pack $itk_component(user) -pady 2 -padx 2  -expand yes -fill both
      place $itk_component(label) -x 10
      pack $itk_component(ring) -expand yes -fill both

      raise $itk_component(label)
      eval itk_initialize $args

      announceExist
     }

    }

    configbody ::DCS::TitledFrame::configCommands {

     set count 0
     
     if {$itk_option(-configCommands) != "" } {
      
      $itk_component(configmenu) delete 0 last
      
      foreach {label command} $itk_option(-configCommands) {
       
       $itk_component(configmenu) add command -label $label -command [list $this pushNewCommand $command]
       incr count
      }
      $itk_component(label) configure -state normal
     } else {
      #The menu won't appear if there are no config commands
      $itk_component(label) configure -state disabled
     }
    }

    body ::DCS::TitledFrame::pushNewCommand { command_ } {
     
     set _lastCommand $command_
     
     updateRegisteredComponents -command
    }

    body ::DCS::TitledFrame::getLastCommand {} {
     return $_lastCommand
    }

    #
    configbody ::DCS::TitledFrame::labelFont {
     updateLabel
    }

    configbody ::DCS::TitledFrame::labelText {

     $itk_component(label) configure -text $itk_option(-labelText)
     
     updateLabel
    }

    configbody ::DCS::TitledFrame::labelPadX {

     place $itk_component(label) -x $itk_option(-labelPadX)
     
     updateLabel
    }

    #handles slightly fancy packing and placing of the label over the
    #grooved frame.
    body ::DCS::TitledFrame::updateLabel {} {

     #change the text
     $itk_component(label) configure -font $itk_option(-labelFont)
     
     #get the metrics for the font that is used
     array set fontMetrics [font metrics [$itk_component(label) cget -font]]
     
     #calculate half the height of a letter for this font
     set midpoint [expr int ($fontMetrics(-linespace) / 2)]

     #calculate how much space is needed for the label for this font.
     set textWidth [expr [font measure $itk_option(-labelFont) $itk_option(-labelText) ] +  $itk_option(-labelPadX) * 2]
     
     $itk_component(spacer1) configure -height [expr $midpoint +2] -width $textWidth
     $itk_component(spacer2) configure -height [expr $midpoint +2] -width $textWidth
    }

    body ::DCS::TitledFrame::childsite {} {
     return $itk_component(user)
    }

    class DCS::BeamlineChooser {
     inherit itk::Widget
     
     public method handleOk
     public method handleCancel
     public method wait
     public method isOk
     public method getBeamline { } { return $m_beamline }
       public method handleDoubleClick

     private method handleListSelection
     private variable m_beamline
     private variable m_ok

        private variable m_title Beaemline

     
     constructor { beamlineList {title Beamline} } {
      global env

     set m_title $title
      
      itk_component add frame {
       DCS::TitledFrame $itk_interior.label
      } {}
      
      set cs [$itk_component(frame) childsite]

      pack $cs -expand 1 -fill both
      
      itk_component add blLabel {
       label $cs.blLabel -text "Available ${m_title}s"
      } {}
     
      itk_component add blListbox {
       ::iwidgets::scrolledlistbox $cs.blListbox
      } {}

      itk_component add selectedLabel {
       label $cs.selectedLabel -text "Selected $m_title"
      } {}
     
      itk_component add selectedEntry {
       label $cs.selectedEntry -text "" -bg gray -relief sunken -justify left
      } {}

      set buttonFrame [frame $cs.bf]

      itk_component add ok {
       button $buttonFrame.ok -text "Ok" -state normal -command "$this handleOk"
      } {}
      
      itk_component add cancel {
       button $buttonFrame.cancel -text "Cancel" -state normal -command "$this handleCancel"
      } {}

      grid $itk_component(frame) -row 0 -column 0 -sticky news

      grid $itk_component(blLabel) -row 0 -columnspan 2 -sticky w
      grid $itk_component(blListbox) -row 1 -columnspan 2 -sticky news
      grid $itk_component(selectedLabel) -row 2 -columnspan 2 -stick w
      grid $itk_component(selectedEntry) -row 3 -columnspan 2 -sticky news

      grid $buttonFrame -row 4 -column 0 -columnspan 2

      grid $itk_component(ok) -row 0 -column 0 -sticky e
      grid $itk_component(cancel) -row 0 -column 1 -sticky w

      #insert the beamlines into list box
      foreach {item} $beamlineList {
       $itk_component(blListbox) insert 0 $item
      }  
      
      # Set handler for list box selection
      $itk_component(blListbox) config -selectioncommand [::itcl::code $this handleListSelection]
      $itk_component(blListbox) config -dblclickcommand [::itcl::code $this handleDoubleClick]
      $itk_component(blListbox) sort ascending
      
      $itk_component(blListbox) selection set 1 1
      handleListSelection
     }

     destructor {

     }
    }


    ###################################################################
    #
    # Handle Ok button
    #
    ###################################################################
    body DCS::BeamlineChooser::handleOk {} {
     global _beamlineDialogWait
     
     set m_beamline [$itk_component(selectedEntry) cget -text]
     
     set _beamlineDialogWait 1
     set m_ok 1

     pack forget $itk_interior
    }

    ###################################################################
    #
    # Handle Cancel button
    #
    ###################################################################
    body DCS::BeamlineChooser::handleCancel {} {
     global _beamlineDialogWait
     
     set m_beamline ""
     set _beamlineDialogWait 0
     set m_ok 0
     
     pack forget $itk_interior

    }

    ###################################################################
    #
    # Handle list selection
    #
    ###################################################################
    body DCS::BeamlineChooser::handleListSelection {} {

     set selectedIndex [$itk_component(blListbox) curselection]
     $itk_component(selectedEntry) config -text [$itk_component(blListbox) get $selectedIndex]
    }

    body DCS::BeamlineChooser::handleDoubleClick {} {
     handleListSelection
       handleOk
    }

    body DCS::BeamlineChooser::isOk { } {

     return $m_ok
     
    }

    body DCS::BeamlineChooser::wait {} {

     global _beamlineDialogWait

     tkwait variable _beamlineDialogWait
    }


    set beamlines {bl1 bl2 bl3 bl4};
    set title bl3
    ### From here we will pack the beamline chooser
    set beamlineDialog [DCS::BeamlineChooser .beamlineDialog $beamlines $title]
    # Open login dialog
    pack .beamlineDialog

  • 相关阅读:
    Android Wear(手表)开发
    Android 中文件类型与MIME的匹配表
    匹配字符串-好技能-正则表达式
    正则表达式匹配字符串
    如何开发Android Wear应用程序
    【转】 hive安装配置及遇到的问题解决
    Hadoop项目开发环境搭建(EclipseMyEclipse + Maven)
    MapReduce 开发环境搭建(EclipseMyEclipse + Maven)
    hive权威安装出现的不解错误!(完美解决)两种方法都可以
    Hive项目开发环境搭建(EclipseMyEclipse + Maven)
  • 原文地址:https://www.cnblogs.com/greencolor/p/2050551.html
Copyright © 2011-2022 走看看