Skip to content

Commit

Permalink
Add format to Text{Read,Write} widgets
Browse files Browse the repository at this point in the history
- Add TextFormat enum to store text format types
  • Loading branch information
GDYendell committed Jul 18, 2023
1 parent 6f84258 commit 58bbf5f
Show file tree
Hide file tree
Showing 9 changed files with 1,034 additions and 7 deletions.
34 changes: 34 additions & 0 deletions schemas/pvi.device.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,32 @@
"type": "integer",
"description": "Number of lines to display",
"default": 1
},
"format": {
"anyOf": [
{
"$ref": "#/definitions/TextFormat"
},
{
"type": "null"
}
],
"description": "Display format",
"default": null
}
},
"additionalProperties": false
},
"TextFormat": {
"type": "integer",
"enum": [
0,
1,
2,
3,
4
]
},
"ArrayTrace": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -358,6 +380,18 @@
"type": "integer",
"description": "Number of lines to display",
"default": 1
},
"format": {
"anyOf": [
{
"$ref": "#/definitions/TextFormat"
},
{
"type": "null"
}
],
"description": "Display format",
"default": null
}
},
"additionalProperties": false
Expand Down
29 changes: 28 additions & 1 deletion src/pvi/_format/adl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@

from pvi._format.utils import Bounds, split_with_sep
from pvi._format.widget import UITemplate, WidgetFormatter
from pvi.device import WidgetType
from pvi.device import TextFormat, TextRead, TextWrite, WidgetType

ADL_TEXT_FORMATS = {
TextFormat.decimal: "decimal",
TextFormat.hexadecimal: "hexadecimal",
TextFormat.engineer: "engr. notation",
TextFormat.exponential: "exponential",
TextFormat.string: "string",
}


class AdlTemplate(UITemplate[str]):
Expand All @@ -27,15 +35,25 @@ def set(
properties["y"] = bounds.y
properties["width"] = bounds.w
properties["height"] = bounds.h

for item, value in properties.items():
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}"'

template, n = pattern.subn(r"\g<1>=" + str(value), template)
assert n == 1, f"No replacements made for {item}"

match widget:
case TextWrite(_, format) | TextRead(_, format) if (
is_text_widget(template) and format is not None
):
template = add_property(template, "format", ADL_TEXT_FORMATS[format])

return template

def search(self, search: str) -> str:
Expand All @@ -57,3 +75,12 @@ def create_group(
texts += c.format()

return group_object + texts


def is_text_widget(text: str):
return text.startswith('"text ')


def add_property(text: str, property: str, value: str) -> str:
end = "\n}"
return text.replace(end, f'\n\t{property}="{value}"{end}')
33 changes: 28 additions & 5 deletions src/pvi/_format/bob.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@
ComboBox,
Group,
Row,
TableRead,
TableWidgetType,
TableWidgetTypes,
TableWrite,
TextFormat,
TextRead,
TextWrite,
WidgetType,
WriteWidget,
)

BOB_TEXT_FORMATS = {
TextFormat.decimal: "1",
TextFormat.hexadecimal: "4",
TextFormat.engineer: "3",
TextFormat.exponential: "2",
TextFormat.string: "6",
}


class BobTemplate(UITemplate[ElementBase]):
"""Extract and modify elements from a template .bob file."""
Expand Down Expand Up @@ -58,10 +69,17 @@ def set(
if new_text:
replace_text(t_copy, item, new_text)

if widget_type == "table" and isinstance(widget, TableWidgetTypes):
add_table_columns(t_copy, widget)
elif widget_type == "combo" and isinstance(widget, ComboBox):
add_combo_box_items(t_copy, widget)
# Add additional properties from widget
match widget_type, widget:
case ("combo", ComboBox() as combo_box):
add_combo_box_items(t_copy, combo_box)
case ("table", TableRead() | TableWrite() as table):
add_table_columns(t_copy, table)
case (
("textentry", TextWrite(_, format))
| ("textupdate", TextRead(_, format))
) if format is not None:
add_format(t_copy, BOB_TEXT_FORMATS[format])

return t_copy

Expand Down Expand Up @@ -174,6 +192,11 @@ def add_editable(element: ElementBase, editable: bool):
SubElement(element, "editable").text = "true" if editable else "false"


def add_format(element: ElementBase, format: str):
if format:
SubElement(element, "format").text = format


def replace_text(element: ElementBase, tag: str, text: str):
try:
# Iterate tree to find tag and replace text
Expand Down
30 changes: 29 additions & 1 deletion src/pvi/_format/edl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@

from pvi._format.utils import Bounds, split_with_sep
from pvi._format.widget import UITemplate, WidgetFormatter
from pvi.device import WidgetType
from pvi.device import TextFormat, TextRead, TextWrite, WidgetType

EDL_TEXT_FORMATS = {
TextFormat.decimal: "decimal",
TextFormat.hexadecimal: "hex",
TextFormat.engineer: "engineer",
TextFormat.exponential: "exp",
TextFormat.string: "default",
}


class EdlTemplate(UITemplate[str]):
Expand All @@ -27,6 +35,7 @@ def set(
for item, value in properties.items():
if item == "displayFileName":
value = f"0 {value}" # These are items in an array but we only use one

multiline = re.compile(r"^%s {[^}]*}$" % item, re.MULTILINE | re.DOTALL)
if multiline.search(template):
pattern = multiline
Expand All @@ -37,8 +46,18 @@ def set(
pattern = re.compile(r"^%s .*$" % item, re.MULTILINE)
if isinstance(value, str):
value = f'"{value}"'

template, n = pattern.subn(f"{item} {value}", template)
assert n == 1, f"No replacements made for {item}"

match widget:
case TextWrite(_, format) | TextRead(_, format) if (
is_text_widget(template) and format is not None
):
template = add_property(
template, "displayMode", EDL_TEXT_FORMATS[format]
)

return template

def search(self, search: str) -> str:
Expand All @@ -60,3 +79,12 @@ def create_group(
texts += c.format()

return group_object + texts


def is_text_widget(text: str):
return text.startswith("\n# (Text")


def add_property(text: str, property: str, value: str) -> str:
end = "endObjectProperties\n"
return text.replace(end, f'{property} "{value}"\n{end}')
13 changes: 13 additions & 0 deletions src/pvi/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json
import re
from dataclasses import dataclass, field, fields
from enum import Enum
from pathlib import Path
from typing import (
Annotated,
Expand Down Expand Up @@ -49,6 +50,16 @@ def to_snake_case(pascal_s: str) -> str:
return PASCAL_CASE_REGEX.sub(lambda m: "_" + m.group().lower(), pascal_s)[1:]


class TextFormat(Enum):
"""Format to use for display of Text{Read,Write} widgets on a UI"""

decimal = 0
hexadecimal = 1
engineer = 2
exponential = 3
string = 4


@as_discriminated_union
@dataclass
class ReadWidget:
Expand All @@ -75,6 +86,7 @@ class TextRead(ReadWidget):
"""Text view of any PV"""

lines: Annotated[int, desc("Number of lines to display")] = 1
format: Annotated[Optional[TextFormat], desc("Display format")] = None


@dataclass
Expand Down Expand Up @@ -141,6 +153,7 @@ class TextWrite(WriteWidget):
"""Text control of any PV"""

lines: Annotated[int, desc("Number of lines to display")] = 1
format: Annotated[Optional[TextFormat], desc("Display format")] = None


@dataclass
Expand Down
Loading

0 comments on commit 58bbf5f

Please sign in to comment.