Skip to content

Commit

Permalink
Refactor _format module
Browse files Browse the repository at this point in the history
- Rename classes
- Make passing of ui properties to formatter more explicit and pass
  widget to formatter separately to properties map
- Expand one character variables
- mypy fixes
  • Loading branch information
GDYendell committed Jul 5, 2023
1 parent 12d5c18 commit e61c53e
Show file tree
Hide file tree
Showing 8 changed files with 792 additions and 519 deletions.
23 changes: 15 additions & 8 deletions src/pvi/_format/adl.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
from __future__ import annotations

import re
from typing import List
from typing import List, Optional

from pvi._format.utils import Bounds, split_with_sep
from pvi._format.widget import WidgetFactory, WidgetTemplate
from pvi._format.widget import UITemplate, WidgetFormatter
from pvi.device import WidgetType


class AdlTemplate(WidgetTemplate[str]):
class AdlTemplate(UITemplate[str]):
def __init__(self, text: str):
assert "children {" not in text, "Can't do groups"
widgets = split_with_sep(text, "\n}\n")
self.screen = "".join(widgets[:3])
self.widgets = widgets[3:]

def set(self, t: str, bounds: Bounds = None, **properties) -> str:
def set(
self,
template: str,
bounds: Optional[Bounds] = None,
widget: Optional[WidgetType] = None,
**properties,
) -> str:
if bounds:
properties["x"] = bounds.x
properties["y"] = bounds.y
properties["width"] = bounds.w
properties["height"] = bounds.h
for item, value in properties.items():
if t.startswith('"related display"'):
if template.startswith('"related display"'):
value = f"{value}.adl" # Must include file extension
# Only need single line
pattern = re.compile(r"^(\s*%s)=.*$" % item, re.MULTILINE)
if isinstance(value, str):
value = f'"{value}"'
t, n = pattern.subn(r"\g<1>=" + str(value), t)
template, n = pattern.subn(r"\g<1>=" + str(value), template)
assert n == 1, f"No replacements made for {item}"
return t
return template

def search(self, search: str) -> str:
matches = [t for t in self.widgets if re.search(search, t)]
Expand All @@ -39,7 +46,7 @@ def search(self, search: str) -> str:
def create_group(
self,
group_object: List[str],
children: List[WidgetFactory[str]],
children: List[WidgetFormatter[str]],
padding: Bounds = Bounds(),
) -> List[str]:

Expand Down
160 changes: 108 additions & 52 deletions src/pvi/_format/aps.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
from typing_extensions import Annotated

from pvi._format.adl import AdlTemplate
from pvi._format.screen import LayoutProperties, Screen, ScreenWidgets
from pvi._format.screen import (
ScreenFormatterFactory,
ScreenLayout,
ScreenWidgetFormatter,
)
from pvi._format.widget import (
ActionFactory,
GroupFactory,
LabelFactory,
PVWidgetFactory,
SubScreenFactory,
WidgetFactory,
ActionWidgetFormatter,
GroupWidgetFormatter,
GroupWidgetFormatterFactory,
LabelWidgetFormatter,
PVWidgetFormatter,
SubScreenWidgetFormatter,
WidgetFormatter,
WidgetFormatterFactory,
)
from pvi._schema_utils import desc
from pvi.device import Device
Expand All @@ -33,7 +39,7 @@ class APSFormatter(Formatter):
def format(self, device: Device, prefix: str, path: Path):
assert path.suffix == ".adl", "Can only write adl files"
template = AdlTemplate((Path(__file__).parent / "aps.adl").read_text())
layout = LayoutProperties(
layout = ScreenLayout(
spacing=self.spacing,
title_height=self.title_height,
max_height=self.max_height,
Expand All @@ -44,95 +50,145 @@ def format(self, device: Device, prefix: str, path: Path):
group_widget_indent=0,
group_width_offset=0,
)
screen_widgets = ScreenWidgets(
heading_cls=LabelFactory.from_template(
template, search='"Heading"', textix="text"
widget_factory = ScreenWidgetFormatter(
heading_formatter=WidgetFormatterFactory.from_template(
LabelWidgetFormatter,
template,
search='"Heading"',
property_map=dict(textix="text"),
),
label_cls=LabelFactory.from_template(
template, search='"Label"', textix="text"
label_formatter=WidgetFormatterFactory.from_template(
LabelWidgetFormatter,
template,
search='"Label"',
property_map=dict(textix="text"),
),
led_cls=PVWidgetFactory.from_template(
template, search='"LED"', sized=Bounds.square, chan="pv"
led_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"LED"',
sized=Bounds.square,
property_map=dict(chan="pv"),
),
progress_bar_cls=PVWidgetFactory.from_template(
template, search='"ProgressBar"', chan="pv"
progress_bar_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"ProgressBar"',
property_map=dict(chan="pv"),
),
text_read_cls=PVWidgetFactory.from_template(
template, search='"TextRead"', chan="pv"
text_read_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"TextRead"',
property_map=dict(chan="pv"),
),
check_box_cls=PVWidgetFactory.from_template(
template, search='"CheckBox"', chan="pv"
check_box_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"CheckBox"',
property_map=dict(chan="pv"),
),
combo_box_cls=PVWidgetFactory.from_template(
template, search='"ComboBox"', chan="pv"
combo_box_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"ComboBox"',
property_map=dict(chan="pv"),
),
text_write_cls=PVWidgetFactory.from_template(
template, search='"TextWrite"', chan="pv"
text_write_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"TextWrite"',
property_map=dict(chan="pv"),
),
# Cannot handle dynamic tables so insert a label with the PV name
table_cls=PVWidgetFactory.from_template(
template, search='"Label"', textix="pv"
table_formatter=WidgetFormatterFactory.from_template(
PVWidgetFormatter,
template,
search='"Label"',
property_map=dict(textix="pv"),
),
action_button_cls=ActionFactory.from_template(
template, search='"SignalX"', label="label", chan="pv"
action_button_formatter=WidgetFormatterFactory.from_template(
ActionWidgetFormatter,
template,
search='"SignalX"',
property_map=dict(label="label", chan="pv"),
),
sub_screen_cls=SubScreenFactory.from_template(
template, search='"SubScreenFile"', name="file_name"
sub_screen_formatter=WidgetFormatterFactory.from_template(
SubScreenWidgetFormatter,
template,
search='"SubScreenFile"',
property_map=dict(name="file_name"),
),
)

label_background_cls = group_box_cls = WidgetFactory.from_template(
template, search="clr=2"
label_background_formatter = WidgetFormatterFactory.from_template(
WidgetFormatter, template, search="clr=2"
)
screen_title_formatter = WidgetFormatterFactory.from_template(
LabelWidgetFormatter,
template,
search='"Title"',
property_map=dict(textix="text"),
)
screen_title_cls = LabelFactory.from_template(
template, search='"Title"', textix="text"
group_title_formatter = WidgetFormatterFactory.from_template(
LabelWidgetFormatter,
template,
search='"Group"',
property_map=dict(textix="text"),
)
group_title_cls = LabelFactory.from_template(
template, search='"Group"', textix="text"
group_box_formatter = WidgetFormatterFactory.from_template(
WidgetFormatter, template, search='fill="outline"'
)
group_box_cls = WidgetFactory.from_template(template, search='fill="outline"')

def make_group_widgets(bounds: Bounds, title: str) -> List[WidgetFactory[str]]:
def create_group_widget_formatters(
bounds: Bounds, title: str
) -> List[WidgetFormatter[str]]:
title_bounds = Bounds(
bounds.x + layout.spacing,
bounds.y + layout.spacing,
bounds.w - 2 * layout.spacing,
layout.group_label_height - layout.spacing,
)
return [
group_box_cls(bounds),
label_background_cls(title_bounds),
group_title_cls(title_bounds, title),
group_box_formatter(bounds),
label_background_formatter(title_bounds),
group_title_formatter(title_bounds, title),
]

def make_screen_widgets(bounds: Bounds, title: str) -> List[WidgetFactory[str]]:
def create_screen_widget_formatters(
bounds: Bounds, title: str
) -> List[WidgetFormatter[str]]:
title_bounds = Bounds(0, 0, bounds.w, layout.title_height)
return [
label_background_cls(title_bounds),
screen_title_cls(title_bounds, title),
label_background_formatter(title_bounds),
screen_title_formatter(title_bounds, title),
]

screen = Screen(
screen_cls=GroupFactory.from_template(
screen_factory = ScreenFormatterFactory(
screen_formatter_cls=GroupWidgetFormatterFactory.from_template(
GroupWidgetFormatter,
template,
search=GroupType.SCREEN,
sized=with_title(layout.spacing, layout.title_height),
make_widgets=make_screen_widgets,
create_widget_formatters=create_screen_widget_formatters,
),
group_cls=GroupFactory.from_template(
group_formatter_cls=GroupWidgetFormatterFactory.from_template(
GroupWidgetFormatter,
template,
search=GroupType.GROUP,
sized=with_title(layout.spacing, layout.group_label_height),
make_widgets=make_group_widgets,
create_widget_formatters=create_group_widget_formatters,
),
screen_widgets=screen_widgets,
widget_formatter=widget_factory,
prefix=prefix,
layout=layout,
base_file_name=path.stem,
)
title = f"{device.label} - {prefix}"

main_screen, sub_screens = screen.screen(device.children, title)
main_screen, sub_screens = screen_factory.create_screen_formatter(
device.children, title
)

path.write_text("".join(main_screen.format()))
for screen_name, screen_text in sub_screens:
Expand Down
Loading

0 comments on commit e61c53e

Please sign in to comment.