def _context_changed ( self, old, new ):
        """ Handles the underlying context being changed.
        """
        self._context_base = None

        cm = ContextModified( reset = True )
        dm = TraitDictEvent()

        if old is not None:
            cm.removed = [ item.name for item in old.context_items ]
            old.on_trait_change( self._context_is_modified, 'context_modified',
                                 remove = True )

            dm.removed = dict( old )
            old.on_trait_change( self._dict_is_modified, 'dict_modified',
                                 remove = True )

        if new is not None:
            cm.added = [ item.name for item in new.context_items ]
            new.on_trait_change( self._context_is_modified, 'context_modified' )

            dm.added = dict( new )
            new.on_trait_change( self._dict_is_modified, 'dict_modified' )

        self._context_is_modified( cm )
        self._dict_is_modified( dm )
    def _context_changed(self, old, new):
        """ Handles the underlying context being changed.
        """
        self._context_base = None

        cm = ContextModified(reset=True)
        dm = TraitDictEvent()

        if old is not None:
            cm.removed = [item.name for item in old.context_items]
            old.on_trait_change(self._context_is_modified,
                                'context_modified',
                                remove=True)

            dm.removed = dict(old)
            old.on_trait_change(self._dict_is_modified,
                                'dict_modified',
                                remove=True)

        if new is not None:
            cm.added = [item.name for item in new.context_items]
            new.on_trait_change(self._context_is_modified, 'context_modified')

            dm.added = dict(new)
            new.on_trait_change(self._dict_is_modified, 'dict_modified')

        self._context_is_modified(cm)
        self._dict_is_modified(dm)
Example #3
0
 def _context_items_changed ( self, old, new ):
     """ Handles the 'items' trait being changed.
     """
     self.post_context_modified( ContextModified(
         removed = self._remove_context_items( *old ),
         added   = self._add_context_items( *new ),
     ) )
Example #4
0
 def _set_name ( self, name ):
     old = self.name
     if name != old:
         self._name = name
         if self.context is not None:
             self.post_context_modified(
                 ContextModified( removed = [ old ], added = [ name ] )
             )
Example #5
0
 def _evaluate_changed(self, evaluate):
     """ Handles the 'evaluate' trait being changed.
     """
     self._block = ExpressionBlock.from_string(evaluate)
     self._inputs = dict.fromkeys(self._block.inputs)
     self._data = None
     if self.context is not None:
         self.context.post_context_modified(
             ContextModified(modified=[self.name]))
Example #6
0
 def _context_modified_changed_for_context(self, event):
     """ Handles the data associated with this item being changed.
     """
     inputs = self._inputs
     if inputs is not None:
         for name in event.all_modified:
             if name in inputs:
                 self._data = None
                 self.context.post_context_modified(
                     ContextModified(modified=[self.name]))
                 break
Example #7
0
    def _set_context_group ( self, group ):
        if self.is_valid_array( group ):
            group = group.shape

        if (group is not None) and (group not in self._context_groups):
            raise TraitError, "There is no group for '%s'" % group

        old = self._context_group
        if group != old:
            self._context_group = group
            self.post_context_modified( ContextModified( reset = True ) )
            self.trait_property_changed( 'context_group', old, group )
Example #8
0
    def context_group_for ( self, name = None, names = None ):
        """ Gets/Sets the contents of a specified context group.
        """
        # If an array was specified as the group name, use its shape as the
        # name:
        if name is None:
            name = self.context_group
        elif self.is_valid_array( name ):
            name = name.shape

        # If this is just a query:
        if names is None:
            # Return the list of items in the specified group:
            return self._context_groups.get( name, empty_group )[1][:]

        # Only allow changing groups whose name is a string (not a shape):
        if not isinstance( name, basestring ):
            raise NumericContextError( "Can only modify a group with a string "
                      "name, but '%s' was specified." % ( name, ) )

        # Delete the old contents of the group (if any):
        old_group = self._context_groups.get( name, empty_group )
        for cur_name in old_group[1]:
            self._context_items[ cur_name ].groups.remove( name )

        if len( names ) == 0:
            # If empty list of names, delete the group (if any):
            self._context_groups.pop( name, None )

            # If the current group was just deleted, reset it:
            if name == self.context_group:
                self.context_group = None
        else:
            # Otherwise, verify all items have the same shape:
            shape = None
            for cur_name in names:
                if shape is None:
                    shape = self[ cur_name ].shape
                elif shape != self[ cur_name ].shape:
                    raise NumericContextError( 'All items in a group must have '
                                               'the same shape.' )

            # Define the group:
            self._context_groups[ name ] = ( shape, names[:] )

            # Add the group name to the list of groups each item is in:
            for cur_name in names:
                self._context_items[ cur_name ].groups.append( name )

            # If the current group was just modified, reset the context:
            if name == self.context_group:
                self.post_context_modified( ContextModified( reset = True ) )
Example #9
0
    def _propagate_context_modified(self):
        """ Propagate the pending event.
        """
        self._process_context_modified_event(
            ContextModified(reset=self._context_reset,
                            modified=self._context_modified.keys(),
                            added=self._context_added.keys(),
                            removed=self._context_removed.keys()))

        self._context_reset = False
        self._context_modified = {}
        self._context_added = {}
        self._context_removed = {}
Example #10
0
    def _sub_context_modified ( self, sub_context, name, old, event ):
        """ Handles a sub-context being modified.
        """
        ci = self._context_items

        # Create the context modified event wewill use for all changes:
        cm = ContextModified()

        # Iterate over each name the sub-context has been bound to in our
        # context:
        for name in self._sub_contexts[ sub_context ]:
            # Compute the common prefix for all sub-context items under the
            # current name:
            prefix = name + '.'

            # Create the list of modified name within our context:
            modified = [ (prefix + n) for n in event.modified ]

            # If the sub-context was reset, add all of the items in the
            # sub-context's current group to the modified list (avoiding dups):
            if event.reset:
                for n in sub_context.context_names:
                    n2 = prefix + n
                    if n2 not in modified:
                        modified.append( n2 )

            # Add all modified items to the event:
            cm.modified.extend( modified )

            # Add and remove all of the added and removed sub-context items
            # to our context and the event using the 'extended' name for our
            # context:
            cm.removed.extend( self._remove_context_items( *[
                ci[ prefix + n ] for n in event.removed
            ] ) )
            cm.added.extend( self._add_context_items( *[
                SubContextItem( context          = self,
                                sub_context_name = name,
                                sub_name         = n ) for n in event.added
            ] ) )

        # Finally, post the event:
        self.post_context_modified( cm )
    def _defer_events_changed(self):

        # 'defer_events' is a Property, so we don't get an 'old' for free
        assert ((self._deferred_dict_modified is
                 None) == (self._deferred_context_modified is None))
        old = self._deferred_dict_modified is not None
        new = self.defer_events

        # If 'defer_events' changed, make the transition
        if old != new:
            if self.defer_events:
                self._deferred_dict_modified = TraitDictEvent()
                self._deferred_context_modified = ContextModified()
            else:
                dm = self._deferred_dict_modified
                cm = self._deferred_context_modified
                self._deferred_dict_modified = None
                self._deferred_context_modified = None
                self.post_dict_modified(dm)
                self.post_context_modified(cm)
Example #12
0
 def _data_updated ( self, object, name, old, new ):
     """ Handles the data associated with this item being changed.
     """
     self.post_context_modified( ContextModified( modified = [ self.name ] ))
Example #13
0
 def _updated_changed_for_context_filter ( self ):
     if self._cur_mask is not Undefined:
         self._cur_mask = Undefined
         self.post_context_modified( ContextModified( reset = True ) )
Example #14
0
 def _context_items_items_changed ( self, event ):
     if not self._no_update:
         self.post_context_modified( ContextModified(
             removed = self._remove_context_items( *event.removed ),
             added   = self._add_context_items( *event.added ),
         ) )
Example #15
0
    def _dict_is_modified( self, event ):
        """ Fires when 'context_data' fires 'dict_modified'.
        """
        assert disjoint( event.added, event.changed, event.removed )

        # How much can we optimize this while keeping it maintainable?

        # If the dictionary has changed, then we are dirty. (I think this is
        # the only place we have to do this...)
        self.dirty = True

        # These become attributes on a ContextModified event we create below.
        # Leave them as normal sets until the end to avoid excessive trait
        # validation.
        added    = set()
        modified = set()
        removed  = set()
        changed  = set()

        # The following three loops duplicate code: the body of 'changed' is
        # simply the body of 'removed' followed by the body of 'added',
        # followed by some logic for group maintenance. It would be better to
        # abstract out the two shared chunks, but I keep waiting for a higher
        # level insight that will greatly simplify this logic and eliminate the
        # need to repeat code in the first place.

        for name, new in event.added.iteritems():

            # Rebind renamed dynamic bindings
            if hashable( new ) and new in self._dynamic_bindings:
                self._rebind_dynamic( new, name )

            # Add new data
            if self.is_valid_array( new ):
                added.update(
                    self._add_context_items( ContextItem( name = name ) )
                )
            elif isinstance( new, ANumericContext ):
                added.update( self._add_sub_context( name, new ) )
                changed.add( name )
            else:
                changed.add( name )

        for name, old in event.changed.iteritems():
            new = self.context_data[ name ]

            # Short-circuit if possible
            if new is old:
                continue

            # Unbind dynamic bindings
            if hashable( old ) and old in self._dynamic_bindings:
                d = self._dynamic_bindings[ old ]
                self._unbind_dynamic( old, d['trait_name'], remove=False )

            # Remove old data
            if name in self._context_items:
                removed.update(
                    self._remove_context_items( self._context_items[ name ],
                                                delete = False )
                )
            elif isinstance( old, ANumericContext ):
                removed.update( self._remove_sub_context( name, old ) )
                changed.add( name )
            else:
                changed.add( name )

            # Rebind dynamic bindings
            if hashable( new ) and new in self._dynamic_bindings:
                self._rebind_dynamic( new, name )

            # Add new data
            if self.is_valid_array( new ):
                added.update(
                    self._add_context_items( ContextItem( name = name ) )
                )
            elif isinstance( new, ANumericContext ):
                added.update( self._add_sub_context( name, new ) )
                changed.add( name )
            else:
                changed.add( name )

            # Update an item's group if it changes shape
            if ( self.is_valid_array( new ) and self.is_valid_array( old ) and
                    new.shape != old.shape ):

                context_groups = self._context_groups
                item           = self._context_items[ name ]

                for group in item.groups:
                    n, names = context_groups[ group ]
                    names.remove( name )
                    if len( names ) == 0:
                        del context_groups[ group ]

                group       = new.shape
                item.groups = [ group ]
                context_groups.setdefault(
                    group, ( group, [] ) )[1].append( name )

        for name, old in event.removed.iteritems():

            # Unbind dynamic bindings
            if hashable( old ) and old in self._dynamic_bindings:
                d = self._dynamic_bindings[ old ]
                self._unbind_dynamic( old, d['trait_name'], remove=False )

            # Remove old data
            if name in self._context_items:
                removed.update(
                    self._remove_context_items( self._context_items[ name ],
                                                delete = False )
                )
            elif isinstance( old, ANumericContext ):
                removed.update( self._remove_sub_context( name, old ) )
                changed.add( name )
            else:
                changed.add( name )

        # Calculate context event
        modified |= added & removed
        added    -= modified
        removed  -= modified
        cm = ContextModified(
            added    = list( added ),
            modified = list( modified ),
            removed  = list( removed ),
            changed  = list( changed ),
        )

        # Fire events
        self.post_dict_modified( event )
        self.post_context_modified( cm )
Example #16
0
 def _set_data(self, value):
     self.context.context_data[self.name] = value
     # ('self.context' might have just removed us)
     if self.context is not None:
         self.context.post_context_modified(
             ContextModified(modified=[self.name]))