November 11, 2006
The main thing in Flake is shapes. A shape is connected to (at least) one tool that knows about the shapes internals. (see Flake) We have a general pathShape (which edits any type of vectors) as well as specialisations, e.g. a star or a rounded-rect that underwater are still pathShapes. The path tool has different implementations (to edit nodes without having to know it’s a star one’s editing), there is a method that you can call to find out what the parameters are.
The tool manager in the UI can create a toolbox docker, it contains all tools and lets you choose them. There is 1 tool manager per application which means that there is 1 active tool type per application. Since some applications could benefit from a different approach, Thomas will look at this and see if it can be changed.
Decision: Alter ToolManager to no longer have one active tool per application, but one per view.
Shapes draw themselves and contain all their own information (document content). Thomas suggests to make a model/view separation in the shape internally to make it possible that 2 shapes point at the same datastructure.
During the last meeting (june 2005), templates were discussed. The shape factory can create any shape possible. Each plugins shape factory creates specific shapes based on properties (name value pairs) that are defined by that plugin. Stencils in Kivio can be defined with templates (name, value pairs).
Decision: We will continue to use a Template which includes an icon, a name and a properties object (name/value pairs) for the shapeSelector and
Loading and saving: from and to which fileformat should shapes load and save? Loading an old Kivio file; use the path/shape the load and save old file formats? or convert using file filters? With the latter it is impossible to save the exact stuff you loaded.
Decision: We will use ODF as native format, so load/save from/to ODF and use converters (koffice-filters) for the rest.
KService: A KService is a dynamically loaded library via the system controller cache, there is some code that loads a list that contains all tools complying with the settings. Then a constructor is called - 2 choices here: 1) construct the actual tool, 2) have a generic constructor that creates all factories available in the plugin. There is only one thing in a plugin that can be auto-constructed: a tool factory OR a shape factory OR a colour space factory OR ... With option 2, a registry gets to own the factories so it will have to delete something it didn’t create.
Decision: Create a pluginLoader that is able to load all kinds of plugins and stop all the separate registries from doing that themselves.
As a plugin is a standalone item it needs to contain all related components. This is because a class outside the plugin can not (dynamic) cast to any type that is contained inside the plugin. We need all base classes in a shared library like Flake (e.g. the parameter shape). All factories will always be loaded.
Decision: Do sensible grouping of tools and shapes and combine them: all specialisations in 1 plugin (with default constructor called from the plugin loader)
This saves discovery and loading time and prevents weird dependencies. Combining a tool and a shape in 1 plugin will require a 3rd generic type Constructing a plugin: have a constructor that creates all stuff instead of doing it with various constructors.
The KoShapeSelector can contain sets of templates and one can add custom templates that can create custom shapes. A template is a set of icon, name and a KoProperties object. Properties are just name-value pairs, creating a new shape is done by using in those pairs in the specific KoShapeFactory::createShape(). Further explanation at: Calligra/ShapeSelector. In the user interface we want to have a unification of clipart, shape stencils and the clipboard.
Which strategy to use for placing stuff on the canvas? We have drag-and-drop, dragging a stamp, multiple clicks, and freehand movement. In the latter case, the mouse path is important, so these can’t be created from the shape selector. Paths, freehand movement, and lines will be put in the toolbar, rectangles, stars and other shapes in the shape selector.
Decision: The shapeSelector should allow users to insert objects using 4 ways: DnD / Double click / single click / click and drag
Decision: The shapeSelector will hold shape-types that are currently available as Tools. These include things like a 'star', 'rect'. We decided that the separation lies at the line tool. With things like the polyline still being tools. The line tool itself was voted to be a Tool.
It’s been decided to give the KoCanvasResourceProvider extra methods for colors, line styles, etc. instead of having to keep to generic methods.
For at least KPresenter, we want a “selectable” flag so that e.g. master slide objects can’t be selected from the normal page view. Shapes can link back to their parent “page” (as in Karbon), so that removing a shape and then undo-ing the removal will put the shape back at its proper page. We can’t put this in the userdata field, since this field is shape specific and some shapes already use it. We could have a page/group layer be a KoShapeContainer as well. Krita needs image data access, the text tool needs document info access.
Page numbering is perceived differently in different applications: KWord and KPresenter have separate pages while Karbon has 1 infinite page. If the document gets requested to remove a shape from the document data, the shape itself does not get deleted. Having the page (or slide/image) be a KoShapeContainer is neater though, since it’s a shape in itself as well so the flake hierarchy can be used for that.
Decision: KPresenter uses KoShapeContainer inheriting classes for its pages and adds the shapes to that and thus taking advantage of the existing flake hierarchy without extra work.
Decision: The KoShape class needs a new boolean; isSelectable() which, when false, makes it possible to have a page that the user never knows about, but is added to the KoShapeManager
A problem with undo stacks: select an object, insert a node, deselect it, switch back and forth to a different tool, reselect the object and the node, then undo the insertion. Since the history does not contain the right information anymore, we keep a selection to a non-existing node because the selection is not updated of changes in the data-model. Solution: Make PathInsert/delete command tell all the path tools in existence about the just deleted point so they can deselect it. Problem with that is that the command is in the flake lib and the way to get at all the tools is in the kofficeui lib (KoToolManager). We probably need an interface for that.
Why are Karbon layers not in the shape manager? Because we wanted them to be selectable. This is solved by the selectable flag. Jan can't think of any other reasons at this time.
A KOffice-wide library for layer manipulation (a common layer) box will be looked at, this would go in the ui and not in Flake. ODF requires layers with global properties - we support shape containers.
How to attach animation to a shape? We cannot use userdata, see above. Since KPresenter is the only application needing this right now, it will use a decorator pattern and if needed extend upon this later. The animation details will thus be saved in a separate class that has a reference to the shape and allow it to alter the shape's coordinates/scaling/rotation. The concept behind the decorator pattern is that the shape will have no knowledge (and pointers etc) to the animation details.
ODF versus shapes - loading: how do we know which shape loads a certain blob of information we got from a source? Ask the registry to give the factory for this shape, passing it the DOM node. Thorsten volunteers. Hierarchy: we need a helper method to be able to hierarchically load nested objects. See the Calligra/Flake/Loading&Saving proposal.
Text in shapes: text nodes inside objects should be forceable inside the other shape’s boundary. Thomas expects this not to be too much work since joining objects is already likely to work. See the KoShapeContainerModel class and its use in the KoShapeContainer.
Bounding rectangles and shadows: should the bounding rectangle of an object include its shadow or not? We know that aligning should not take it into account. Repainting could be an issue, but we could fix KoShape to draw the shadow and be aware of it.
Decision: the KoShape should not include the shadow in its boundingRect. solution is to make the KoShapeManager enlarge the boudingrect of a shape before it inserts that shape into its rTree.
Creating and inserting shapes: move getting the shape controller from KoToolManager to KoCanvasBase and doing some strategy moving, should do the trick. Thorsten volunteers. done 22.11.2006 Thorsten Zachmann
Autoselection of tools (which tool, if any, should be selected by default when selecting a shape)? This is something to experiment with and will include little details. Users and usability people should definitely be consulted here as well.
KOffice-wide settings like default font sizes, the preferred colour chooser, the color for selection-outlines and grid behaviour, should be KOffice-wide. Hence a mechanism to share configuration files and settings is needed, next to a single panel where users can set those options for all KOffice apps in one go.
Tools are categorised in four groups: the pointer; line, text and other tools; basic application-specific tools; and advanced application-specific tools. The last category could be hidden from view when editing within another application to prevent the toolbox from overflowing.