andrej@1511: #!/usr/bin/env python
andrej@1511: # -*- coding: utf-8 -*-
andrej@1511: 
andrej@1511: # This file is part of Beremiz, a Integrated Development Environment for
andrej@1511: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
andrej@1511: #
andrej@1511: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
andrej@1680: # Copyright (C) 2017: Andrey Skvortsov
andrej@1511: #
andrej@1511: # See COPYING file for copyrights details.
andrej@1511: #
andrej@1511: # This program is free software; you can redistribute it and/or
andrej@1511: # modify it under the terms of the GNU General Public License
andrej@1511: # as published by the Free Software Foundation; either version 2
andrej@1511: # of the License, or (at your option) any later version.
andrej@1511: #
andrej@1511: # This program is distributed in the hope that it will be useful,
andrej@1511: # but WITHOUT ANY WARRANTY; without even the implied warranty of
andrej@1511: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
andrej@1511: # GNU General Public License for more details.
andrej@1511: #
andrej@1511: # You should have received a copy of the GNU General Public License
andrej@1511: # along with this program; if not, write to the Free Software
andrej@1511: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
andrej@1511: 
andrej@1853: 
andrej@1853: from __future__ import absolute_import
andrej@1732: import os
andrej@1732: import shutil
laurent@371: 
andrej@1832: import wx
andrej@1853: from svgui.pyjs import translate
laurent@371: 
andrej@1680: import util.paths as paths
Edouard@728: from POULibrary import POULibrary
Edouard@737: from docutil import open_svg
Laurent@1061: from py_ext import PythonFileCTNMixin
laurent@371: 
andrej@1736: 
Edouard@728: class SVGUILibrary(POULibrary):
Edouard@728:     def GetLibraryPath(self):
andrej@1730:         return paths.AbsNeighbourFile(__file__, "pous.xml")
Edouard@728: 
andrej@1736: 
Laurent@1061: class SVGUI(PythonFileCTNMixin):
laurent@371: 
Edouard@717:     ConfNodeMethods = [
andrej@1739:         {
andrej@1739:             "bitmap":    "ImportSVG",
andrej@1739:             "name":    _("Import SVG"),
andrej@1739:             "tooltip": _("Import SVG"),
andrej@1739:             "method":   "_ImportSVG"
andrej@1739:         },
andrej@1739:         {
andrej@1739:             "bitmap":    "ImportSVG",  # should be something different
andrej@1739:             "name":    _("Inkscape"),
andrej@1739:             "tooltip": _("Create HMI"),
andrej@1739:             "method":   "_StartInkscape"
andrej@1739:         },
laurent@371:     ]
laurent@371: 
Laurent@1061:     def _getSVGpath(self, project_path=None):
Laurent@1061:         if project_path is None:
Laurent@1061:             project_path = self.CTNPath()
Laurent@1061:         # define name for SVG file containing gui layout
Laurent@1061:         return os.path.join(project_path, "gui.svg")
laurent@371: 
laurent@371:     def _getSVGUIserverpath(self):
andrej@1680:         return paths.AbsNeighbourFile(__file__, "svgui_server.py")
laurent@371: 
Laurent@1061:     def OnCTNSave(self, from_project_path=None):
Laurent@1061:         if from_project_path is not None:
Laurent@1061:             shutil.copyfile(self._getSVGpath(from_project_path),
Laurent@1061:                             self._getSVGpath())
Laurent@1061:         return PythonFileCTNMixin.OnCTNSave(self, from_project_path)
Laurent@1061: 
Edouard@718:     def CTNGenerate_C(self, buildpath, locations):
laurent@371:         """
andrej@1730:         Return C code generated by iec2c compiler
laurent@371:         when _generate_softPLC have been called
laurent@371:         @param locations: ignored
laurent@371:         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
laurent@371:         """
andrej@1730: 
laurent@371:         current_location = self.GetCurrentLocation()
laurent@371:         # define a unique name for the generated C file
andrej@1833:         location_str = "_".join(map(str, current_location))
andrej@1730: 
laurent@371:         res = ([], "", False)
andrej@1730: 
andrej@1742:         svgfile = self._getSVGpath()
laurent@371:         if os.path.exists(svgfile):
andrej@2442:             res += (("gui.svg", open(svgfile, "rb")),)
laurent@371: 
laurent@371:         svguiserverfile = open(self._getSVGUIserverpath(), 'r')
laurent@371:         svguiservercode = svguiserverfile.read()
laurent@371:         svguiserverfile.close()
laurent@371: 
laurent@371:         svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
laurent@371:         svguilibfile = open(svguilibpath, 'w')
andrej@1742:         fpath = paths.AbsDir(__file__)
andrej@1680:         svguilibfile.write(translate(os.path.join(fpath, "pyjs", "lib", "sys.py"), "sys"))
andrej@1680:         svguilibfile.write(open(os.path.join(fpath, "pyjs", "lib", "_pyjs.js"), 'r').read())
andrej@1680:         svguilibfile.write(translate(os.path.join(fpath, "pyjs", "lib", "pyjslib.py"), "pyjslib"))
andrej@1680:         svguilibfile.write(translate(os.path.join(fpath, "svguilib.py"), "svguilib"))
laurent@371:         svguilibfile.write("pyjslib();\nsvguilib();\n")
andrej@1680:         svguilibfile.write(open(os.path.join(fpath, "pyjs", "lib", "json.js"), 'r').read())
andrej@1680:         svguilibfile.write(open(os.path.join(fpath, "livesvg.js"), 'r').read())
laurent@371:         svguilibfile.close()
laurent@371:         jsmodules = {"LiveSVGPage": "svguilib.js"}
andrej@2442:         res += (("svguilib.js", open(svguilibpath, "rb")),)
andrej@1730: 
andrej@1734:         runtimefile_path = os.path.join(buildpath, "runtime_%s.py" % location_str)
laurent@371:         runtimefile = open(runtimefile_path, 'w')
andrej@1739:         runtimefile.write(svguiservercode % {"svgfile": "gui.svg"})
laurent@371:         runtimefile.write("""
Edouard@1014: def _runtime_%(location)s_start():
laurent@371:     website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
andrej@1730: 
Edouard@1014: def _runtime_%(location)s_stop():
laurent@371:     website.UnLoadHMI()
andrej@1730: 
andrej@1776:         """ % {"location": location_str,
andrej@1776:                "svgui_class": "SVGUI_HMI",
andrej@1776:                "jsmodules": str(jsmodules)})
laurent@371:         runtimefile.close()
andrej@1730: 
andrej@2442:         res += (("runtime_%s.py" % location_str, open(runtimefile_path, "rb")),)
andrej@1730: 
laurent@371:         return res
laurent@371: 
laurent@371:     def _ImportSVG(self):
Edouard@718:         dialog = wx.FileDialog(self.GetCTRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "",  _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
laurent@371:         if dialog.ShowModal() == wx.ID_OK:
laurent@371:             svgpath = dialog.GetPath()
laurent@371:             if os.path.isfile(svgpath):
laurent@371:                 shutil.copy(svgpath, self._getSVGpath())
laurent@371:             else:
andrej@1734:                 self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n") % svgpath)
andrej@1730:         dialog.Destroy()
laurent@371: 
laurent@371:     def _StartInkscape(self):
laurent@371:         svgfile = self._getSVGpath()
greg@427:         open_inkscape = True
Edouard@718:         if not self.GetCTRoot().CheckProjectPathPerm():
Edouard@718:             dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
greg@427:                                       _("You don't have write permissions.\nOpen Inkscape anyway ?"),
greg@427:                                       _("Open Inkscape"),
andrej@1745:                                       wx.YES_NO | wx.ICON_QUESTION)
greg@427:             open_inkscape = dialog.ShowModal() == wx.ID_YES
greg@427:             dialog.Destroy()
greg@427:         if open_inkscape:
greg@427:             if not os.path.isfile(svgfile):
greg@427:                 svgfile = None
greg@427:             open_svg(svgfile)