Click in here:
Have you ever used a tool in one program that works so well you want to use it in other programs?
In open source graphics software, there are many programs to choose from: Gimp, Inkscape, Krita, Mypaint, etc.
It is very unlikely that a single program is going to do everything just the way you want.
What if you could easily transplant your favorite tools from one program to another? This page
aims to explore some of that.
Simply porting tool code from one program to another is not a very satisfying solution. A huge amount
of effort goes into translating and debugging transplanted code. Plus if the tool gets improvements
elsewhere, it can be quite a pain to update the transplanted code!
One peril of open source development is the lack of time people have to code things. The norm
is for people to code just in their spare time, and for no money. There are important exceptions
such as Google Summer of Code, various foundations that are mostly for specific projects,
and some individuals, but otherwise, time is limited!
For tools, it is much easier and faster to code a dialog to correspond to a data structure, than
spend the huge amount of time required to iron out the intricacies of an efficient tool.
If you could easily share interfaces, this cuts down on development time, making programmers happy.
It also allows a wider base to test out and improve interfaces, making designers happy.
If it is coded in a very accessible manner, it would also allow artists to make and experiment with
crazy new interfaces.
Libmypaint is doing something similar in spirit, by allowing sharing of Mypaint brushes among raster
based image editors. Tool sharing I mean here is the sharing of the interfaces mostly for manipulating
vector objects, which usually means dragging around various on canvas nuts and bolts.
Ok, maybe this sounds great in theory, but who's going to code all of this?! That remains to be seen,
but in the meantime, let's talk about what possibly has to be done to allow tool sharing.
So what can we learn from current tool implementations? With the rise of html5 and the canvas element,
there are several libraries, such as paperjs,
processing.js, or kinetic.js that make it very easy to implement tools with minimal
effort. They offer a simple scripting interface, and can even easily provide animated tools.
Here is an example of a tool written with paper.js. While the tool is simply
a pale imitation of Corel Draw's dimensioning tool, the point is that with just a couple of screens of code,
one may create tools quickly to get things done.
Refinements can always be made later (and make the code 10 times longer).
Comparatively, most desktop programs that have been around for a long
time tend to implement tools in ways that are not very accessible. They generally require very specific and
detailed knowledge of a broader code base, which tends to be less documented the older it is. Plus, the relevant
code tends to be strewn across many directories, and without documentation, it is quite difficult to figure
out what all must be done to create new tools.
Moving forward then, what are the requirements to share tools? At the simplest to implement level,
code should be documented, with a clear description of what files are involved. This makes it easier to simply port from one place to another.
Perhaps there could be a kind of SWIG for tool code, to create code specific
to the target program, whether C++ for Inkscape or C for Gimp. As mentioned above, there are drawbacks to this!
Easier would be to write code in an environment that makes certain assumptions about what vector
objects and display capabilities are available.
If tool plugins exist in a program, they can be made to adapt to sharing tools.
Then the task at hand is to implement a tool plugin ability in interested programs, and ideally only the "sharing"
part of "sharing tools" needs to be reimplemented in target programs, and the "tool" part slides right in to place.
In Laidout, there are a number of interfaces available, and specifically what they do in a particular context
depends on "subclasses" of the interfaces for that context. Interfaces can also behave as children of other interfaces,
by specifying what kind of data they work on, and sending messages to the parent interface when that data is altered.
As an example, take Laidout's alignment tool. It works
on a "selection of objects", by only adjusting the transformations of each object. It uses a different path editor interface
as a child interface to adjust the alignment path.
To define all these interface relationships, and how native programs interact with them, perhaps we need a sort of QML for interfaces.
Another option is to create a shared library for tools. There are strengths and weaknesses to either
approach. With a new qml/scripted method, you would need to require an interpreter engine always running.
Many programs these days have such a thing available in a sense, at least in a minimal way, such as Gimp's
browsable pdb. With a shared library, you must adapt your software to however the library encapsulates data. If the
requirements of this library are kept simple, this would make it easy to update tools just by updating the library.
For the tools I envision sharing, keeping it simple means having draggable controls that can be displayed
with a very limited subset of svg path elements, and text labels. Being able to type in data such as numbers or labels
on the canvas is also important. Some programs have the ability to generate
dialogs from scripts, such as Gimp, and Scribus to an extent. To share tools that have dialogs, this could
Tool implementation can become complicated quite quickly, when considering how best to interface to programs'
undo stack, rendering, control definitions, helper dialogs, time based tools, and the actual objects being changed.
Definitely more research and comments are required to sort this out!
... I'll have more on this, hopefully after my next Laidout release!
May 12, 2013
Copyright 2013, Tom J. Lechner