22from pvi .device import (
33 LED ,
44 ButtonPanel ,
5+ CheckBox ,
56 ComboBox ,
67 ComponentUnion ,
78 Device ,
1314 SignalW ,
1415 SignalX ,
1516 SubScreen ,
17+ TableRead ,
18+ TableWrite ,
1619 TextFormat ,
1720 TextRead ,
1821 TextWrite ,
2528from fastcs .attributes import Attribute , AttrR , AttrRW , AttrW
2629from fastcs .controller_api import ControllerAPI
2730from fastcs .cs_methods import Command
28- from fastcs .datatypes import Bool , Enum , Float , Int , String , Waveform
31+ from fastcs .datatypes import (
32+ Bool ,
33+ DataType ,
34+ Enum ,
35+ Float ,
36+ Int ,
37+ String ,
38+ Table ,
39+ Waveform ,
40+ )
2941from fastcs .exceptions import FastCSException
30- from fastcs .util import snake_to_pascal
42+ from fastcs .util import numpy_to_fastcs_datatype , snake_to_pascal
3143
3244from .options import EpicsGUIFormat , EpicsGUIOptions
3345
@@ -40,12 +52,13 @@ def __init__(self, controller_api: ControllerAPI, pv_prefix: str) -> None:
4052 self ._pv_prefix = pv_prefix
4153
4254 def _get_pv (self , attr_path : list [str ], name : str ):
43- attr_prefix = ":" .join ([self ._pv_prefix ] + attr_path )
55+ attr_prefix = ":" .join (
56+ [self ._pv_prefix ] + [snake_to_pascal (node ) for node in attr_path ]
57+ )
4458 return f"{ attr_prefix } :{ snake_to_pascal (name )} "
4559
46- @staticmethod
47- def _get_read_widget (attribute : AttrR ) -> ReadWidgetUnion | None :
48- match attribute .datatype :
60+ def _get_read_widget (self , fastcs_datatype : DataType ) -> ReadWidgetUnion | None :
61+ match fastcs_datatype :
4962 case Bool ():
5063 return LED ()
5164 case Int () | Float ():
@@ -59,17 +72,16 @@ def _get_read_widget(attribute: AttrR) -> ReadWidgetUnion | None:
5972 case datatype :
6073 raise FastCSException (f"Unsupported type { type (datatype )} : { datatype } " )
6174
62- @staticmethod
63- def _get_write_widget (attribute : AttrW ) -> WriteWidgetUnion | None :
64- match attribute .datatype :
75+ def _get_write_widget (self , fastcs_datatype : DataType ) -> WriteWidgetUnion | None :
76+ match fastcs_datatype :
6577 case Bool ():
6678 return ToggleButton ()
6779 case Int () | Float ():
6880 return TextWrite ()
6981 case String ():
7082 return TextWrite (format = TextFormat .string )
7183 case Enum ():
72- return ComboBox (choices = attribute . datatype .names )
84+ return ComboBox (choices = fastcs_datatype .names )
7385 case Waveform ():
7486 return None
7587 case datatype :
@@ -82,8 +94,8 @@ def _get_attribute_component(
8294 name = snake_to_pascal (name )
8395 match attribute :
8496 case AttrRW ():
85- read_widget = self ._get_read_widget (attribute )
86- write_widget = self ._get_write_widget (attribute )
97+ read_widget = self ._get_read_widget (attribute . datatype )
98+ write_widget = self ._get_write_widget (attribute . datatype )
8799 if write_widget is None or read_widget is None :
88100 return None
89101 return SignalRW (
@@ -94,12 +106,12 @@ def _get_attribute_component(
94106 read_widget = read_widget ,
95107 )
96108 case AttrR ():
97- read_widget = self ._get_read_widget (attribute )
109+ read_widget = self ._get_read_widget (attribute . datatype )
98110 if read_widget is None :
99111 return None
100112 return SignalR (name = name , read_pv = pv , read_widget = read_widget )
101113 case AttrW ():
102- write_widget = self ._get_write_widget (attribute )
114+ write_widget = self ._get_write_widget (attribute . datatype )
103115 if write_widget is None :
104116 return None
105117 return SignalW (name = name , write_pv = pv , write_widget = write_widget )
@@ -188,3 +200,39 @@ def extract_api_components(self, controller_api: ControllerAPI) -> Tree:
188200 components .append (Group (name = name , layout = Grid (), children = children ))
189201
190202 return components
203+
204+
205+ class PvaEpicsGUI (EpicsGUI ):
206+ """For creating gui in the PVA EPICS transport."""
207+
208+ def _get_pv (self , attr_path : list [str ], name : str ):
209+ return f"pva://{ super ()._get_pv (attr_path , name )} "
210+
211+ def _get_read_widget (self , fastcs_datatype : DataType ) -> ReadWidgetUnion | None :
212+ if isinstance (fastcs_datatype , Table ):
213+ fastcs_datatypes = [
214+ numpy_to_fastcs_datatype (datatype )
215+ for _ , datatype in fastcs_datatype .structured_dtype
216+ ]
217+
218+ base_get_read_widget = super ()._get_read_widget
219+ widgets = [base_get_read_widget (datatype ) for datatype in fastcs_datatypes ]
220+
221+ return TableRead (widgets = widgets ) # type: ignore
222+ else :
223+ return super ()._get_read_widget (fastcs_datatype )
224+
225+ def _get_write_widget (self , fastcs_datatype : DataType ) -> WriteWidgetUnion | None :
226+ if isinstance (fastcs_datatype , Table ):
227+ widgets = []
228+ for _ , datatype in fastcs_datatype .structured_dtype :
229+ fastcs_datatype = numpy_to_fastcs_datatype (datatype )
230+ if isinstance (fastcs_datatype , Bool ):
231+ # Replace with compact version for Table row
232+ widget = CheckBox ()
233+ else :
234+ widget = super ()._get_write_widget (fastcs_datatype )
235+ widgets .append (widget )
236+ return TableWrite (widgets = widgets )
237+ else :
238+ return super ()._get_write_widget (fastcs_datatype )
0 commit comments