/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace com::sun::star::awt
{ class XWindow;
} namespace com::sun::star::datatransfer::clipboard
{ class XClipboard;
} namespace com::sun::star::datatransfer::dnd
{ class XDropTarget;
} namespace com::sun::star::graphic
{ class XGraphic;
} typedef css::uno::Reference<css::accessibility::XAccessible> a11yref; typedef css::uno::Reference<css::accessibility::XAccessibleRelationSet> a11yrelationset; enumclass PointerStyle; class CommandEvent; class Formatter; class InputContext; class KeyEvent; class MouseEvent; class TransferDataContainer; class OutputDevice; class VirtualDevice; struct SystemEnvData; class BitmapEx;
namespace vcl
{ class ILibreOfficeKitNotifier; typedef OutputDevice RenderContext;
} namespace tools
{ class JsonWriter;
}
class LOKTrigger;
namespace weld
{ class Container; class DialogController;
class VCL_DLLPUBLIC Widget
{ friendclass ::LOKTrigger;
// This function simply calls show() or hide() but is convenient when the // visibility depends on some condition virtualvoid set_visible(bool visible)
{ if (visible)
show(); else
hide();
}
// return if this widget's visibility is true virtualbool get_visible() const = 0;
// return if this widget's visibility and that of all its parents is true virtualbool is_visible() const = 0;
/* focus */
// sets if this widget can own the keyboard focus virtualvoid set_can_focus(bool bCanFocus) = 0;
// causes this widget to have the keyboard focus virtualvoid grab_focus() = 0;
// returns if this widget has the keyboard focus virtualbool has_focus() const = 0;
// if the widget that has focus is a child, which includes toplevel popup // children, of this widget. So an Entry with an active popup (or dialog) // has has_child_focus of true, but has_focus of false, while its popup is // shown virtualbool has_child_focus() const = 0;
// return if this widget has the keyboard focus within the active window // TODO: review if this has any practical difference from has_focus() virtualbool is_active() const = 0;
// The name of the widget in the GtkBuilder UI definition used to construct it. virtual OUString get_buildable_name() const = 0; /* Typically there is no need to change the buildable name at runtime, changing the id in .ui file itself is preferred.
But for ui-testing purposes it can sometimes be useful to rename different widgets, that were loaded from the same .ui, to unique names in order to distinguish between them
*/ virtualvoid set_buildable_name(const OUString& rName) = 0;
/* The help id of the widget used to identify help for this widget.
By default the help id of a widget is a path-like sequence of (load-time) buildable-names from the widgets UI definition ancestor to this widget, e.g. grandparent/parent/widget.
The default can be overwritten with set_help_id
*/ virtual OUString get_help_id() const = 0; virtualvoid set_help_id(const OUString& rName) = 0;
/* * Report the extents of this widget relative to the rRelative target widget. * * To succeed, both widgets must be realized, and must share a common toplevel. * * returns false if the relative extents could not be determined, e.g. if * either widget was not realized, or there was no common ancestor. * Otherwise true.
*/ virtualbool get_extents_relative_to(const Widget& rRelative, int& x, int& y, int& width, int& height) const = 0;
// After this call this widget is only accessibility labelled by pLabel and // pLabel only accessibility labels this widget virtualvoid set_accessible_relation_labeled_by(weld::Widget* pLabel) = 0;
// rLink is called when the mnemonic for the Widget is called. // If rLink returns true the Widget will not automatically gain // focus as normally occurs virtualvoid connect_mnemonic_activate(const Link<Widget&, bool>& rLink)
{
assert(!m_aMnemonicActivateHdl.IsSet() || !rLink.IsSet());
m_aMnemonicActivateHdl = rLink;
}
If the freeze count is non-zero, emission of the widget's notifications is stopped. The notifications are queued until the freeze count is decreased to zero. Duplicate notifications may be squashed together.
*/ virtualvoid freeze() = 0;
/* Reverts the effect of a previous call to freeze.
The freeze count is decreased on the widget and when it reaches zero, queued notifications are emitted.
*/ virtualvoid thaw() = 0;
/* push/pop busy mouse cursor state
bBusy of true to push a busy state onto the stack and false to pop it off, calls to this should balance.
see weld::WaitObject */ virtualvoid set_busy_cursor(bool bBusy) = 0;
//iterate upwards through the hierarchy starting at this widgets parent, //calling func with their helpid until func returns true or we run out of //parents virtualvoid help_hierarchy_foreach(const std::function<bool(const OUString&)>& func) = 0;
/* Escapes string contents which are interpreted by the UI.
Should be overwritten by each VCL implementation to account for the string contents which are interpreted by its ui.
*/ virtual OUString escape_ui_str(const OUString& rLabel) const = 0;
//do something transient to attract the attention of the user to the widget virtualvoid call_attention_to() = 0;
//make this widget look like a page in a notebook virtualvoid set_stack_background() = 0; //make this widget look like it has a highlighted background virtualvoid set_highlight_background() = 0; //make this widget suitable as parent for a title virtualvoid set_title_background() = 0; //make this widget suitable for use in a toolbar virtualvoid set_toolbar_background() = 0; //trying to use a custom color for a background is generally a bad idea. If your need //fits one of the above categories then that's a somewhat better choice virtualvoid set_background(const Color& rBackColor) = 0; // reset to default background virtualvoid set_background() = 0;
public: // remove from old container and add to new container in one go // new container can be null to just remove from old container virtualvoid move(weld::Widget* pWidget, weld::Container* pNewParent) = 0; // create an XWindow as a child of this container. The XWindow is // suitable to contain css::awt::XControl items virtual css::uno::Reference<css::awt::XWindow> CreateChildFrame() = 0; // rLink is called when the focus transitions from a widget outside the container // to a widget inside the container or vice versa virtualvoid connect_container_focus_changed(const Link<Container&, void>& rLink)
{
m_aContainerFocusChangedHdl = rLink;
} // causes a child of the container to have the keyboard focus virtualvoid child_grab_focus() = 0;
};
class VCL_DLLPUBLIC Box : virtualpublic Container
{ public: // Moves child to a new position in the list of children virtualvoid reorder_child(weld::Widget* pWidget, int position) = 0; // Sort ok/cancel etc buttons in platform order virtualvoid sort_native_button_order() = 0;
};
class VCL_DLLPUBLIC Paned : virtualpublic Container
{ public: // set pixel position of divider virtualvoid set_position(int nPos) = 0; // get pixel position of divider virtualint get_position() const = 0;
};
class VCL_DLLPUBLIC ScrolledWindow : virtualpublic Container
{ friendclass ::LOKTrigger;
//trying to use custom color for a scrollbar is generally a bad idea. virtualvoid customize_scrollbars(const Color& rBackgroundColor, const Color& rShadowColor, const Color& rFaceColor)
= 0;
};
// returns whether the widget that has focus is within this Window // (its very possible to move this to weld::Container if that becomes // desirable) virtualbool has_toplevel_focus() const = 0; virtualvoid present() = 0;
// with pOld of null, automatically find the old default widget and unset // it, otherwise use as hint to the old default virtualvoid change_default_widget(weld::Widget* pOld, weld::Widget* pNew) = 0; virtualbool is_default_widget(const weld::Widget* pCandidate) const = 0;
// center dialog on its parent // // bTrackGeometryRequests set to true tries to ensure the dialog will end // up still centered on its parent windows final size, taking into account // that there may currently be pending geometry requests for the parent not // yet processed by the underlying toolkit // // for e.g gtk this will means the dialog is always centered even when // resized, calling set_centered_on_parent with false will turn this // off again. virtualvoid set_centered_on_parent(bool bTrackGeometryRequests) = 0;
virtualint run() = 0; // Run async without a controller // @param self - must point to this, to enforce that the dialog was created/held by a shared_ptr virtualbool runAsync(std::shared_ptr<Dialog> const& rxSelf, const std::function<void(sal_Int32)>& func)
= 0; virtualvoid response(int response) = 0; virtualvoid add_button(const OUString& rText, int response, const OUString& rHelpId = {}) = 0; virtualvoid set_default_response(int response) = 0; virtual std::unique_ptr<Button> weld_button_for_response(int response) = 0; virtual std::unique_ptr<weld::Container> weld_content_area() = 0;
// shrink the dialog down to shown just these widgets virtualvoid collapse(weld::Widget* pEdit, weld::Widget* pButton) = 0; // undo previous dialog collapse virtualvoid undo_collapse() = 0;
/// A widget used to choose from a list of items. class VCL_DLLPUBLIC ComboBox : virtualpublic Widget
{ private:
OUString m_sSavedValue;
std::vector<OUString> m_aSavedValues;
public: // OUString is the id of the row, it may be null to measure the height of a generic line typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, bool, const OUString&>
render_args;
/* m_aChangeHdl is called when the active item is changed. The can be due to the user selecting a different item from the list or while typing into the entry of a combo box with an entry.
Use changed_by_direct_pick() to discover whether an item was actually explicitly selected, e.g. from the menu.
*/ void connect_changed(const Link<ComboBox&, void>& rLink) { m_aChangeHdl = rLink; }
// font size is in points, not pixels, e.g. see Window::[G]etPointFont virtualvoid set_font(const vcl::Font& rFont) = 0;
// font size is in points, not pixels, e.g. see Window::[G]etPointFont virtualvoid set_entry_font(const vcl::Font& rFont) = 0; virtual vcl::Font get_entry_font() = 0;
// for custom rendering a row void connect_custom_get_size(const Link<vcl::RenderContext&, Size>& rLink)
{
m_aGetSizeHdl = rLink;
} void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; } // call set_custom_renderer after setting custom callbacks virtualvoid set_custom_renderer(bool bOn) = 0; // create a virtual device compatible with the device passed in render_args wrt alpha virtual VclPtr<VirtualDevice> create_render_virtual_device() const = 0; // set a sub menu for a entry, only works with custom rendering virtualvoid set_item_menu(const OUString& rIdent, weld::Menu* pMenu) = 0; // get the width needed to show the menu launcher in a custom row virtualint get_menu_button_width() const = 0;
/* Model column indexes are considered to begin at 0, but with special columns before index 0. A expander image column (and an additional optional toggle button column when enable_toggle_buttons is used). Column index -1 is reserved to access those columns.
*/ class VCL_DLLPUBLIC TreeView : virtualpublic Widget
{ friendclass ::LOKTrigger;
public: typedef std::pair<const TreeIter&, int> iter_col; typedef std::pair<const TreeIter&, OUString> iter_string; // OUString is the id of the row, it may be null to measure the height of a generic line typedef std::pair<vcl::RenderContext&, const OUString&> get_size_args; typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, bool, const OUString&>
render_args;
private:
OUString m_sSavedValue;
protected:
Link<TreeView&, void> m_aSelectionChangedHdl;
Link<TreeView&, bool> m_aRowActivatedHdl;
Link<int, void> m_aColumnClickedHdl;
Link<const iter_col&, void> m_aRadioToggleHdl;
Link<const TreeIter&, bool> m_aEditingStartedHdl;
Link<const iter_string&, bool> m_aEditingDoneHdl; // if handler returns false, the expansion of the row is refused
Link<const TreeIter&, bool> m_aExpandingHdl; // if handler returns false, the collapse of the row is refused
Link<const TreeIter&, bool> m_aCollapsingHdl;
Link<TreeView&, void> m_aVisibleRangeChangedHdl;
Link<TreeView&, void> m_aModelChangedHdl; // if handler returns true, then menu has been show and event is consumed
Link<const CommandEvent&, bool> m_aPopupMenuHdl; // if handler returns true, drag is disallowed, consumer can change bool // arg to false to disable the treeview default dnd icon
Link<bool&, bool> m_aDragBeginHdl;
std::function<int(const weld::TreeIter&, const weld::TreeIter&)> m_aCustomSort;
/* A row is "activated" when the user double clicks a treeview row. It may also be emitted when a row is selected and Space or Enter is pressed.
a return of "true" means the activation has been handled, a "false" propagates the activation to the default handler which expands/collapses the row, if possible.
*/ void connect_row_activated(const Link<TreeView&, bool>& rLink) { m_aRowActivatedHdl = rLink; }
// Argument is a pair of iter, col describing the toggled node void connect_toggled(const Link<const iter_col&, void>& rLink) { m_aRadioToggleHdl = rLink; }
// call before inserting any content and connecting to toggle signals, // an pre-inserted checkbutton column will exist at the start of every row // inserted after this call which can be accessed with col index -1 virtualvoid enable_toggle_buttons(ColumnToggleType eType) = 0;
//by index virtualint get_selected_index() const = 0; //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze. virtualvoid select(int pos) = 0; virtualvoid unselect(int pos) = 0; virtualvoid remove(int pos) = 0; // col index -1 gets the first text column virtual OUString get_text(int row, int col = -1) const = 0; // col index -1 sets the first text column virtualvoid set_text(int row, const OUString& rText, int col = -1) = 0; // col index -1 sets all columns virtualvoid set_sensitive(int row, bool bSensitive, int col = -1) = 0; virtualbool get_sensitive(int row, int col) const = 0; virtualvoid set_id(int row, const OUString& rId) = 0; // col index -1 sets the expander toggle, enable_toggle_buttons must have been called to create that column virtualvoid set_toggle(int row, TriState eState, int col = -1) = 0; // col index -1 gets the expander toggle, enable_toggle_buttons must have been called to create that column virtual TriState get_toggle(int row, int col = -1) const = 0; // col index -1 sets the expander image virtualvoid set_image(int row, const OUString& rImage, int col = -1) = 0; // col index -1 sets the expander image virtualvoid set_image(int row, VirtualDevice& rImage, int col = -1) = 0; // col index -1 sets the expander image virtualvoid set_image(int row, const css::uno::Reference<css::graphic::XGraphic>& rImage, int col = -1)
= 0; virtualvoid set_text_emphasis(int row, bool bOn, int col) = 0; virtualbool get_text_emphasis(int row, int col) const = 0; virtualvoid set_text_align(int row, double fAlign, int col) = 0; virtualvoid swap(int pos1, int pos2) = 0; virtual std::vector<int> get_selected_rows() const = 0; virtualvoid set_font_color(int pos, const Color& rColor) = 0; // scroll to make 'row' visible, this will also expand all parent rows of 'row' as necessary to // make 'row' visible virtualvoid scroll_to_row(int row) = 0; virtualbool is_selected(int pos) const = 0; virtualint get_cursor_index() const = 0; virtualvoid set_cursor(int pos) = 0;
//by text virtualint find_text(const OUString& rText) const = 0; //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze. void select_text(const OUString& rText) { select(find_text(rText)); } void remove_text(const OUString& rText) { remove(find_text(rText)); }
std::vector<OUString> get_selected_rows_text() const
{
std::vector<int> aRows(get_selected_rows());
std::vector<OUString> aRet;
aRet.reserve(aRows.size()); for (auto a : aRows)
aRet.push_back(get_text(a)); return aRet;
}
//via iter virtual std::unique_ptr<TreeIter> make_iterator(const TreeIter* pOrig = nullptr) const = 0; virtualvoid copy_iterator(const TreeIter& rSource, TreeIter& rDest) const = 0; virtualbool get_selected(TreeIter* pIter) const = 0; virtualbool get_cursor(TreeIter* pIter) const = 0; virtualvoid set_cursor(const TreeIter& rIter) = 0; virtualbool get_iter_first(TreeIter& rIter) const = 0; // set iter to point to next node at the current level virtualbool iter_next_sibling(TreeIter& rIter) const = 0; // set iter to point to previous node at the current level virtualbool iter_previous_sibling(TreeIter& rIter) const = 0; // set iter to point to next node, depth first, then sibling virtualbool iter_next(TreeIter& rIter) const = 0; // set iter to point to previous node, sibling first then depth virtualbool iter_previous(TreeIter& rIter) const = 0; // set iter to point to first child node virtualbool iter_children(TreeIter& rIter) const = 0; bool iter_nth_sibling(TreeIter& rIter, int nChild) const
{ bool bRet = true; for (int i = 0; i < nChild && bRet; ++i)
bRet = iter_next_sibling(rIter); return bRet;
} bool iter_nth_child(TreeIter& rIter, int nChild) const
{ if (!iter_children(rIter)) returnfalse; return iter_nth_sibling(rIter, nChild);
} virtualbool iter_parent(TreeIter& rIter) const = 0; virtualint get_iter_depth(const TreeIter& rIter) const = 0; virtualint get_iter_index_in_parent(const TreeIter& rIter) const = 0; /* Compares two paths. If a appears before b in a tree, then -1 is returned. If b appears before a , then 1 is returned. If the two nodes are equal, then 0 is returned.
*/ virtualint iter_compare(const TreeIter& a, const TreeIter& b) const = 0; virtualbool iter_has_child(const TreeIter& rIter) const = 0; // returns the number of direct children rIter has virtualint iter_n_children(const TreeIter& rIter) const = 0; virtualvoid remove(const TreeIter& rIter) = 0; //Don't select when frozen, select after thaw. Note selection doesn't survive a freeze. virtualvoid select(const TreeIter& rIter) = 0; virtualvoid unselect(const TreeIter& rIter) = 0; //visually indent this row as if it was at get_iter_depth() + nIndentLevel virtualvoid set_extra_row_indent(const TreeIter& rIter, int nIndentLevel) = 0; // col index -1 sets the first text column virtualvoid set_text(const TreeIter& rIter, const OUString& rStr, int col = -1) = 0; // col index -1 sets all columns virtualvoid set_sensitive(const TreeIter& rIter, bool bSensitive, int col = -1) = 0; virtualbool get_sensitive(const TreeIter& rIter, int col) const = 0; virtualvoid set_text_emphasis(const TreeIter& rIter, bool bOn, int col) = 0; virtualbool get_text_emphasis(const TreeIter& rIter, int col) const = 0; virtualvoid set_text_align(const TreeIter& rIter, double fAlign, int col) = 0; // col index -1 sets the expander toggle, enable_toggle_buttons must have been called to create that column virtualvoid set_toggle(const TreeIter& rIter, TriState bOn, int col = -1) = 0; // col index -1 gets the expander toggle, enable_toggle_buttons must have been called to create that column virtual TriState get_toggle(const TreeIter& rIter, int col = -1) const = 0; // col index -1 gets the first text column virtual OUString get_text(const TreeIter& rIter, int col = -1) const = 0; virtualvoid set_id(const TreeIter& rIter, const OUString& rId) = 0; virtual OUString get_id(const TreeIter& rIter) const = 0; // col index -1 sets the expander image virtualvoid set_image(const TreeIter& rIter, const OUString& rImage, int col = -1) = 0; // col index -1 sets the expander image virtualvoid set_image(const TreeIter& rIter, VirtualDevice& rImage, int col = -1) = 0; // col index -1 sets the expander image virtualvoid set_image(const TreeIter& rIter, const css::uno::Reference<css::graphic::XGraphic>& rImage, int col = -1)
= 0; virtualvoid set_font_color(const TreeIter& rIter, const Color& rColor) = 0; // scroll to make rIter visible, this will also expand all parent rows of rIter as necessary to // make rIter visible virtualvoid scroll_to_row(const TreeIter& rIter) = 0; virtualbool is_selected(const TreeIter& rIter) const = 0;
virtualvoid move_subtree(TreeIter& rNode, const TreeIter* pNewParent, int nIndexInNewParent)
= 0;
// call func on each element until func returns true or we run out of elements virtualvoid all_foreach(const std::function<bool(TreeIter&)>& func) = 0; // call func on each selected element until func returns true or we run out of elements virtualvoid selected_foreach(const std::function<bool(TreeIter&)>& func) = 0; // call func on each visible element until func returns true or we run out of elements virtualvoid visible_foreach(const std::function<bool(TreeIter&)>& func) = 0; // clear the children of pParent (whole tree if nullptr), // then add nSourceCount rows under pParent, call func on each row // inserted with an arg of the index that this row will be when bulk insert // ends. // // this enables inserting the entries backwards in models where that is faster, // // pFixedWidths is optional, when present each matching entry col text // width will not be measured, and the fixed width used instead. Use // sparingly because wider text than the fixed width is clipped and cannot // be scrolled into view horizontally. // @param bGoingToSetText needs to be true, if you plan to call set_text inside the insert func. virtualvoid bulk_insert_for_each(int nSourceCount, const std::function<void(TreeIter&, int nSourceIndex)>& func, const weld::TreeIter* pParent = nullptr, const std::vector<int>* pFixedWidths = nullptr, bool bGoingToSetText = false)
= 0;
/* expanding on-demand node details
When a node is added with children-on-demand (typically via 'insert' with bChildrenOnDemand of true), then initially in reality the children-on-demand node is given a 'placeholder' child entry to indicate the load-on-demand state.
The 'placeholder' needs to be there for the expander indicator to be drawn/shown even when there are no "real" entries yet. This child doesn't exist for the purposes of any of the iterator methods, e.g. iter_has_child on an on-demand node which hasn't been expanded yet is false. Likewise the rest of the iterator methods skip over or otherwise ignore that node.
Normal usage is the user clicks on the expander, the expansion mechanism removes the 'placeholder' entry (set_children_on_demand(false)) and calls any installed expanding-callback (installable via connect_expanding) which has the opportunity to populate the node with children.
If you decide to directly populate the children of an on-demand node outside of the expanding-callback then you also need to explicitly remove the 'placeholder' with set_children_on_demand(false) otherwise the treeview
is in an inconsistent state. */
virtualbool get_row_expanded(const TreeIter& rIter) const = 0; // expand row will first trigger the callback set via connect_expanding before expanding virtualvoid expand_row(const TreeIter& rIter) = 0; // collapse row will first trigger the callback set via connect_collapsing before collapsing virtualvoid collapse_row(const TreeIter& rIter) = 0; // set the empty node to appear as if it has children, true is equivalent // to 'insert' with a bChildrenOnDemand of true. See notes above. virtualvoid set_children_on_demand(const TreeIter& rIter, bool bChildrenOnDemand) = 0; // return if the node is configured to be populated on-demand virtualbool get_children_on_demand(const TreeIter& rIter) const = 0; // set if the expanders are shown or not virtualvoid set_show_expanders(bool bShow) = 0;
// only meaningful is call this from a "changed" callback, true if the change // was due to mouse hovering over the entry virtualbool changed_by_hover() const = 0;
// for custom rendering a cell void connect_custom_get_size(const Link<get_size_args, Size>& rLink) { m_aGetSizeHdl = rLink; } void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; } // call set_column_custom_renderer after setting custom callbacks virtualvoid set_column_custom_renderer(int nColumn, bool bEnable) = 0; // redraw all rows, typically only useful with custom rendering to redraw due to external // state change virtualvoid queue_draw() = 0;
/* with bDnDMode false simply return the row under the point * * with bDnDMode true: * a) return the row which should be dropped on, which may * be different from the row the mouse is over in some backends where * positioning the mouse on the bottom half of a row indicates to drop * after the row * b) dnd highlight the dest row
*/ virtualbool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode, bool bAutoScroll = true)
= 0; virtualvoid unset_drag_dest_row() = 0; virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const = 0; // for dragging and dropping between TreeViews, return the active source virtual TreeView* get_drag_source() const = 0;
using Widget::set_sensitive; using Widget::get_sensitive;
};
/* A row is "activated" when the user double clicks a treeview row. It may also be emitted when a row is selected and Space or Enter is pressed.
a return of "true" means the activation has been handled, a "false" propagates the activation to the default handler which expands/collapses the row, if possible.
*/ void connect_item_activated(const Link<IconView&, bool>& rLink) { m_aItemActivatedHdl = rLink; }
// call func on each selected element until func returns true or we run out of elements virtualvoid selected_foreach(const std::function<bool(TreeIter&)>& func) = 0;
//all of them. Don't select when frozen, select after thaw. Note selection doesn't survive a freeze. virtualvoid select_all() = 0; virtualvoid unselect_all() = 0;
// return the number of toplevel nodes virtualint n_children() const = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.