--- a/Beremiz.py Thu Jun 28 16:42:07 2012 +0200
+++ b/Beremiz.py Sun Jul 01 23:20:19 2012 +0200
@@ -605,12 +605,14 @@
selected = self.TabsOpened.GetSelection()
- graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
+ window = self.TabsOpened.GetPage(selected) + viewer_is_modified = window.IsModified() + is_viewer = isinstance(window, Viewer)
+ viewer_is_modified = is_viewer = False if self.TabsOpened.GetPageCount() > 0:
self.FileMenu.Enable(wx.ID_CLOSE, True)
self.FileMenu.Enable(wx.ID_PREVIEW, True)
self.FileMenu.Enable(wx.ID_PRINT, True)
MenuToolBar.EnableTool(wx.ID_PRINT, True)
@@ -624,7 +626,7 @@
self.FileMenu.Enable(wx.ID_PRINT, False)
MenuToolBar.EnableTool(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
- project_modified = self.CTR.ProjectTestModified()
+ project_modified = self.CTR.ProjectTestModified() or viewer_is_modified self.FileMenu.Enable(wx.ID_SAVE, project_modified)
MenuToolBar.EnableTool(wx.ID_SAVE, project_modified)
self.FileMenu.Enable(wx.ID_SAVEAS, True)
@@ -876,12 +878,20 @@
def OnSaveProjectMenu(self, event):
+ selected = self.TabsOpened.GetSelection() + window = self.TabsOpened.GetPage(selected) self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
def OnSaveProjectAsMenu(self, event):
+ selected = self.TabsOpened.GetSelection() + window = self.TabsOpened.GetPage(selected) --- a/ConfigTreeNode.py Thu Jun 28 16:42:07 2012 +0200
+++ b/ConfigTreeNode.py Sun Jul 01 23:20:19 2012 +0200
@@ -408,15 +408,13 @@
def _OpenView(self, name=None, onlyopened=False):
if self.EditorType is not None:
app_frame = self.GetCTRoot().AppFrame
+ if self._View is None and not onlyopened: self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
+ if self._View is not None: app_frame.EditProjectElement(self._View, self.CTNName())
- app_frame.EditProjectElement(self._View, self.CTNName(), onlyopened)
--- a/ProjectController.py Thu Jun 28 16:42:07 2012 +0200
+++ b/ProjectController.py Sun Jul 01 23:20:19 2012 +0200
@@ -939,6 +939,10 @@
def _OpenProjectFiles(self):
self._OpenView("Project files")
+ def _OpenFileEditor(self, filepath): + self._OpenView(filepath) def _OpenView(self, name=None, onlyopened=False):
if self._IECCodeView is None:
@@ -955,11 +959,9 @@
self._IECCodeView.SetText(text = text)
self._IECCodeView.SetIcon(GetBitmap("ST"))
+ if self._IECCodeView is not None: self.AppFrame.EditProjectElement(self._IECCodeView, name)
- self.AppFrame.EditProjectElement(self._IECCodeView, name, onlyopened)
elif name == "IEC raw code":
@@ -972,25 +974,56 @@
self._IECRawCodeView.SetKeywords(IEC_KEYWORDS)
self._IECRawCodeView.RefreshView()
self._IECRawCodeView.SetIcon(GetBitmap("ST"))
+ if self._IECRawCodeView is not None: self.AppFrame.EditProjectElement(self._IECRawCodeView, name)
- self.AppFrame.EditProjectElement(self._IECRawCodeView, name, onlyopened)
return self._IECRawCodeView
elif name == "Project files":
if self._ProjectFilesView is None:
self._ProjectFilesView = FileManagementPanel(self.AppFrame.TabsOpened, self, name, self._getProjectFilesPath(), True)
+ for extension, name, editor in features.file_editors: + if extension not in extensions: + extensions.append(extension) + self._ProjectFilesView.SetEditableFileExtensions(extensions) + if self._ProjectFilesView is not None: self.AppFrame.EditProjectElement(self._ProjectFilesView, name)
- self.AppFrame.EditProjectElement(self._ProjectFilesView, name, onlyopened)
+ return self._ProjectFilesView + elif name is not None and os.path.isfile(name): + if not self._FileEditors.has_key(name): + file_extension = os.path.splitext(name)[1] + editors = dict([(editor_name, editor) + for extension, editor_name, editor in features.file_editors + if extension == file_extension]) + editor_name = editors.keys()[0] + dialog = wx.SingleChoiceDialog(self.ParentWindow, + _("Select an editor:"), _("Editor selection"), + names, wx.OK|wx.CANCEL) + if dialog.ShowModal() == wx.ID_OK: + editor_name = names[dialog.GetSelection()] + if editor_name is not None: + editor = editors[editor_name]() + self._FileEditors[name] = editor(self.AppFrame.TabsOpened, self, name, self.AppFrame) + self._FileEditors[name].SetIcon(GetBitmap("FILE")) + if self._FileEditors.has_key(name): + self.AppFrame.EditProjectElement(self._FileEditors[name], name) - return self._ProjectFilesView
+ return self._FileEditors[name] return ConfigTreeNode._OpenView(self, name, onlyopened)
@@ -1002,6 +1035,8 @@
self._IECRawCodeView = None
if self._ProjectFilesView == view:
self._ProjectFilesView = None
+ if view in self._FileEditors.values(): + self._FileEditors.pop(view.GetTagName()) self._CloseView(self._IECCodeView)
--- a/canfestival/canfestival.py Thu Jun 28 16:42:07 2012 +0200
+++ b/canfestival/canfestival.py Sun Jul 01 23:20:19 2012 +0200
@@ -108,8 +108,8 @@
return self.CanFestivalSlaveNode.getCan_Device()
- ConfigTreeNode._OpenView(self)
+ def _OpenView(self, name=None, onlyopened=False): + ConfigTreeNode._OpenView(self, name, onlyopened) if self._View is not None:
self._View.SetBusId(self.GetCurrentLocation())
@@ -273,10 +273,8 @@
manager = MiniNodeManager(self, masterpath, self.CTNFullName() + ".generated_master")
self._GeneratedMasterView = MasterViewer(app_frame.TabsOpened, manager, app_frame)
- app_frame.EditProjectElement(self._GeneratedMasterView, name)
- app_frame.EditProjectElement(self._IECCodeView, name, onlyopened)
+ if self._GeneratedMasterView is not None: + app_frame.EditProjectElement(self._IECCodeView, name) return self._GeneratedMasterView
--- a/features.py Thu Jun 28 16:42:07 2012 +0200
+++ b/features.py Sun Jul 01 23:20:19 2012 +0200
@@ -1,5 +1,6 @@
-libraries = [('Python','py_ext.PythonLibrary'),
- ('SVGUI','svgui.SVGUILibrary')]
+ ('Python', 'py_ext.PythonLibrary'), + ('SVGUI', 'svgui.SVGUILibrary')] ('canfestival', _('CANopen support'), _('Map located variables over CANopen'), 'canfestival.canfestival.RootClass'),
@@ -8,3 +9,4 @@
('wxglade_hmi', _('WxGlade GUI'), _('Add a simple WxGlade based GUI.'), 'wxglade_hmi.WxGladeHMI'),
('svgui', _('SVGUI'), _('Experimental web based HMI'), 'svgui.SVGUI')]
--- a/images/icons.svg Thu Jun 28 16:42:07 2012 +0200
+++ b/images/icons.svg Sun Jul 01 23:20:19 2012 +0200
@@ -43,9 +43,9 @@
- inkscape:zoom="7.2407738"
- inkscape:cx="596.13887"
- inkscape:cy="800.65537"
+ inkscape:zoom="28.963095" + inkscape:cx="519.38634" inkscape:current-layer="svg2"
@@ -87871,6 +87871,164 @@
xlink:href="#radialGradient8198"
inkscape:collect="always" />
+ gradientTransform="translate(-40,0)" + gradientUnits="userSpaceOnUse" + id="linearGradient17986-08" + xlink:href="#linearGradient5175-3-7-9-2-7-1" + inkscape:collect="always" /> + id="linearGradient5175-3-7-9-2-7-1"> + style="stop-color:#bdcccd;stop-opacity:1;" + id="stop5177-6-9-6-1-9-0" /> + style="stop-color:#7979ff;stop-opacity:1;" + id="stop5179-73-8-3-1-8-7" /> + gradientTransform="translate(-40,0)" + gradientUnits="userSpaceOnUse" + id="linearGradient18365" + xlink:href="#linearGradient5175-3-7-9-2-7-1" + inkscape:collect="always" /> + id="linearGradient3262-4" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-17.058,0)" + style="stop-color:#f6f6f6" + style="stop-color:#ccc" + id="linearGradient3264-6" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-17.058,0)" + style="stop-color:#aaa" + style="stop-color:#8c8c8c" + id="linearGradient3260-1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.096142,0,0,0.096142,1.8469,1.943)" + style="stop-color:#e5e5e5" + style="stop-color:#ababab" + id="linearGradient2517-1" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.31429,0,0,0.32593,0.45711,-0.32225)" + style="stop-color:#f4f4f4" + style="stop-color:#dbdbdb" + id="linearGradient2519-4" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.25379,0,0,0.30502,19.129,-0.68549)" + style="stop-color:#aaa" + style="stop-color:#c8c8c8" + id="linearGradient2511-5" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.27273,0,0,0.30232,1.4546,0.7442)" + style="stop-color:#fff" + style="stop-color:#fff;stop-opacity:0" + id="linearGradient2507-51" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.3092,0,0,0.37669,0.47615,0.10718)" + style="stop-color:#fefefe" + style="stop-color:#cbcbcb" + gradientTransform="matrix(0.3092,0,0,0.37669,0.47615,0.10718)" + gradientUnits="userSpaceOnUse" + id="linearGradient3039-9" + xlink:href="#linearGradient2507-51" + inkscape:collect="always" /> @@ -91756,7 +91914,7 @@
- sodipodi:role="line">%% Extension Cfile Pyfile wxGlade SVGUI FOLDER %%</tspan></text>
+ sodipodi:role="line">%% Extension Cfile Pyfile wxGlade SVGUI FOLDER FILE %%</tspan></text> inkscape:label="#use3839"
@@ -93398,4 +93556,64 @@
sodipodi:nodetypes="cccccccccc"
inkscape:label="#rect2160" />
+ transform="matrix(0.83945151,0,0,0.83945151,496.66938,322.90098)" + inkscape:connector-curvature="0" + style="fill:url(#linearGradient2517-1);stroke:url(#linearGradient2519-4);stroke-width:0.99992001;stroke-linejoin:round" + d="M 1.5,0.49997 H 9.9412 C 10.383,0.66176 12.88,2.63277 13.5,3.90907 v 11.591 h -12 v -15 z" /> + inkscape:connector-curvature="0" + style="opacity:0.6;fill:none;stroke:url(#linearGradient2511-5)" + d="m 12.5,4.2151 v 10.285 h -10 v -13 h 7.2363" /> + inkscape:connector-curvature="0" + style="fill:#c1c1c1;fill-rule:evenodd" + d="M 9.2941,0.8409 C 10.142,3.6448 9,5.0341 9,5.0341 c 0,0 1.893,-1.2514 4.171,-0.1023 1.943,0.9798 0.036,-1.008 -0.041,-1.129 C 12.587,2.9553 10.707,1.1697 10.025,0.8726 9.9696,0.84836 9.5814,0.8409 9.2941,0.8409 z" /> + inkscape:connector-curvature="0" + style="fill:url(#linearGradient3039-9);fill-rule:evenodd" + d="m 9.2941,0.8409 c 0.9879,0 0.7059,3.181 0.7059,3.181 0,0 2.272,-0.5007 3.171,0.9099 0.163,0.2556 0.036,-1.008 -0.041,-1.129 C 12.587,2.9553 10.707,1.1697 10.025,0.8726 9.9696,0.84836 9.5814,0.8409 9.2941,0.8409 z" /> + transform="translate(534.91586,321.71842)" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + inkscape:connector-curvature="0" + style="fill:url(#linearGradient18365);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" + d="m -40,0 0,16 16,0 0,-16 -16,0 z m 1,1 14,0 0,14 -14,0 0,-14 z" + id="path3806-1-6-1-9-0" + sodipodi:nodetypes="cccccccccc" + inkscape:label="#rect2160" /> + transform="matrix(0.39454693,0,0,0.39454693,503.03943,330.01484)" + inkscape:connector-curvature="0" + style="fill:url(#linearGradient3262-4);stroke:url(#linearGradient3264-6);stroke-linejoin:round;display:block" + d="M 6.9375,0.5 C 6.6891,0.5 6.5,0.68908 6.5,0.9375 v 1.25 C 5.9461,2.3297 5.4488,2.5594 4.9688,2.8438 L 4.0625,1.9375 c -0.17566,-0.17566 -0.44934,-0.17566 -0.625,0 l -1.5,1.5 c -0.17566,0.17566 -0.17566,0.44934 0,0.625 L 2.8438,4.9688 C 2.5594,5.4488 2.3297,5.9461 2.1875,6.5 h -1.25 C 0.68908,6.5 0.5,6.6891 0.5,6.9375 v 2.125 c 1e-8,0.24842 0.18908,0.4375 0.4375,0.4375 h 1.25 c 0.1422,0.5539 0.37188,1.0512 0.65625,1.5312 l -0.9063,0.907 c -0.17566,0.17566 -0.17566,0.44934 0,0.625 l 1.5,1.5 c 0.17566,0.17566 0.44934,0.17566 0.625,0 l 0.9063,-0.907 c 0.48,0.285 0.9773,0.514 1.5312,0.656 v 1.25 c 1e-7,0.24842 0.18908,0.4375 0.4375,0.4375 h 2.125 c 0.2484,0 0.4375,-0.189 0.4375,-0.438 v -1.25 c 0.5539,-0.1422 1.0512,-0.37188 1.5312,-0.65625 l 0.90625,0.90625 c 0.17566,0.17566 0.44934,0.17566 0.625,0 l 1.5,-1.5 c 0.17566,-0.17566 0.17566,-0.44934 0,-0.625 l -0.906,-0.906 c 0.285,-0.48 0.514,-0.977 0.656,-1.531 h 1.25 c 0.249,0 0.438,-0.1891 0.438,-0.4375 v -2.125 c 0,-0.2484 -0.189,-0.4375 -0.438,-0.4375 h -1.25 c -0.142,-0.5539 -0.371,-1.0512 -0.656,-1.5312 l 0.906,-0.9063 c 0.17566,-0.17566 0.17566,-0.44934 0,-0.625 l -1.5,-1.5 c -0.17566,-0.17566 -0.44934,-0.17566 -0.625,0 l -0.906,0.9063 c -0.48,-0.2844 -0.977,-0.5141 -1.531,-0.6563 v -1.25 C 9.5004,0.68878 9.3113,0.4997 9.0629,0.4997 H 6.9379 z M 8,6 c 1.104,0 2,0.896 2,2 0,1.104 -0.896,2 -2,2 C 6.896,10 6,9.104 6,8 6,6.896 6.896,6 8,6 z" /> + inkscape:connector-curvature="0" + d="M 8,3.4651 C 5.4994,3.4651 3.4651,5.4994 3.4651,8 c 0,2.501 2.0343,4.535 4.5349,4.535 2.501,0 4.535,-2.034 4.535,-4.535 C 12.535,5.4994 10.501,3.4651 8,3.4651 z m 0,2.093 c 1.3479,0 2.4419,1.094 2.4419,2.4419 0,1.3479 -1.094,2.4419 -2.4419,2.4419 -1.3479,0 -2.4419,-1.0941 -2.4419,-2.442 C 5.5581,6.652 6.6521,5.558 8,5.558 z" /> + inkscape:connector-curvature="0" + style="fill:none;stroke:url(#linearGradient3260-1)" + d="M 8,4 C 5.7944,4 4,5.7944 4,8 c 0,2.206 1.7944,4 4,4 2.206,0 4,-1.794 4,-4 C 12,5.7944 10.206,4 8,4 z" /> --- a/util/FileManagementPanel.py Thu Jun 28 16:42:07 2012 +0200
+++ b/util/FileManagementPanel.py Sun Jul 01 23:20:19 2012 +0200
@@ -268,7 +268,8 @@
for idx, (name, bitmap, help) in enumerate([
("DeleteButton", "remove_element", _("Remove file from left folder")),
("LeftCopyButton", "LeftCopy", _("Copy file from right folder to left")),
- ("RightCopyButton", "RightCopy", _("copy file from left folder to right"))]):
+ ("RightCopyButton", "RightCopy", _("copy file from left folder to right")), + ("EditButton", "edit", _("Edit file"))]): button = wx.lib.buttons.GenBitmapButton(self.Editor,
bitmap=GetBitmap(bitmap),
size=wx.Size(28, 28), style=wx.NO_BORDER)
@@ -311,6 +312,9 @@
self.Controler = controler
+ self.EditableFileExtensions = [] self.SetIcon(GetBitmap("FOLDER"))
@@ -319,6 +323,11 @@
+ def SetEditableFileExtensions(self, extensions): + self.EditableFileExtensions = extensions + if len(self.EditableFileExtensions) > 0: self.ManagedDir.RefreshTree()
self.SystemDir.RefreshTree()
@@ -331,6 +340,10 @@
self.DeleteButton.Enable(os.path.isfile(managed_filepath))
self.LeftCopyButton.Enable(os.path.isfile(system_filepath))
self.RightCopyButton.Enable(os.path.isfile(managed_filepath))
+ if len(self.EditableFileExtensions) > 0: + self.EditButton.Enable( + os.path.isfile(managed_filepath) and + os.path.splitext(managed_filepath)[1] in self.EditableFileExtensions) def OnTreeItemChanged(self, event):
self.RefreshButtonsState()
@@ -352,6 +365,13 @@
self.ManagedDir.RefreshTree()
+ def OnEditButton(self, event): + filepath = self.ManagedDir.GetPath() + if (os.path.isfile(filepath) and + os.path.splitext(filepath)[1] in self.EditableFileExtensions): + self.Controler._OpenView(filepath) def CopyFile(self, src, dst):
src_folder, src_filename = os.path.split(src)