Metadata-Version: 2.4
Name: svgsynoptic2
Version: 4.4.0
Summary: Widget for displaying a SVG synoptic.
Author-email: Johan Forsberg <kits-sw@maxiv.lu.se>
License:                    GNU LESSER GENERAL PUBLIC LICENSE
                               Version 3, 29 June 2007
        
         Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
         Everyone is permitted to copy and distribute verbatim copies
         of this license document, but changing it is not allowed.
        
        
          This version of the GNU Lesser General Public License incorporates
        the terms and conditions of version 3 of the GNU General Public
        License, supplemented by the additional permissions listed below.
        
          0. Additional Definitions.
        
          As used herein, "this License" refers to version 3 of the GNU Lesser
        General Public License, and the "GNU GPL" refers to version 3 of the GNU
        General Public License.
        
          "The Library" refers to a covered work governed by this License,
        other than an Application or a Combined Work as defined below.
        
          An "Application" is any work that makes use of an interface provided
        by the Library, but which is not otherwise based on the Library.
        Defining a subclass of a class defined by the Library is deemed a mode
        of using an interface provided by the Library.
        
          A "Combined Work" is a work produced by combining or linking an
        Application with the Library.  The particular version of the Library
        with which the Combined Work was made is also called the "Linked
        Version".
        
          The "Minimal Corresponding Source" for a Combined Work means the
        Corresponding Source for the Combined Work, excluding any source code
        for portions of the Combined Work that, considered in isolation, are
        based on the Application, and not on the Linked Version.
        
          The "Corresponding Application Code" for a Combined Work means the
        object code and/or source code for the Application, including any data
        and utility programs needed for reproducing the Combined Work from the
        Application, but excluding the System Libraries of the Combined Work.
        
          1. Exception to Section 3 of the GNU GPL.
        
          You may convey a covered work under sections 3 and 4 of this License
        without being bound by section 3 of the GNU GPL.
        
          2. Conveying Modified Versions.
        
          If you modify a copy of the Library, and, in your modifications, a
        facility refers to a function or data to be supplied by an Application
        that uses the facility (other than as an argument passed when the
        facility is invoked), then you may convey a copy of the modified
        version:
        
           a) under this License, provided that you make a good faith effort to
           ensure that, in the event an Application does not supply the
           function or data, the facility still operates, and performs
           whatever part of its purpose remains meaningful, or
        
           b) under the GNU GPL, with none of the additional permissions of
           this License applicable to that copy.
        
          3. Object Code Incorporating Material from Library Header Files.
        
          The object code form of an Application may incorporate material from
        a header file that is part of the Library.  You may convey such object
        code under terms of your choice, provided that, if the incorporated
        material is not limited to numerical parameters, data structure
        layouts and accessors, or small macros, inline functions and templates
        (ten or fewer lines in length), you do both of the following:
        
           a) Give prominent notice with each copy of the object code that the
           Library is used in it and that the Library and its use are
           covered by this License.
        
           b) Accompany the object code with a copy of the GNU GPL and this license
           document.
        
          4. Combined Works.
        
          You may convey a Combined Work under terms of your choice that,
        taken together, effectively do not restrict modification of the
        portions of the Library contained in the Combined Work and reverse
        engineering for debugging such modifications, if you also do each of
        the following:
        
           a) Give prominent notice with each copy of the Combined Work that
           the Library is used in it and that the Library and its use are
           covered by this License.
        
           b) Accompany the Combined Work with a copy of the GNU GPL and this license
           document.
        
           c) For a Combined Work that displays copyright notices during
           execution, include the copyright notice for the Library among
           these notices, as well as a reference directing the user to the
           copies of the GNU GPL and this license document.
        
           d) Do one of the following:
        
               0) Convey the Minimal Corresponding Source under the terms of this
               License, and the Corresponding Application Code in a form
               suitable for, and under terms that permit, the user to
               recombine or relink the Application with a modified version of
               the Linked Version to produce a modified Combined Work, in the
               manner specified by section 6 of the GNU GPL for conveying
               Corresponding Source.
        
               1) Use a suitable shared library mechanism for linking with the
               Library.  A suitable mechanism is one that (a) uses at run time
               a copy of the Library already present on the user's computer
               system, and (b) will operate properly with a modified version
               of the Library that is interface-compatible with the Linked
               Version.
        
           e) Provide Installation Information, but only if you would otherwise
           be required to provide such information under section 6 of the
           GNU GPL, and only to the extent that such information is
           necessary to install and execute a modified version of the
           Combined Work produced by recombining or relinking the
           Application with a modified version of the Linked Version. (If
           you use option 4d0, the Installation Information must accompany
           the Minimal Corresponding Source and Corresponding Application
           Code. If you use option 4d1, you must provide the Installation
           Information in the manner specified by section 6 of the GNU GPL
           for conveying Corresponding Source.)
        
          5. Combined Libraries.
        
          You may place library facilities that are a work based on the
        Library side by side in a single library together with other library
        facilities that are not Applications and are not covered by this
        License, and convey such a combined library under terms of your
        choice, if you do both of the following:
        
           a) Accompany the combined library with a copy of the same work based
           on the Library, uncombined with any other library facilities,
           conveyed under the terms of this License.
        
           b) Give prominent notice with the combined library that part of it
           is a work based on the Library, and explaining where to find the
           accompanying uncombined form of the same work.
        
          6. Revised Versions of the GNU Lesser General Public License.
        
          The Free Software Foundation may publish revised and/or new versions
        of the GNU Lesser General Public License from time to time. Such new
        versions will be similar in spirit to the present version, but may
        differ in detail to address new problems or concerns.
        
          Each version is given a distinguishing version number. If the
        Library as you received it specifies that a certain numbered version
        of the GNU Lesser General Public License "or any later version"
        applies to it, you have the option of following the terms and
        conditions either of that published version or of any later version
        published by the Free Software Foundation. If the Library as you
        received it does not specify a version number of the GNU Lesser
        General Public License, you may choose any version of the GNU Lesser
        General Public License ever published by the Free Software Foundation.
        
          If the Library as you received it specifies that a proxy can decide
        whether future versions of the GNU Lesser General Public License shall
        apply, that proxy's public statement of acceptance of any version is
        permanent authorization for you to choose that version for the
        Library.
        
Project-URL: Source, https://gitlab.com/MaxIV/lib-maxiv-svgsynoptic
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: pytango>=9.2.1
Requires-Dist: taurus>=4.5
Requires-Dist: pyqtwebengine
Dynamic: license-file

# SVG synoptic #


## Important ##

There has been some refactoring of this library since version 2.1. The
changes are mostly under the hood, but there is one change that needs
to be done to existing synoptics to work with later versions: a
"backend" must be loaded. At the moment, only the Qt backend is
usable, which works exactly like it used to, it's just separated out
and needs this line to be loaded from the HTML, e.g.:

    <script src="js/qt_backend.js"></script>

See the examples if this is unclear.


## Installation ##

Like any python package. E.g. to install in a virtualenv:

    $ pip install svgsynoptic2

You can also use conda:

    $ conda install -c conda-forge svgsynoptic2


## Examples ##

    $ cd examples
    $ python simple_example
    $ python tango_example

## Introduction ##

The SVG synoptic enables an intuitive way of interaction with a control system, by displaying a graphical representation (e.g. a drawing) of the physical and/or logical structure, and allowing various information and interactions to be tied in to this representation. The user can interact by panning/zooming (if the drawing is complex enough to require this) and "hovering"/clicking elements to bring up informations or launch more specific panels.

The library is developed with the TANGO control system in mind, and has a Qt widget implementation based on Taurus. It should however be possible to adapt it to other systems as well.

A SVG synoptic consists mainly of an SVG format file, that can be produced in any way. There are various software packages that can be used (inkscape is a good FOSS alternative) that can be used by non-programmers, but since SVG is an open, XML based format, it is possible to generate the files programmatically. 

By annotating elements in the SVG file, they can be connected to control system items, displaying e.g. the current on/off state, an alarm, or a numerical value. 

The SVG synoptic can be run as a standalone application or embedded in a Qt application. There is also work underway to make it possible to run as a "web application".


## Usage ##

To make a simple synoptic application, all you need to do is copy the structure of one of the demo applications, create a SVG file of the correct structure, and modify "index.html" to suit your needs. 

### The SVG file ###

This is really the most important part of any synoptic application. It can in principle contain anything that is supported by SVG (caveat: the application uses the PyQt5's QWebEngineView widget to display the SVG. Not all the newest SVG features may be supported.) 

#### Structure ####

The only restriction of the file is that it has to conform to a certain layer structure (the names of the layers matter, except when noted. All layers except the toplevel are optional.):

* *main* (name does not matter, but there needs to be a toplevel layer, containing all the other layers)
  - *symbols* (a "scratch" layer; will not be displayed by the application)
  - *background* (should contain stuff that will always be visible)
  - *Vacuum* (can be any name, can be show/hidden by the user)
  - *Stuff* (same)
  - ...

Further, each of the layers can optionally have sublayers of the names "zoom0", "zoom1", and so on. These will be used at different detail levels depending on user navigation. Things drawn outside of these sublayers are shown in every zoom level of the layer.

- Stuff
  + zoom0  (a general overview, that is shown when the app is started)
  + zoom1  (more detailed view of the parts)
  + zoom3  (super detailed view with individual equipment, etc)

The scales where the different zoom levels will become active can be tweaked through a configuration option, see below.

#### Models ####

In order to connect your drawing to TANGO, you need to insert references to devices or attributes. This is done through the "desc" SVG element which can be inserted into most SVG elements. 

A desc element containing a text like "model=sys/tg_test/1" will connect the container element to the test device. This means that the element will be colored ("fill") according to the State of the device, and also that left clicking the element will by default open the device using a Taurus device panel. The click behavior can be overridden by python code.

Adding an attribute as a model (e.g. "model=sys/tg_test/1/ampli") to a text element will instead cause it to display the current value of the element. If the "State" attribute is given, the fill color will also be set accordingly.

It's also possible to name a part of the drawing as a "section" by setting a desc like "section=MySection". This part will then become clickable, causing the view to zoom in on it.

##### Models in separate json file #####
It is possible to store the actual tango models in a separate json config file, and have aliases in the SVG file. The aliases must be surrounded by $-signs, for example:

```model=$valve1$```

The config file then needs a line:
 
 ```"valve1" : "bxxx/vac/valve-01"```

The model list is injected into the html-file. In order for this to work the html file needs a placeholder where this should go:

```<script type="text/javascript">/*configplaceholder*/</script>```

Finally, to import the list of models call the setConfig() function of the widget giving the name of the json file. See also the "tango" example.



#### Tips & tricks ####

The SVG format has lots of features that can be useful for a synoptic. There are no particular restrictions to what features can be used, except for what's actually supported by the browser component used. Since it's an evolving standard, some newer features may not be supported by the PyQt5's widgets so it's important to test that before relying on it.

Inkscape is a very powerful tool and it's worth putting a little time into learning to use it effectively. It has many helpful features that may not be immediately obvious. 

##### Groups #####
It's often practical to group elements together to form more complex shapes. You can set the model on a group as usual. Groups can also be cloned. Note that the State color will only affect parts of the group that do not have inline fill styles (see "Troubleshooting" below). This effect can be used to e.g. make an icon that contains a lamp that is colored according to state. 

##### Clones #####
Usually a synoptic will contain a few different symbols that are reused several times, e.g. vacuum valves, pumps, etc. This can be quite tedious since you have to copy-paste each symbol everywhere every time you change its appearance. The "clone" functionality in inkscape allows you to create one "master" instance of each symbol (element or group) and then create clones of it to use in the drawing. 
    - Clones can't be edited, but changes made to the original are reflected by all clones. If the original is a group, you can edit it by double clicking it. It will then be entered (like a layer) and you can edit the contents.
    - The model can be set individually on each clone. 
    - The original can be kept in the "symbols" layer (see above) so it's not visible.
    - To check that your element is a clone, select it and check the bottom of the window, where it should say "Clone of: ...". 
    - Clones can safely be duplicated (Ctrl+d) into new clones. 
    - Avoid clones of clones, as this can cause unexpected behaviors.

##### Alignment #####
Inkscape has lots of tools that make it easier to make drawings neat. The "snap" feature helps a lot with placement of elements, especially together with the "grid" and "guide" features. The "Align and distribute" panel also helps with spacing and lining up of elements. Holding the Control key when moving or rotating things is also helpful. Check inkscape's documentation for more information.

##### Scaling #####
Be careful about scaling elements, as it can easily make things look "off". This is especially true about text, and rotated elements. Holding down Control while scaling makes sure the width/height ratio is kept intact. Also, inkscape can be configured to keep line thickness constant when scaling. If you mess up the scaling of some object, it can be reset from inkscape through "Object"->"Transform..."->"Matrix", by checking the "Edit current matrix" box and clearing it. However this will also reset the position of your element, so if it's a clone it will be positioned on the original.


#### Troubleshooting ####

A generally useful tool to check issues is the "XML Editor" in inkscape. It can be used to inspect the resulting SVG file directly.
Another useful tool, it's a Web Inspector accessible via the F12 key in Synoptic. 

##### items do not display state colors correctly #####

First, check that your model definition is correct. Then, check that the "fill" style is not set in the element's "style" attribute. Unsetting fill can be done by clicking the "?" button in the "Fill and Stroke" dialog. If it's a group, also check the elements in the group. An object with no inline fill should appear completely black in Inkscape.

The synoptic uses CSS classes to set the fill style, and that can be overridden by "inline" styles directly on the element. Inkscape uses inline styles to set fill, so it's quite likely to be an issue. 


## The HTML file ##

Not too much to do in this file, but there are some settings for the synoptic that can be tweaked, and some functionality ("plugins") of the synoptic selectively loaded. Have a look at the HTML files in the examples to see how this is done. 

Also, any background or foreground images, styling etc, should be done here. If more complex styling is required, separate CSS files may be loaded from here. Note that SVG can also be styled by CSS.

### Configuration ###

The synoptic library takes an optional "config" argument, that can be used to tweak the default settings. It is a plain JavaScript object, e.g:

    const config = {
        windowSize: {width: 400, height: 600},
        view: {zoomSteps: [1]},
    };
    loadSVG("${path}/example.svg", container, config);

#### Zoom levels ####

By default there is assumed to be three zoom levels, at 1, 10 and 100 times each. This means that the first level (0) is only shown when the synoptic is maximally zoomed out, the next (1) is shown until it's zoomed in to 10 times enlargement, and finally, the last level (2) is shown up to a zoom factor 100, which is also the maximum allowed zoom.

Let's say you have two zoom levels, and you want to switch between them at zoom factor 2 and allow zooming up to a factor 10. The config should then look like this:

    view: {zoomSteps: [2, 10]}},

#### Layer visibility ####

You may prefer some layers to be hidden at application startup, e.g. stuff that is normally not interesting to see. This can be done with configuration:

    layers: {hidden: ["stuff"]},
    
Beware that the strings given in the "hidden" list need to be the *id* of the layers, not the *label* which is seen in the synoptic application. Normally when creating a layer in Inkscape, it gets an automatic id like "layer4". You may need to inspect the SVG file in order to find the id of the "g" element corresponding to the layer. Since these ids are usually arbitrary anyway, it may be a good idea to change them to correspond to the label, so that the configuration is more easily understood. Just make sure the layer ids are unique.


## Issues and limitations ##

Some things to be aware of:

* Currently, having SVG "transform" attributes on a *layer* causes all sorts of issues where models are not recognized as in view. Make sure the "transform" attribute is not set on any of your layers (most easily done through the XML editor in inkscape). It's quite easy to add this by mistake in inkscape, by selecting all elements in a layer and moving them at the same time. This will hopefully be handled better by a future version of SVG synoptic.

## Popup module ##

The `svgsynoptic2.popup` module includes some classes that can be useful in a synoptic.

The following are helper classes that shouldn't be used directly, but you can inherit from them:

* `CommandsWidget`: a widget that shows a number of Command buttons - base class for `CommandsWidgetPopup`
* `CommandsWidgetPopup`: a popup variant of `CommandsWidget`. It moves the mouse on start and it closes on unfocus, after successful command
  or after 10 seconds. On show it hides irrelevant buttons (based on the state).
  This class shouldn't be used directly. Define your own class with `commands` as class attribute, with a list of (command, state).
  If "state" matches the current state, the command is hidden. See `ValvePopup` as example.

The following can be used directly:

* `ValvePopup`: a command widget popup with `Open` and `Close` buttons. Only the relevant command is shown (`Open` if the state is "close" and reciprocally).
* `PlcResetPopup`: a command widget popup with a single reset button (MAX IV specific).
* `TaurusFormExpanding`: a `TaurusForm` that adapts its size to its children
* `StateComposerWidget`: display all devices from a `StateComposer` tango device server (MAX IV specific)

You can easily write your `CommandsWidgetPopup` variant and takes inspiration from other widgets.
