enable
enable copied to clipboard
Build a Simple Consistent Style System for Enable
Currently there is:
- not a lot of coherence between different components and the styling traits they expose
- a lot of commonality
- no easy way to apply consistent styling across a group of different components
There have been efforts towards this in the past, in older versions of Enable, but they were somewhat hampered by the lack of Traits features. At the extreme end of possibilities is something like CSS, but that seems like overkill for what Enable needs. It's probably sufficient to define a core set of style classes for things like lines, text, drawing paths, etc. and use DelegatesTo to define component values for backward compatibility.
As a sketch, something like:
def Optional(*args, **kwargs):
return Union(None, *args, **kwargs)
class AbstractStyle(ABCHasStrictTraits):
@abstractmethod
def set_style(self, gc):
raise NotImplementedError
@contextmanager
def __call__(self, gc):
with gc:
self.set_style(gc)
yield
class LineStyle(AbstractStyle):
color = Optional(black_color_trait)
width = Optional(Int)
dash = Optional(LineStyle)
cap = ...
join = ...
def set_style(self, gc)
if self.color is not None:
gc.set_stroke_color(self.color)
if self.color is not None:
gc.set_stroke_width(self.width)
... # etc
yield
class RegionStyle(AbstractStyle):
color = Optional(white_color_trait)
border = Instance(LineStyle)
def set_style(self, gc):
if self.color is not None:
gc.set_fill_color(self.color)
if self.border is not None:
self.border.set_style(gc)
class Shape(Component):
path = Instance(CompiledPath)
style = Instance(RegionStyle)
def _draw_mainlayer(self, gc, ...):
with self.style(gc):
gc.add_path(self.path)
gc.draw_path()
Consistent use of this has the possibility to significantly clean up rendering code.
You'd also want basic observation of changes + updating so using classes can trigger redraws as needed. Probably easiest to add an updated event to the ABC that can be listened for.
Thinking about this a little more, it wouldn't take much to give this some sort of cascading-type capabilities: if you added ancestor styles to the style classes with an appropriate system of managing application order (easiest would be to allow just one ancestor, so you get a tree of styles; arbitrary DAGs are harder).