source: moxy/trunk/src/moxy/moxy_wx/pv.py @ 837

Last change on this file since 837 was 837, checked in by jemian, 11 years ago

refactor common code

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Rev Url
File size: 7.5 KB
Line 
1#!/usr/bin/env python
2
3########### SVN repository information ###################
4# $Date: 2012-04-26 18:45:52 +0000 (Thu, 26 Apr 2012) $
5# $Author: jemian $
6# $Revision: 837 $
7# $URL$
8# $Id: pv.py 837 2012-04-26 18:45:52Z jemian $
9########### SVN repository information ###################
10
11'''
12demo view for EPICS PV connection class: m_pv.PvConnection()
13
14Copyright (c) 2009 - 2012, UChicago Argonne, LLC.
15See LICENSE file for details.
16'''
17
18
19# - - - - - - - - - - - - - - - - - - Imports
20
21
22import wx                   #@UnusedImport
23import wx.lib.buttons
24import wx.lib.stattext
25from moxy.model.pv import PvConnection
26import tools
27
28
29# - - - - - - - - - - - - - - - - - - Global
30
31
32__svnid__ = "$Id: pv.py 837 2012-04-26 18:45:52Z jemian $"
33
34
35# - - - - - - - - - - - - - - - - - - class
36
37
38class DemoView(wx.Frame):
39    '''
40    Show an EPICS PV connection.
41    Allow it to connect and disconnect.
42    (This is like CA Probe.)
43    '''
44   
45    _cb_counter = 0
46   
47    def __init__(self, pvname = ''):
48        self.pvname = pvname
49        self.value = ''
50        self.state = 'not connected'
51        self.remarks = ''
52        self.pv = None
53       
54        wx.Frame.__init__(self, id=wx.ID_ANY, name=u'Frame1', 
55            parent=None, title=u'PV Connection',)
56        #self.SetClientSize(wx.Size(750, 440))
57        self.SetToolTipString(u'PV Connection')
58       
59        self._init_widgets()
60        self.Bind(wx.EVT_CLOSE, self.OnClose)
61
62    def _init_widgets(self):
63        self.panel = wx.Panel(id=wx.ID_ANY, name='panel1', parent=self)
64        sizer = wx.BoxSizer(orient=wx.VERTICAL)
65        self.panel.SetSizer(sizer)
66       
67        upper = self._Make_Description_Sizer(self.panel)
68        lower = self._Make_Positions_Sizer(self.panel)
69        buttons = self._init_buttons1(self.panel)
70       
71        sizer.AddSizer(upper, 1, flag=wx.EXPAND)
72        sizer.AddSizer(lower, 1, flag=wx.EXPAND)
73        sizer.AddSizer(buttons, 0, flag=wx.EXPAND)
74
75    def _Make_Description_Sizer(self, parent):
76        '''
77        edit the PV name string if not connected
78        '''
79        self.w_pvname = tools.TextEntry(parent, editable=True)
80        self.w_value = tools.TextEntry(parent, bgColor=tools.COLOR_BACKGROUND)
81       
82        self.SetPV(self.pvname)
83        self.SetValue(self.value)
84
85        sbox = wx.StaticBox(parent, id=wx.ID_ANY,
86              label='PV name and value', style=0)
87        sbs = wx.StaticBoxSizer(sbox, wx.VERTICAL)
88        fgs = wx.FlexGridSizer(rows=2, cols=2, hgap=4, vgap=4)
89        fgs.AddGrowableCol(1)
90        sbs.Add(fgs, 0, wx.EXPAND|wx.ALIGN_CENTRE|wx.ALL, 5)
91
92        fgs.Add(wx.lib.stattext.GenStaticText(parent, wx.ID_ANY, 'PV name'), 0, flag=wx.EXPAND)
93        fgs.Add(self.w_pvname, 0, flag=wx.EXPAND)
94        fgs.Add(wx.lib.stattext.GenStaticText(parent, wx.ID_ANY, 'value'), 0, flag=wx.EXPAND)
95        fgs.Add(self.w_value, 0, flag=wx.EXPAND)
96
97        return sbs
98
99    def _Make_Positions_Sizer(self, parent):
100        '''
101        show connection state and something else useful
102        '''
103        self.w_state = tools.TextEntry(parent)
104        self.w_remarks = tools.TextEntry(parent)
105       
106        self.SetState(self.state)
107        self.SetRemarks(self.remarks)
108       
109        sbox = wx.StaticBox(parent, id=wx.ID_ANY,
110              label='connection status', style=0)
111        sbs = wx.StaticBoxSizer(sbox, wx.VERTICAL)
112        fgs = wx.FlexGridSizer(rows=2, cols=1, hgap=4, vgap=4)
113        fgs.AddGrowableCol(0)
114        sbs.Add(fgs, 0, wx.EXPAND|wx.ALIGN_CENTRE|wx.ALL, 5)
115       
116        fgs.Add(self.w_state, 0, flag=wx.EXPAND)
117        fgs.Add(self.w_remarks, 0, flag=wx.EXPAND)
118
119        return sbs
120   
121    def _init_buttons1(self, parent):
122        '''
123        build the buttons row and place it in a sizer, return the sizer
124        '''
125        self.connectButton = tools.Button(parent, 
126              label=u'Connect', name='connectButton', 
127              tip=u'Connect with EPICS PV', 
128              binding=self.doConnectButton)
129        self.disconnectButton = tools.Button(parent, 
130              label=u'Disconnect', name='disconnectButton', 
131              tip=u'Disconnect from EPICS PV', 
132              binding=self.doDisconnectButton)
133
134        sizer = wx.BoxSizer(orient=wx.HORIZONTAL)
135        sizer.AddWindow(self.connectButton, proportion=1, flag=wx.EXPAND)
136        sizer.AddWindow(self.disconnectButton, proportion=1, flag=wx.EXPAND)
137        return sizer
138
139    def connect(self):
140        self.w_pvname.SetEditable(False)
141        pvname = self.w_pvname.GetValue()
142        if len(pvname.strip()) > 0:
143            self.pvname = pvname
144            self.pv = PvConnection(pvname)
145            self.pv.connect(self.callback, vc_pv = True)
146
147    def disconnect(self):
148        self.w_pvname.SetEditable(True)
149        self.pv.disconnect()
150        self.pv = None      # throw away the PV connection
151        self.SetState( 'not connected' )
152        self.SetRemarks( '' )
153        wx.CallAfter(self.w_value.SetBackgroundColour, tools.COLOR_BACKGROUND)
154
155    def doConnectButton(self, event):
156        self.connect()
157
158    def doDisconnectButton(self, event):
159        self.disconnect()
160
161    def SetPV(self, value):
162        self.pvname = str(value)
163        wx.CallAfter(self.w_pvname.SetValue, self.pvname)
164
165    def SetRemarks(self, value):
166        self.remarks = str(value)
167        wx.CallAfter(self.w_remarks.SetValue, self.remarks)
168
169    def SetState(self, value):
170        self.state = str(value)
171        wx.CallAfter(self.w_state.SetValue, self.state)
172
173    def SetValue(self, value):
174        self.value = str(value)
175        wx.CallAfter(self.w_value.SetValue, self.value)
176   
177    def ColorSelector(self, index):
178        # this makes a gaudy display
179        clut = [ tools.COLOR_NOT_MOVING, 
180                 tools.COLOR_MOVING, 
181                 tools.COLOR_PALE_PURPLE, 
182                 tools.COLOR_LIGHTGREEN, 
183                 tools.COLOR_LIGHTRED,
184                 tools.COLOR_RED,
185                 'orange',
186                 'yellow',
187                 'green',
188                 'blue',
189                 'indigo',
190                 'violet',
191                 'white',
192                 'salmon',
193                 'bisque',
194                 'goldenrod',
195                 'mintcream',
196                 'skyblue',
197        ]
198        return clut[index % len(clut)]
199   
200    def callback(self, **kw):
201        "generic monitor callback"
202        #print kw
203        if 'conn' in kw.keys():
204            self.SetState({False: 'not connected', True: 'connected'}[kw['conn']])
205            if kw['conn']:
206                value = self.pv.channel.get()
207                self.SetValue( value )
208            else:
209                wx.CallAfter(self.w_value.SetBackgroundColour, tools.COLOR_BACKGROUND)
210                self.SetRemarks( 'disconnect received, IOC is unavailable?' )
211        else:
212            self.SetRemarks(kw['cb_info'])
213            self.SetValue(kw['value'])
214            self._cb_counter += 1   # change the color every update event
215            color = self.ColorSelector(self._cb_counter)
216            wx.CallAfter(self.w_value.SetBackgroundColour, color)
217
218    def OnClose(self, event):
219        dlg = wx.MessageDialog(self, 
220            "Do you really want to close this application?",
221            "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
222        result = dlg.ShowModal()
223        dlg.Destroy()
224        if result == wx.ID_OK:
225            if self.pv is not None:
226                self.pv.disconnect()
227            self.Destroy()
228
229
230# - - - - - - - - - - - - - - - - - - methods
231
232
233def _demo_():
234    '''demonstrate use of this module'''
235    app = wx.App()
236    fr = DemoView('Godzilla')
237    fr.SetValue( 'loves Tokyo' )
238    fr.SetState( 'just started' )
239    fr.SetPV('pj:test')
240    fr.SetPV('prj:m1.RBV')
241    fr.Show()
242    app.MainLoop()
243
244
245# - - - - - - - - - - - - - - - - - - main
246
247
248if __name__ == '__main__':
249    _demo_()
Note: See TracBrowser for help on using the repository browser.