<s> """<STR_LIT>""" <EOL> from collections import defaultdict <EOL> from atom . api import Atom , Unicode , Typed , observe <EOL> from enaml . application import Application , deferred_call <EOL> from enaml . core . declarative import Declarative , d_ <EOL> class Setter ( Declarative ) : <EOL> """<STR_LIT>""" <EOL> field = d_ ( Unicode ( ) ) <EOL> value = d_ ( Unicode ( ) ) <EOL> def destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> super ( Setter , self ) . destroy ( ) <EOL> StyleCache . _setter_destroyed ( self ) <EOL> @ observe ( '<STR_LIT>' , '<STR_LIT:value>' ) <EOL> def _invalidate_cache ( self , change ) : <EOL> if change [ '<STR_LIT:type>' ] == '<STR_LIT>' : <EOL> StyleCache . _setter_invalidated ( self ) <EOL> _MAX_CACHE = <NUM_LIT> <EOL> _SPLIT_CACHE = { } <EOL> def _comma_split ( text ) : <EOL> cache = _SPLIT_CACHE <EOL> if text in cache : <EOL> return cache [ text ] <EOL> if len ( cache ) >= _MAX_CACHE : <EOL> cache . clear ( ) <EOL> result = tuple ( s . strip ( ) for s in text . split ( u'<STR_LIT:U+002C>' ) if s ) <EOL> cache [ text ] = result <EOL> return result <EOL> class Style ( Declarative ) : <EOL> """<STR_LIT>""" <EOL> element = d_ ( Unicode ( ) ) <EOL> style_class = d_ ( Unicode ( ) ) <EOL> object_name = d_ ( Unicode ( ) ) <EOL> pseudo_class = d_ ( Unicode ( ) ) <EOL> pseudo_element = d_ ( Unicode ( ) ) <EOL> def setters ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ c for c in self . children if isinstance ( c , Setter ) ] <EOL> def match ( self , item ) : <EOL> """<STR_LIT>""" <EOL> specificity = <NUM_LIT:0> <EOL> if self . object_name : <EOL> item_name = item . name <EOL> if item_name and item_name in _comma_split ( self . object_name ) : <EOL> specificity += <NUM_LIT> <EOL> else : <EOL> return - <NUM_LIT:1> <EOL> if self . style_class : <EOL> item_class = item . style_class <EOL> if item_class : <EOL> count = <NUM_LIT:0> <EOL> style_classes = _comma_split ( self . style_class ) <EOL> for item_class in item_class . split ( ) : <EOL> if item_class in style_classes : <EOL> count += <NUM_LIT:1> <EOL> if count > <NUM_LIT:0> : <EOL> specificity += <NUM_LIT> * count <EOL> else : <EOL> return - <NUM_LIT:1> <EOL> else : <EOL> return - <NUM_LIT:1> <EOL> if self . element : <EOL> elements = _comma_split ( self . element ) <EOL> for t in type ( item ) . __mro__ : <EOL> if t . __name__ in elements : <EOL> specificity += <NUM_LIT> <EOL> break <EOL> else : <EOL> return - <NUM_LIT:1> <EOL> return specificity <EOL> def destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> super ( Style , self ) . destroy ( ) <EOL> StyleCache . _style_destroyed ( self ) <EOL> def child_added ( self , child ) : <EOL> """<STR_LIT>""" <EOL> super ( Style , self ) . child_added ( child ) <EOL> if self . is_initialized and isinstance ( child , Setter ) : <EOL> StyleCache . _style_setters_changed ( self ) <EOL> def child_removed ( self , child ) : <EOL> """<STR_LIT>""" <EOL> super ( Style , self ) . child_removed ( child ) <EOL> if self . is_initialized and isinstance ( child , Setter ) : <EOL> StyleCache . _style_setters_changed ( self ) <EOL> @ observe ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:object_name>' ) <EOL> def _invalidate_match_cache ( self , change ) : <EOL> if change [ '<STR_LIT:type>' ] == '<STR_LIT>' : <EOL> StyleCache . _style_match_invalidated ( self ) <EOL> @ observe ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def _invalidate_pseudo_cache ( self , change ) : <EOL> if change [ '<STR_LIT:type>' ] == '<STR_LIT>' : <EOL> StyleCache . _style_pseudo_invalidated ( self ) <EOL> class StyleSheet ( Declarative ) : <EOL> """<STR_LIT>""" <EOL> def destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> super ( StyleSheet , self ) . destroy ( ) <EOL> StyleCache . _style_sheet_destroyed ( self ) <EOL> def styles ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ c for c in self . children if isinstance ( c , Style ) ] <EOL> def child_added ( self , child ) : <EOL> """<STR_LIT>""" <EOL> super ( StyleSheet , self ) . child_added ( child ) <EOL> if self . is_initialized and isinstance ( child , Style ) : <EOL> StyleCache . _style_sheet_styles_changed ( self ) <EOL> def child_removed ( self , child ) : <EOL> """<STR_LIT>""" <EOL> super ( StyleSheet , self ) . child_removed ( child ) <EOL> if self . is_initialized and isinstance ( child , Style ) : <EOL> StyleCache . _style_sheet_styles_changed ( self ) <EOL> class Stylable ( Declarative ) : <EOL> """<STR_LIT>""" <EOL> style_class = d_ ( Unicode ( ) ) <EOL> def destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> super ( Stylable , self ) . destroy ( ) <EOL> StyleCache . _item_destroyed ( self ) <EOL> def style_sheet ( self ) : <EOL> """<STR_LIT>""" <EOL> for child in reversed ( self . children ) : <EOL> if isinstance ( child , StyleSheet ) : <EOL> return child <EOL> def restyle ( self ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def parent_changed ( self , old , new ) : <EOL> """<STR_LIT>""" <EOL> super ( Stylable , self ) . parent_changed ( old , new ) <EOL> if self . is_initialized : <EOL> StyleCache . _item_parent_changed ( self ) <EOL> def child_added ( self , child ) : <EOL> """<STR_LIT>""" <EOL> super ( Stylable , self ) . child_added ( child ) <EOL> if self . is_initialized and isinstance ( child , StyleSheet ) : <EOL> StyleCache . _item_style_sheet_changed ( self ) <EOL> def child_removed ( self , child ) : <EOL> """<STR_LIT>""" <EOL> super ( Stylable , self ) . child_removed ( child ) <EOL> if self . is_initialized and isinstance ( child , StyleSheet ) : <EOL> StyleCache . _item_style_sheet_changed ( self ) <EOL> @ observe ( '<STR_LIT>' ) <EOL> def _invalidate_style_class ( self , change ) : <EOL> if change [ '<STR_LIT:type>' ] == '<STR_LIT>' : <EOL> StyleCache . _item_style_class_invalidated ( self ) <EOL> class _RestyleTask ( Atom ) : <EOL> dirty = Typed ( set , ( ) ) <EOL> def __call__ ( self ) : <EOL> StyleCache . _restyle_task = None <EOL> for item in self . dirty : <EOL> item . restyle ( ) <EOL> def _app_style_sheet ( ) : <EOL> app = Application . instance ( ) <EOL> if app is not None : <EOL> sheet = app . style_sheet <EOL> if sheet is not None and not sheet . is_initialized : <EOL> sheet . initialize ( ) <EOL> return sheet <EOL> class StyleCache ( object ) : <EOL> """<STR_LIT>""" <EOL> _item_style_sheets = { } <EOL> _item_styles = { } <EOL> _style_sheet_items = defaultdict ( set ) <EOL> _style_items = defaultdict ( set ) <EOL> _queried_items = set ( ) <EOL> _toolkit_setters = { } <EOL> _restyle_task = None <EOL> @ classmethod <EOL> def style_sheets ( cls , item ) : <EOL> """<STR_LIT>""" <EOL> cache = cls . _item_style_sheets <EOL> if item in cache : <EOL> return cache [ item ] <EOL> sheets = [ ] <EOL> parent = item . parent <EOL> if parent is not None : <EOL> sheets . extend ( cls . style_sheets ( parent ) ) <EOL> else : <EOL> app_sheet = _app_style_sheet ( ) <EOL> if app_sheet is not None : <EOL> sheets . append ( app_sheet ) <EOL> if isinstance ( item , Stylable ) : <EOL> sheet = item . style_sheet ( ) <EOL> if sheet is not None : <EOL> sheets . append ( sheet ) <EOL> sheet_items = cls . _style_sheet_items <EOL> for sheet in sheets : <EOL> sheet_items [ sheet ] . add ( item ) <EOL> sheets = cache [ item ] = tuple ( sheets ) <EOL> cls . _queried_items . add ( item ) <EOL> return sheets <EOL> @ classmethod <EOL> def styles ( cls , item ) : <EOL> """<STR_LIT>""" <EOL> cache = cls . _item_styles <EOL> if item in cache : <EOL> return cache [ item ] <EOL> styles = [ ] <EOL> for sheet in cls . style_sheets ( item ) : <EOL> matches = [ ] <EOL> for style in sheet . styles ( ) : <EOL> specificity = style . match ( item ) <EOL> if specificity >= <NUM_LIT:0> : <EOL> matches . append ( ( specificity , len ( matches ) , style ) ) <EOL> if matches : <EOL> matches . sort ( ) <EOL> styles . extend ( style for _1 , _2 , style in matches ) <EOL> style_items = cls . _style_items <EOL> for style in styles : <EOL> style_items [ style ] . add ( item ) <EOL> styles = cache [ item ] = tuple ( styles ) <EOL> return styles <EOL> @ classmethod <EOL> def toolkit_setter ( cls , setter , translate ) : <EOL> """<STR_LIT>""" <EOL> cache = cls . _toolkit_setters <EOL> if setter in cache : <EOL> return cache [ setter ] <EOL> result = cache [ setter ] = translate ( setter ) <EOL> return result <EOL> @ classmethod <EOL> def _setter_destroyed ( cls , setter ) : <EOL> cls . _toolkit_setters . pop ( setter , None ) <EOL> @ classmethod <EOL> def _style_destroyed ( cls , style ) : <EOL> cls . _style_items . pop ( style , None ) <EOL> @ classmethod <EOL> def _style_sheet_destroyed ( cls , sheet ) : <EOL> cls . _style_sheet_items . pop ( sheet , None ) <EOL> @ classmethod <EOL> def _item_destroyed ( cls , item ) : <EOL> cls . _queried_items . discard ( item ) <EOL> sheets = cls . _item_style_sheets . pop ( item , None ) <EOL> if sheets is not None : <EOL> sheet_items = cls . _style_sheet_items <EOL> for sheet in sheets : <EOL> if sheet in sheet_items : <EOL> sheet_items [ sheet ] . discard ( item ) <EOL> styles = cls . _item_styles . pop ( item , None ) <EOL> if styles is not None : <EOL> style_items = cls . _style_items <EOL> for style in styles : <EOL> if style in style_items : <EOL> style_items [ style ] . discard ( item ) <EOL> @ classmethod <EOL> def _setter_invalidated ( cls , setter ) : <EOL> cls . _toolkit_setters . pop ( setter , None ) <EOL> items = cls . _style_items . get ( setter . parent ) <EOL> if items is not None : <EOL> cls . _request_restyle ( items ) <EOL> @ classmethod <EOL> def _style_match_invalidated ( cls , style ) : <EOL> cls . _style_items . pop ( style , None ) <EOL> items = cls . _style_sheet_items . get ( style . parent ) <EOL> if items is not None : <EOL> cache = cls . _item_styles <EOL> for item in items : <EOL> cache . pop ( item , None ) <EOL> cls . _request_restyle ( items ) <EOL> @ classmethod <EOL> def _style_pseudo_invalidated ( cls , style ) : <EOL> items = cls . _style_items . get ( style ) <EOL> if items is not None : <EOL> cls . _request_restyle ( items ) <EOL> @ classmethod <EOL> def _item_style_class_invalidated ( cls , item ) : <EOL> styles = cls . _item_styles . pop ( item , None ) <EOL> if styles is not None : <EOL> style_items = cls . _style_items <EOL> for style in styles : <EOL> if style in style_items : <EOL> style_items [ style ] . discard ( item ) <EOL> cls . _request_restyle ( ( item , ) ) <EOL> @ classmethod <EOL> def _style_setters_changed ( cls , style ) : <EOL> items = cls . _style_items . get ( style ) <EOL> if items is not None : <EOL> cls . _request_restyle ( items ) <EOL> @ classmethod <EOL> def _style_sheet_styles_changed ( cls , sheet ) : <EOL> items = cls . _style_sheet_items . get ( sheet , None ) <EOL> if items is not None : <EOL> styles = cls . _item_styles <EOL> for item in items : <EOL> styles . pop ( item , None ) <EOL> cls . _request_restyle ( items ) <EOL> @ classmethod <EOL> def _item_parent_changed ( cls , item ) : <EOL> cls . _item_style_sheet_changed ( item ) <EOL> @ classmethod <EOL> def _item_style_sheet_changed ( cls , item ) : <EOL> item_styles = cls . _item_styles <EOL> item_sheets = cls . _item_style_sheets <EOL> items = [ i for i in item . traverse ( ) if i in cls . _queried_items ] <EOL> for item in items : <EOL> sheets = item_sheets . pop ( item , None ) <EOL> if sheets is not None : <EOL> sheet_items = cls . _style_sheet_items <EOL> for sheet in sheets : <EOL> if sheet in sheet_items : <EOL> sheet_items [ sheet ] . discard ( item ) <EOL> styles = item_styles . pop ( item , None ) <EOL> if styles is not None : <EOL> style_items = cls . _style_items <EOL> for style in styles : <EOL> if style in style_items : <EOL> style_items [ style ] . discard ( item ) <EOL> cls . _request_restyle ( items ) <EOL> @ classmethod <EOL> def _app_sheet_changed ( cls ) : <EOL> if cls . _queried_items : <EOL> cls . _item_style_sheets . clear ( ) <EOL> cls . _item_styles . clear ( ) <EOL> cls . _style_sheet_items . clear ( ) <EOL> cls . _style_items . clear ( ) <EOL> cls . _request_restyle ( cls . _queried_items ) <EOL> def __new__ ( cls , * args , ** kwargs ) : <EOL> raise TypeError ( '<STR_LIT>' ) <EOL> @ classmethod <EOL> def _request_restyle ( cls , items ) : <EOL> task = cls . _restyle_task <EOL> if task is None : <EOL> task = cls . _restyle_task = _RestyleTask ( ) <EOL> deferred_call ( task ) <EOL> task . dirty . update ( items ) </s>
