Giter Site home page Giter Site logo

gaphas's Introduction

Gaphas

Build state Maintainability Test Coverage Docs build state standard-readme compliant Matrix All Contributors

Gaphas is the diagramming widget library for Python.

Gaphas Demo

Gaphas is a library that provides the user interface component (widget) for drawing diagrams. Diagrams can be drawn to screen and then easily exported to a variety of formats, including SVG and PDF. Want to build an app with chart-like diagrams? Then Gaphas is for you! Use this library to build a tree, network, flowchart, or other diagrams.

This library is currently being used by Gaphor for UML drawing, RAFCON for state-machine based robot control, and ASCEND for solving mathematical models.

๐Ÿ“‘ Table of Contents

๐Ÿ“œ Background

Gaphas was built to provide the foundational diagramming portions of Gaphor. Since Gaphor is built on GTK and Cairo, PyGObject provides access to the GUI toolkit and PyCairo to the 2D graphics library. However, there wasn't a project that abstracted these technologies to easily create a diagramming tool. Hence, Gaphas was created as a library to allow others to create a diagramming tool using GTK and Cairo.

Here is how it works:

  • Items (Canvas items) can be added to a Canvas.
  • The Canvas maintains the tree structure (parent-child relationships between items).
  • A constraint solver is used to maintain item constraints and inter-item constraints.
  • The item (and user) should not be bothered with things like bounding-box calculations.
  • Very modular--e.g., handle support could be swapped in and swapped out.
  • Rendering using Cairo.

The main portions of the library include:

  • canvas - The main canvas class (container for Items).
  • items - Objects placed on a Canvas.
  • solver - A constraint solver to define the layout and connection of items.
  • gtkview - A view to be used in GTK applications that interacts with users with tools.
  • painters - The workers used to paint items.
  • tools - Tools are used to handle user events (such as mouse movement and button presses).
  • aspects - Provides an intermediate step between tools and items.

Gaphas contains default implementations for Canvas and Items. There are protocols in place to allow you to make your own canvas.

๐Ÿ’พ Install

To install Gaphas, simply use pip:

$ pip install gaphas

Use of a virtual environment is highly recommended.

Development

To setup a development environment with Linux:

$ sudo apt-get install -y python3-dev python3-gi python3-gi-cairo
    gir1.2-gtk-3.0 libgirepository1.0-dev libcairo2-dev
$ pip install poetry
$ poetry install

๐Ÿ”ฆ Usage

API docs and tutorials can be found on Read the Docs.

โ™ฅ Contributing

Thanks goes to these wonderful people (emoji key):

Arjan Molenaar
Arjan Molenaar

๐Ÿ’ป ๐Ÿ› ๐Ÿ“– ๐Ÿ‘€ ๐Ÿ’ฌ ๐Ÿ”Œ
Dan Yeaw
Dan Yeaw

๐Ÿ’ป โš ๏ธ ๐Ÿ‘€ ๐Ÿ› ๐Ÿ’ฌ ๐Ÿš‡ ๐Ÿ“–
wrobell
wrobell

๐Ÿ’ป โš ๏ธ ๐Ÿ‘€
Jean-Luc Stevens
Jean-Luc Stevens

๐Ÿ’ป ๐Ÿ› ๐Ÿ“–
Franz Steinmetz
Franz Steinmetz

๐Ÿ’ป ๐Ÿ›
Adrian Boguszewski
Adrian Boguszewski

๐Ÿ’ป
Rico Belder
Rico Belder

๐Ÿ› ๐Ÿ‘€
Adam Boduch
Adam Boduch

๐Ÿ›
Janet Jose
Janet Jose

๐Ÿ“–

This project follows the all-contributors specification. Contributions of any kind are welcome!

  1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug. There is a first-timers-only tag for issues that should be ideal for people who are not very familiar with the codebase yet.
  2. Fork the repository on GitHub to start making your changes to the main branch (or branch off of it).
  3. Write a test which shows that the bug was fixed or that the feature works as expected.
  4. Send a pull request and bug the maintainers until it gets merged and published. ๐Ÿ˜„

See the contributing file!

ยฉ License

Copyright ยฉ Arjan Molenaar and Dan Yeaw

Licensed under the Apache License 2.0.

Summary: You can do what you like with Gaphas, as long as you include the required notices. This permissive license contains a patent license from the contributors of the code.

gaphas's People

Contributors

adrianboguszewski avatar allcontributors[bot] avatar amolenaar avatar azure-pipelines[bot] avatar danyeaw avatar dependabot[bot] avatar franzlst avatar janettech avatar jlstevens avatar kianmeng avatar pre-commit-ci[bot] avatar sourcery-ai-bot avatar sourcery-ai[bot] avatar step-security-bot avatar wrobell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gaphas's Issues

test_tool_zoom.py::test_zoom_should_center_around_mouse_cursor failing in i686 chroot

Describe the bug
test_tool_zoom.py::test_zoom_should_center_around_mouse_cursor fails when run with i686 packages on an x86_64 chroot in Void Linux:

============================= test session starts ==============================
platform linux -- Python 3.10.4, pytest-7.1.2, pluggy-1.0.0
rootdir: /builddir/gaphas-3.6.0, configfile: pyproject.toml, testpaths: tests
collected 192 items

tests/test_canvas.py .........                                           [  4%]
tests/test_connections.py .......                                        [  8%]
tests/test_connector.py ...........                                      [ 14%]
tests/test_constraints.py ........                                       [ 18%]
tests/test_decorators.py ..........                                      [ 23%]
tests/test_element.py .........                                          [ 28%]
tests/test_freehand.py ..                                                [ 29%]
tests/test_geometry.py ...............                                   [ 36%]
tests/test_guide.py ......                                               [ 40%]
tests/test_handle.py .                                                   [ 40%]
tests/test_handle_move.py ....                                           [ 42%]
tests/test_item.py ....                                                  [ 44%]
tests/test_line.py .                                                     [ 45%]
tests/test_matrix.py .                                                   [ 45%]
tests/test_move.py .                                                     [ 46%]
tests/test_position.py ...............                                   [ 54%]
tests/test_quadtree.py .......                                           [ 57%]
tests/test_segment.py ...................                                [ 67%]
tests/test_solver.py ......                                              [ 70%]
tests/test_solver_constraint.py ......                                   [ 73%]
tests/test_solver_variable.py ............                               [ 80%]
tests/test_tool_hover.py ..                                              [ 81%]
tests/test_tool_item.py .........                                        [ 85%]
tests/test_tool_placement.py ..                                          [ 86%]
tests/test_tool_scroll.py ..                                             [ 88%]
tests/test_tool_zoom.py .....F..                                         [ 92%]
tests/test_tree.py .....                                                 [ 94%]
tests/test_view.py ..........                                            [100%]

=================================== FAILURES ===================================
_________________ test_zoom_should_center_around_mouse_cursor __________________

zoom_data = <gaphas.tool.zoom.Zoom object at 0xf4a495c8>
view = <gtkview.GtkView object at 0xf4a4c768 (GaphasView at 0x584cb988)>

    def test_zoom_should_center_around_mouse_cursor(zoom_data, view):
        tool = zoom_tool(view)
        view.add_controller(tool)
        zoom_data.x0 = 100
        zoom_data.y0 = 50
    
        on_scale_changed(tool, 1.2, zoom_data)
    
>       assert view.matrix[4] == -20.0
E       assert -19.999999999999996 == -20.0

tests/test_tool_zoom.py:84: AssertionError
=========================== short test summary info ============================
FAILED tests/test_tool_zoom.py::test_zoom_should_center_around_mouse_cursor

To Reproduce
Steps to reproduce the behavior:

  1. Run tests for gaphas in i686 chroot on x86_64 Void Linux host.

Expected behavior
Tests should pass.

OS

  • Linux (Please put in notes the specific distro)
  • MacOS
  • Windows

NOTES:

Version
Version of Gaphas: 3.6.0
Distro: Void Linux

Additional context
I've opened a PR to add this package to the Void Linux repo here: void-linux/void-packages#37270

The CI run fails for the i686 build here: https://github.com/void-linux/void-packages/runs/6576821953?check_suite_focus=true

Attribute Error While Dragging Segments

Describe the bug
A reproducible bug, but takes work to make it happen.

Traceback (most recent call last):
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/segment.py", line 213, in on_drag_update
    segment_state.moving.move((x + offset_x, y + offset_y))
AttributeError: 'NoneType' object has no attribute 'move'

To Reproduce
Steps to reproduce the behavior:

  1. Create two classes
  2. Create a generalization between them
  3. Set the relationship to Rectilinear
  4. Drag the relationship around, create segments, and connect and disconnect the ends.

Expected behavior
No AttributeError

Screenshots
If applicable, add screenshots to help explain your problem.

OS

  • Linux (Please put in notes the specific distro)
  • MacOS
  • Windows

NOTES:

Version
Version of Gaphas: 3.0.1

Additional context
Maybe we just need to check for moving?

if segment_state.moving: 
    segment_state.moving.move((x + offset_x, y + offset_y))

Update from LGPL 2.0 to 2.1 (or Apache)

This issue goes along with gaphor/gaphor#61. GitHub supports displaying the license on the repository overview. It only supports licenses from choose a license, which includes the LGPL 2.1, but not 2.0.

The main changes are rewording Library to Lesser, and adding another option for using a shared library mechanism:
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.

We are also considering moving to Apache instead of the LGPL, the
summary of differences are:

  • LGPL requires that derivative works must be licensed using the LGPL as well
  • LGPL requires that source code must be disclosed with distribution, Apache does not
  • Apache requires an express grant of patent rights for contributions, LGPL v2.1 does not (v3 does)
  • Apache is more compatible, so we could include MIT or BSD software in our project, but we need to ensure that there is no other LGPL libraries that exist within the current software.

Any other thoughts on upgrading to a newer version of the LGPL or to Apache?

Version 2.1 API Changed for draw method

In #73 we removed the draw_all property from the draw method, which version 1.2.0 of Gaphor depends on. This Gaphor issue is gaphor/gaphor#359.

I recommend we release a new version that is backwards compatible, and then release version 3.0 with a change of the API if we think this cleanup is needed.

Canvas.get_connected_items is too slow

(original: http://gaphor.devjavu.com/ticket/135)

Canvas.get_connected_items method iterates all items referenced by canvas. this is very slow approach.

for example, load uml2.gaphor file from gaphor project. it takes several seconds (10-15s on my machine) to connect two classes with asssociation (this method is used to find relationships, see bug #134 for description how it works).

above affects Canvas.remove_connections_to_item method as it uses get_connected_items method.

Orthogonal Activity Edges

Setting an activity edge style results in the following tracebacks:

Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/canvas.py", line 471, in update_now
self.update_constraints(dirty_matrix_items)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/canvas.py", line 570, in update_constraints
self._solver.solve()
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/solver.py", line 615, in solve
c.solve_for(wvar)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/constraint.py", line 492, in solve_for
self._solve()
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/constraint.py", line 520, in _solve
_update(px, x)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/constraint.py", line 46, in _update
variable.value = value
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/canvas.py", line 742, in _set_value
self._callback(value)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/canvas.py", line 786, in _on_change_x
self._point[0].value, self._point[1].value = item.canvas.get_matrix_c2i(item).transform_point(value, self._py)
File "", line 2, in set_value
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/state.py", line 66, in wrapper
return func(_args, *_kwargs)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/solver.py", line 99, in set_value
self.dirty()
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/solver.py", line 94, in dirty
solver.request_resolve(self)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/solver.py", line 422, in request_resolve
raise JuggleError, 'Variable juggling detected, constraint %s' % c
JuggleError: Variable juggling detected, constraint <gaphas.constraint.EqualsConstraint object at 0xa29930c>
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/decorators.py", line 104, in async_wrapper
func(_args, *_kwargs)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/canvas.py", line 404, in update
self.update_now()
File "/usr/local/lib/python2.6/dist-packages/gaphor-0.14.0-py2.6.egg/gaphor/UML/diagram.py", line 42, in update_now
super(DiagramCanvas, self).update_now()
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/decorators.py", line 140, in wrapper
return func(_args, *_kwargs)
File "/usr/local/lib/python2.6/dist-packages/gaphas-0.4.0-py2.6.egg/gaphas/canvas.py", line 504, in update_now
'dirty: %s; matrix: %s' % (self._dirty_items, self._dirty_matrix_items)
AssertionError: dirty: set([<gaphor.diagram.flow.FlowItem object at 0xa24f42c>]); matrix: set([])

Is gaphas accepting new contributions and pull requests?

First, I wish to thank you for your work on gaphas!

Gaphas has been a real delight to use. The code is of excellent quality, very readable and well documented. I love that gaphas has minimal dependencies, is written in pure Python and successfully abstracts away the more painful parts of using a gtk.DrawingArea as a canvas. Gaphas is quite wonderful, thank you!

I've been working on a prototype project using gaphas to implement something like the Blender node editor. This project is currently in a private repository but I hope to make it public very soon.

My main concern with gaphas is that the last public commit is from July 2012. Is development still active? Are you accepting pull requests? While learning gaphas, I have made several improvements that I would like to contribute back. Some suggestions that I would be happy to submit as a series of pull requests:

  • Multiple typo fixes.
  • Deletion of trailing whitespace.
  • Possible addition of a .gitignore to the gaphas repository.
  • Deletion of code that has been commented out (only a few instances of this).
  • Wrapping docstrings to 80 characters (mostly good already, but a few places could do with better wrapping).
  • A few other more technical ideas if you are interested!

Please do tell me if you are interested in accepting these sorts of PRs!

Scrolling on Wayland is awkward

Describe the bug

It scrolls from one end to the other end of the canvas. Smooth scrolling is not working as one would expect.

Get rid of global state dispatcher

Is your feature request related to a problem? Please describe.

The global state dispatcher should go. It's hard for e.g. Gaphor to keep track of state changes w.r.t. the window the user is working in. Some workarounds had to be made

Describe the solution you'd like

I wonder if we need this, once the item hierarchy has been extracted from Canvas (#113).

Missing reference to minimum size constraints in Element

In cdf08df, minimum size constraints for Elements were introduced and stored in self._c_min_w and self._c_min_w. In 2ca1e2e, those two references were removed. As a consequence, those constraints can no longer be accessed directly, but need to be searched for in the list of all constraints self._constraints. So the latest 0.7.2 release contains the references, but no longer the latest master version.

Is there are reason for this or can those references be added again?

Cassowary solver

Is your feature request related to a problem?

Gaphor is using its own constraint solver. The solver is quite simple and raises JuggleError if not all constraints can be solved.

Describe the solution you'd like

Instead of using our own, we could leverage the work of others. I'm thinking about a Cassowary solver.

Esp. the syntax of the Cassowary project is close to what we already do. It would be nice, though if we can register a callback when a variable has changed after the constraint system has stabilized.

Describe alternatives you've considered

I'm not aware of any other constraint solver that can be used to resolve UI constraints. Suggestions are welcome :).

Other information

If we combine this with something like CCSS (Constraint CSS, we'd probably define a function for this) we should be able to get auto-layouting for free.

AttributeError When Exporting to SVG in Demo

When exporting to svg, the example demo is causing the following AttributeError:

Traceback (most recent call last):
  File "demo.py", line 286, in on_clicked
    svgview.paint(cr)
AttributeError: 'View' object has no attribute 'paint'

Steps to reproduce:

  1. python examples/demo.py
  2. Click on the Write demo.svg button
  3. See AttributeError

Comments on the Gaphas documentation

Hello Dan,

As discussed earlier, here are my review comments on Gaphas docs. I hope you find them useful.
If you find anything that is not clear, please do ask. Also, ignore if I did any mistakes.

The latter part of my document you will find just the grammatical correction on the content. I hope you find the corrections.

Thanks!
Janet
Gaphas.docx

Replace use of events by Gestures

Gestures are a new thing, landing in GTK4. It's available in GTK3 already.

Gestures should allow for more intuitive interactions, such as zoom by pinching your fingers on the trackpad.

I changed Gaphor to use event controllers (gaphor/gaphor#439). If we want to do it properly in Gaphas, it'll introduce some breaking changes.

These are some ideas and findings.

  • Event Controllers work a lot like Gaphas' Tools do ๐Ÿ‘
  • Can event grabbing can be done via the event controller? Event controllers (gestures) can, it seems, but will that also work well with Gaphas?
  • Find out how deal with drawing that happens from the tools, e.g. rubberband tool.
  • In the ideal scenario, we no longer have to register the tools on the view.

References:

Seems that the requirement for the gaphas package is not correct

To Reproduce
I just followed the described installation steps for Python:

pip install gaphor
gaphor

Expected behavior
I ended up having gaphas 3.8.3:

pip3 install gaphas
Requirement already satisfied: gaphas in /home/jf/Desktop/SW/venv_graphor/lib/python3.8/site-packages (3.8.3)
Requirement already satisfied: pycairo<2.0.0,>=1.20.0 in /home/jf/Desktop/SW/venv_graphor/lib/python3.8/site-packages (from gaphas) (1.26.0)
Requirement already satisfied: PyGObject<4.0.0,>=3.38.0 in /home/jf/Desktop/SW/venv_graphor/lib/python3.8/site-packages (from gaphas) (3.46.0)

Then, when running gaphor I got the following error:

  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/jf/Desktop/SW/venv_graphor/lib/python3.8/site-packages/gaphor/plugins/diagramexport/__init__.py", line 13, in <module>
    from gaphor.diagram.painter import ItemPainter
  File "/home/jf/Desktop/SW/venv_graphor/lib/python3.8/site-packages/gaphor/diagram/painter.py", line 16, in <module>
    from gaphor.diagram.selection import Selection
  File "/home/jf/Desktop/SW/venv_graphor/lib/python3.8/site-packages/gaphor/diagram/selection.py", line 4, in <module>
    from gaphas.view.selection import Selection as _Selection
ModuleNotFoundError: No module named 'gaphas.view.selection'

Then, I tried to get an older version of gaphas and installed the oldest satisfying the requirement: 3.1.0 (gaphor 2.5.1 has requirement gaphas<4.0.0,>=3.1.0)

pip3 install gaphas==3.1.0

Now it seems that gaphor is working. I haven't played with it but at least it launches.

OS

  • Linux (Ubuntu 18.04)

NOTES:

Version
Version of Gaphas: 3.8.0

Enhancement: Underscores in static attributes.

This would really classify as an aesthetic improvement if even possible but underscores in static class attributes don't display so well. The underscore becomes part of the underline that indicates the static attribute. Maybe the attribute label could be "bumped up" slightly if there is an underscore?

Wrong access to scroll event

The scroll event in on_scoll needs to be accessed correctly:

  • event.x => event.get_coords()[1]
  • event.y => event.get_coords()[2]
  • event.direction => event.get_scroll_direction()[1]

Fix comparison between Position and tuple

Finally fix:

Traceback (most recent call last):
  File "/home/arjan/Development/gaphor/.venv/lib/python3.10/site-packages/gaphas/tool/hover.py", line 24, in on_motion
    view.selection.hovered_item = find_item_at_point(view, (x, y))
  File "/home/arjan/Development/gaphor/.venv/lib/python3.10/site-packages/gaphas/tool/hover.py", line 29, in find_item_at_point
    return item or item_at_point(view, pos)
  File "/home/arjan/Development/gaphor/.venv/lib/python3.10/site-packages/gaphas/aspect/handlemove.py", line 180, in item_at_point
    item_distance = item.point(ix, iy)
  File "/home/arjan/Development/gaphor/gaphor/UML/classes/association.py", line 176, in point
    super().point(x, y), self._head_end.point(x, y), self._tail_end.point(x, y)
  File "/home/arjan/Development/gaphor/gaphor/diagram/presentation.py", line 241, in point
    d0 = super().point(x, y)
  File "/home/arjan/Development/gaphor/.venv/lib/python3.10/site-packages/gaphas/item.py", line 401, in point
    distance, _point = min(
TypeError: '<' not supported between instances of 'tuple' and 'Position'

NOTES:

Version
Version of Gaphas: 3.2.0

Additional context
Add any other context about the problem here.

JuggleError When Trying to Modify Gaphor Diagram

Describe the bug
JuggleError when trying to modify a certain diagram in Gaphor.

Traceback (most recent call last):
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/decorators.py", line 133, in async_wrapper
    func(*args, **kwargs)
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/view/gtkview.py", line 310, in update
    model.update_now(dirty_items, dirty_matrix_items)
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/decorators.py", line 163, in wrapper
    return func(*args, **kwargs)
  File "/home/dan/Projects/gaphor/gaphor/core/modeling/diagram.py", line 376, in update_now
    self._connections.solve()
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/connections.py", line 73, in solve
    self._solver.solve()
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/solver.py", line 181, in solve
    c.solve()
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/constraint.py", line 107, in solve
    self.solve_for(wvar)
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/position.py", line 164, in solve_for
    self._orig_pos.x, self._orig_pos.y = self.matrix.inverse().transform_point(
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/position.py", line 64, in _set_y
    self._y.value = v
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/variable.py", line 111, in set_value
    self.notify(oldval)
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/variable.py", line 90, in notify
    handler(self, old)
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/constraint.py", line 73, in _propagate
    self.notify()
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/constraint.py", line 69, in notify
    handler(self)
  File "/home/dan/Projects/gaphor/.venv/lib/python3.9/site-packages/gaphas/solver/solver.py", line 135, in request_resolve_constraint
    raise JuggleError(
gaphas.solver.solver.JuggleError: Variable juggling detected, constraint <gaphas.constraint.EqualsConstraint object at 0x7fa84cb56850> resolved 101 times out of 400

To Reproduce
Steps to reproduce the behavior:

  1. Open Gaphor
  2. Open the models/RAAML.gaphor model
  3. Open the Profiles -> RAAML -> Methods -> FTA -> FTA Library -> Events -> Event diagram
  4. Try to disconnect the associations or modify the diagram

Expected behavior
Should be able to disconnect the associations or make other modifications

Screenshots
If applicable, add screenshots to help explain your problem.

OS

  • Linux (Please put in notes the specific distro)
  • MacOS
  • Windows

NOTES:

Version
Version of Gaphas:

Additional context
Add any other context about the problem here.

Generalize painters

Is your feature request related to a problem? Please describe.

When a user is dragging a relation end, we want to be able to grey out items that can not be connected to in Gaphor.

Currently such visual hints are not possible.

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered

Maybe create custom CairoContexts, so they can be layered.

The interface may need to be extended if we also want to support things like handles (and maybe ports). The Cairo interface proved easy to work with, so I see no reason to move away from it.

Considerations

Can we make dealing with PangoLayout simpler as well? Cairo supports a "toy" text api. This one is not considered suitable for real text rendering (use Pango) for that.

Back buffer: No drawing during resize of widget

Is it intended/desired that during a resize operation of the GtkView, the canvas is not drawn, i.e. only the background color is visible?

Our canvas is nested in (several) Gtk.Paned and resides next to a Gtk.Revealer. Thus, in three situations, no state machine now shown:

  • the panes are resized
  • the revealer slides up
  • the window is resized

Personally, I would want the canvas to be drawn in all these situations.

Be able to extend it for building a UI mocking tool

Is your feature request related to a problem? Please describe.
I'm always frustrated when I need to use wine to start windows programs to do what I want, in an ugly and non-hidpi friendly way.

Describe the solution you'd like
I would like to be able to define my own shapes and control their attributes

Describe alternatives you've considered
Alternative would be to build my own web tool

Additional context
Yes, I am trying to have minimal replication of that the long time dead desktop Adobe Air application was doing, called Balsamiq mockup - I still use the cloud version for work, but that is overkill at home.

image

As you see, every symbol defined has its own attributes UI

  1. How can one define shapes ?
  2. How can one define and control attributes of those shapes using common or custom widgets, that in turn control the graphics of the shape ?

Improve the render cycle

Is your feature request related to a problem? Please describe.

In Gaphor we want grey-out elements a line (e.g. association) can connect to. The current drawing process (using Painter instances) is probably not well suited. Also, this flow has been designed based on GTK+ 2.0. The render process has changed drastically for GTK+ 3 and 4. Gaphas should update it's render pipeline accordingly.

Currently all drawing and styling is handled in Item.draw(). For Gaphor we added (CSS) styling to the mix. It would be great if we can separate the render shapes and styling a little more.

Describe the solution you'd like

I like to separate the render and drawing phase. The render phase should provide a structure (tree/list) of paint nodes. These nodes are collected separately from the actual drawing process.

This allows us to transform items (e.g. grey out the shapes) of an item without the need for a re-render of the item.

Describe alternatives you've considered

  • Stick with the current situation: the current update/draw process is based on GTK+ 2.0, we're close to GTK 4 now.

Additional context

I checked on how GTK and Clutter/Mutter do their rendering. Basically they use 2 phases:

  1. Collect all render nodes/shapes
  2. Draw the items to the screen (buffer)

This allows us to add filters in between the drawing process. E.g. to grey-out items.
We produce a render tree and this is used by the view until a re-render is required. We should be able to implement speed optimizations within Gaphas, without bothering application code.

If we do this, we can basically merge the post_update and draw functionality of items into one.

Open questions

  • How to deal with drawing handles, guides, rubber-band selection, etc.?

  • Some data is coming from items, such as handles. Should the render API provide methods for handling handles?

  • Guides and such are rendered by tools, when items are moved. How to add this info to the render pipeline?

  • Should we re-render on state change (normal, focused, selected)? Can we add CSS or conditional nodes to the mix?

  • Should we stick with Cairo? GTK 4 switched to Vulkan/OpenGL renderers. The Cairo API is simple and served us well. Also it allows us to export diagrams to PNG, SVG, etc., without hassle. So yes. If we can, let's stick with Cairo IMHO.

References:

Gaphas Attribute Error

While working with components and connectors, I get the following:

Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/canvas.py", line 674, in update_now
    self.update_constraints(dirty_matrix_items)
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/canvas.py", line 773, in update_constraints
    self._solver.solve()
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/solver.py", line 621, in solve
    c.solve_for(wvar)
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/constraint.py", line 492, in solve_for
    self._solve()
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/constraint.py", line 513, in _solve
    sx, sy = self._line[0]
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/canvas.py", line 1017, in __iter__
    return iter(self.pos)
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/canvas.py", line 1008, in 
    self._point, self._get_value(),
  File "/usr/local/lib/python2.6/dist-packages/gaphas-0.5.0-py2.6.egg/gaphas/canvas.py", line 1004, in _get_value
    self._px, self._py = item.canvas.get_matrix_i2c(item).transform_point(x, y)
AttributeError: 'NoneType' object has no attribute 'get_matrix_i2c'

Generic item hierarchy

Is your feature request related to a problem? Please describe.

Currently all canvas items should inherit from Item. The hierarchy is exclusively maintained in the Canvas class. This is not ideal, since this requires double bookkeeping in case the application has its own data model and it makes Canvas a central component, used by all items.

Describe the solution you'd like

Allow Gaphas to visualize any tree hierarchy. E.g. for Gaphor, we have an owner field that defines the relation between an element and its owner. This should also be usable to display items.

Additional context

It looks like the interface between GtkView and Canvas is actually quite thin: get_all_items() and sort().
Painters and Tools also use get_matrix_i2c() and get_connection().

get_matrix_i2c() could be replaced by a Projection.

How to deal with constaint solving, once the canvas hierarchy has been extracted? Do we still need a Canvas class?

Improve render speed

Is your feature request related to a problem?

Currently, when implementing Item.draw(), you have to take into account speed: every time a canvas is redrawn, this method is called.

Rendering is relatively slow, esp. on macOS.

I did some trails with cairo.RecordingSurface, but that's probably not what we need: to render a surface it has to be applied as a pattern on the target surface. For our purposes it would be enough to just replay any drawing operation on the target surface. My assumption is that that will also be faster.

Describe the solution you'd like

When an item is drawn (the first time this happens is when the bounding box is calculated), the drawing operations should be recorded. On subsequent draws, the recorded items should be replayed. This ensures that:

  1. we always draw the same thing, until the item requires an update (keeps bounding box consistent)
  2. the concern of draw() being fast is less strict

Solution to be determined still. See alternatives.

Describe alternatives you've considered

  • Create a custom DrawingContext for Gaphas. Instead of calling DrawingContext.cairo methods, expose all required methods through DrawingContext directly. This should also expose methods for rendering Pango Layouts and SVG images (librsvg).
  • Use RecordingSurface. For one, @danyeaw got artifacts in the diagram. Secondly it's applied via patterns, where it's more logical for us to just just replay the recorded events on a surface.
  • Maybe add a bit of C/Cython) code that hooks into cairo and provides the required capabilities (e.g. expose RecordingSurface.replay or expose the surface observer code).

Additional context

We should handle SVG and Pango layouts as well. They render to a cairo.Context directly. Do we want to keep that interface, or provide a Gaphas specific way to render those?

gaphas gtk3 with python 3 supports still python 2.7.x

If you plan to support python 2.7 and python 3.4 and higher you have to keep your tests running under python 2.7, too. In your .travis.yml file you label 2.7 and 3.5, 3.6, 3.7 to be supported.

At the moment your code got some lines that can not be executed by python 2.7.13 which we still use in our RAFCON environments in our institute.
So currently the last good commit is f1bbb9d. Thereby problems start with the use of super calls that are not valid to python 2.7 like super().

RAFCON aims to support python 2.7 without gtk3 and 2.7 and 3.4 (current version in our labs), 3.5, 3.6, 3.7 with gtk3, for now.

Note:
Sorry if the description sounds a bit pushy. This was not my intention.

Wrong acces to event state

In GTK+ 3, the event state is accessed by get_state(). Several occurrences of event.state need to be replaced by event.get_state()[1].

Move selection, focus and drop-zone info out of the view

Is your feature request related to a problem? Please describe.

The Gtk View is restricted in that it supports selected and focused items. These are properties defined by the tools we use. A Selection Tool exposes the behavior of actually selecting something

Describe the solution you'd like

Separate selection from the View class. This information should remain accessible in some way, though.

Wrong acces of event button number

At least in tools.py, the access to the button number of an event needs to be changed from event.button to event.get_button()[1] for GTK+ 3.

Check setup.py requirements

Could you please have a look at the requirements in your setup.py?

  • setup_requires contains:
    • pytest-* packages, which I guess can be moved to tests_require
    • sixis this required? You use futurize
    • pre-commit: Required for installation?
  • install_requires
    • PyGObject >= 3.26.1: Is PyGObject really required in this version? We use it with PyGObject 3.20, so this could be a minimum version
    • pycairo >= 1.11.0: Is pycairo really required in this version? We use it with pycairo 1.10, so this could be a minimum version

simplegeneric => singledispatch: backward compatibility

With the change from simplegeneric to singledispatch, gaphas is no longer backward compatible with code that registers custom types, as you now need to call register instead of when_type.

This is fine, as you increase the minor version.

I was just wondering, whether you think there is an easy way for other software not requiring any code changes. Maybe somehow monkeypatching singledispatch? Doesn't sound like the best solution :-D

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.