-
Notifications
You must be signed in to change notification settings - Fork 19
/
AttributeEditor.py
300 lines (247 loc) · 7.72 KB
/
AttributeEditor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# -*- coding: utf-8 -*-
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
# AttributeEditor.py ---
# --------------------------------
# Copyright (c) 2020
# L. CAPOCCHI ([email protected])
# SPE Lab - SISU Group - University of Corsica
# --------------------------------
# Version 2.0 last modified: 03/15/20
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#
# GENERAL NOTES AND REMARKS:
#
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#
# GLOBAL VARIABLES AND FUNCTIONS
#
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
import os
import sys
import linecache
import wx
import gettext
_ = gettext.gettext
import DiagramNotebook
from PropertiesGridCtrl import PropertiesGridCtrl, CodeCB
from DetachedFrame import DetachedFrame
from Patterns.Observer import Subject
from Mixins.Achievable import Achievable
from Decorators import Post_Undo
class AttributeBase(object):
""" Base class to avoid multi inheritence with wx.Frame and wx.Panel used in the DEVSimPy 2.9 version
"""
def __init__(self, parent, ID, model, canvas):
""" Constructor.
@param parent: wxWindows parent
@param ID: Id
@param model: considered model
@param canvas: canvas object
@type parent: instance
@type ID: integer
@type title: String
@type canvas: canvas object
"""
#local copy
self.model = model
self.parent = parent
self.canvas = canvas
# pour garder la relation entre les propriétés afficher et le model associé (voir OnLeftClick de Block)
self.parent.id = id(self.model)
# properties list
self._list = PropertiesGridCtrl(self)
# Create a box sizer for self
self._box = wx.BoxSizer(wx.VERTICAL)
self._box.Add(self._list, 1, wx.EXPAND|wx.ALL)
###linecache module which inspect uses. It caches the file contents and does not reload it accordingly.
linecache.clearcache()
## text doc de la classe
#doc=inspect.getdoc(self.model.getDEVSModel().__class__)
if isinstance(self.model, Achievable):
self._boxH = wx.BoxSizer(wx.HORIZONTAL)
self._code = CodeCB(self, wx.NewIdRef(), self.model)
self._boxH.Add(self._code, 1, wx.ALL|wx.EXPAND, userData='code')
self._box.Add(self._boxH, 1, wx.ALL|wx.EXPAND, userData='code')
self.SetSizer(self._box)
self._box.SetSizeHints(self)
self.CenterOnParent()
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self._list.Bind(wx.EVT_SIZE, self.OnSize)
def OnSize(self, event):
""" Frame has been resized.
"""
### widt and weight of frame
width, height = self.GetClientSizeTuple() if wx.VERSION_STRING<'4.0' else wx.Window.GetClientSize(self)
### number of column of wx.grid
nb_cols = self._list.GetNumberCols()
### width of new column depending of new wx.grid column
width /= nb_cols
for col in range(nb_cols):
self._list.SetColSize(int(col), int(width))
### refresh grid
self._list.Refresh()
def OnKeyDown(self, event):
""" Keyboard has been pressed
"""
keycode = event.GetKeyCode()
x, y = self._list.CalcUnscrolledPosition(event.GetPosition())
coords = self._list.XYToCell(x, y)
row = coords[0]
col = coords[1]
### enter key has been pressed
if keycode == wx.WXK_RETURN:
### save and exit the cell if it was edited
if self._list.IsCellEditControlEnabled():
self._list.DisableCellEditControl()
### close frame
else:
if isinstance(self, wx.Frame):
self.Close()
### circular moving for rows of col 1
elif keycode == wx.WXK_TAB:
if not self._list.MoveCursorDown(False):
self._list.MovePageUp()
elif keycode == wx.WXK_DELETE:
if not self._list.IsReadOnly(row,col):
self._list.SetCellValue(row,col,"")
else:
event.Skip()
###
def MakeIcon(self, img):
"""
The various platforms have different requirements for the
icon size...
"""
if "wxMSW" in wx.PlatformInfo:
img = img.Scale(16, 16)
elif "wxGTK" in wx.PlatformInfo:
img = img.Scale(22, 22)
# wxMac can be any size up to 128x128, so leave the source img alone....
if wx.VERSION_STRING<'4.0':
return wx.IconFromBitmap(img.ConvertToBitmap())
else:
return wx.Icon(img.ConvertToBitmap())
def OnClose(self, event):
self.canvas.UpdateShapes()
self.Destroy()
event.Skip()
def AttributeEditor(*args,**kwargs):
""" Factory function
"""
parent = args[0]
# pour gerer l'affichage dans la page de gauche dans le notebook
if isinstance(parent, (DiagramNotebook.DiagramNotebook, DetachedFrame)):
return AttributeEditorFrame(*args,**kwargs)
elif isinstance(parent, wx.Panel):
return AttributeEditorPanel(*args,**kwargs)
else:
sys.stdout.write(_("Parent not defined for AttributeEditor class"))
return None
###
class AttributeEditorPanel(AttributeBase, wx.Panel):
""" Model attributes in Panel
"""
def __init__(self, parent, ID, model, canvas):
""" Constructor.
"""
# pour gerer l'affichage dans la page de gauche dans le notebook
wx.Panel.__init__(self, parent, ID)
self.SetBackgroundColour(wx.WHITE)
AttributeBase.__init__(self, parent, ID, model, canvas)
###
class AttributeEditorFrame(AttributeBase, wx.Frame):
""" Model attributes in Frame
"""
def __init__(self, parent, ID, model, canvas):
""" Constructor.
"""
wx.Frame.__init__(self, parent, ID, model.label, size = wx.Size(400, 550), style = wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN )
self.SetIcon(self.MakeIcon(wx.Image(os.path.join(ICON_PATH_16_16, 'properties.png'), wx.BITMAP_TYPE_PNG)))
self.Bind(wx.EVT_CLOSE, self.OnClose)
AttributeBase.__init__(self, parent, ID, model, canvas)
###
class QuickAttributeEditor(wx.Frame, Subject):
"""
"""
def __init__(self, parent, id, model):
""" Constructor.
"""
wx.Frame.__init__(self, \
parent, \
id, \
size=(120, 30), \
style=wx.CLIP_CHILDREN|\
wx.FRAME_NO_TASKBAR|\
wx.NO_BORDER|\
wx.FRAME_SHAPED)
Subject.__init__(self)
### Subject init
self.canvas = self.GetParent()
self.__state = {}
self.attach(model)
self.attach(self.canvas.GetDiagram())
#spinCtrl for input and output port numbers
self._sb_input = wx.SpinCtrl(self, wx.NewIdRef(), size=(60,-1), min=0, max=100000)
self._sb_output = wx.SpinCtrl(self, wx.NewIdRef(), size=(60,-1), min=0, max=100000)
# mouse positions
xwindow, ywindow = wx.GetMousePosition()
if wx.VERSION_STRING < '4.0':
xm,ym = self.ScreenToClientXY(xwindow, ywindow)
else:
xm,ym = self.ScreenToClient(wx.Point(int(xwindow), int(ywindow)))
self.SetPosition((int(xm),int(ym)))
#default value for spinCtrl
self._sb_input.SetValue(model.input)
self._sb_output.SetValue(model.output)
self.__do_layout()
self.__set_binding()
###
def __do_layout(self):
"""
"""
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
sizer_1.Add(self._sb_input, 0, wx.ADJUST_MINSIZE, 0)
sizer_1.Add(self._sb_output, 0, wx.ADJUST_MINSIZE, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
###
def __set_binding(self):
"""
"""
self._sb_input.Bind(wx.EVT_TEXT, self.OnInput)
self._sb_output.Bind(wx.EVT_TEXT, self.OnOuput)
self.Bind(wx.EVT_CLOSE, self.OnClose)
@Post_Undo
def OnInput(self, event):
"""
"""
self.__state['input'] = self._sb_input.GetValue()
self.notify()
@Post_Undo
def OnOuput(self, event):
"""
"""
self.__state['output'] = self._sb_output.GetValue()
self.notify()
###
def GetState(self):
"""
"""
return self.__state
###
def Undo(self):
"""
"""
self.canvas.Undo()
###
def OnClose(self, event):
"""
"""
self.Destroy()
event.Skip()
def main():
pass
if __name__ == '__main__':
main()