Skip to content

Latest commit

 

History

46 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DesignKit Package

DesignKit is a Lazarus package that provides a set of visual and non‑visual components to enhance application UI design.
All components are installed on the Common Controls tab of the component palette.

Requirements

  • Lazarus (tested with 4.8) / Free Pascal Compiler 3.2.2 or newer.
  • LCL – included with Lazarus.
  • IDEIntf – included with Lazarus.
  • RichMemoPackage – a fork of the original TRichMemo component (available in plainlib).
  • Helpers – common utility units used by the spell‑checker (available in plainlib).
  • Toolkit – general‑purpose utility classes (available in plainlib).
  • RichKit – additional rich‑text utilities (available in plainlib).
  • Windows 8 or later is required only for the native WinSpellChecker backend. The HunSpell backend works on all platforms (Windows, Linux, macOS) and does not need any OS‑specific API.

TSpellChecker (Common Controls spellchecker)

sample_spellchecker

TSpellChecker is a non‑visual component that adds spell‑checking capabilities to a TRichMemo control. It supports both the native Windows Spell Checker (on Windows) and Hunspell (cross‑platform), with background checking, real‑time debounced updates, cancellation, and an automatic context menu with suggestions.

Features

  • Background spell checking with cancellation support.
  • Debounced real‑time checking (configurable delay).
  • Automatic application of error underlines (with AutoApply).
  • Built‑in context menu with spelling suggestions (replaces the word when a suggestion is chosen).
  • Integration with an external PopupMenu – suggestions can be placed directly in the menu or inside a submenu.
  • Supports Windows Spell Checker (seWindows) and Hunspell (seHunspell).
  • For Hunspell: loads dictionaries from files, streams, or automatically downloads them from a URL (LibreOffice dictionaries repository).
  • Chunked background checking of very large documents with incremental drawing of underlines, so errors appear at the top of the document while the rest is still being checked.
  • Option to check only the visible portion of the RichMemo (CheckVisibleOnly), with automatic re-check on scroll or text change. Works together with ChunkedCheck.
  • The chunked pass starts from the currently visible area, so the user sees fresh results where he is looking even when the document is scrolled far from the beginning.
  • Events: OnSpellCheckComplete (reports error count), OnContextPopup (allows custom handling).

Key Properties

Property Default Description
RichMemo nil The TRichMemo control to be spell‑checked.
Language '' BCP‑47 language tag (e.g. 'en-US', 'ru-RU').
Enabled True Enables/disables spell checking.
Options [scoSpelling] Set of TSpellCheckOptions (scoSpelling, scoComprehensive – Windows only).
AddEmptySuggestions True Include errors even if no suggestions are available.
RealTime False Automatically check after text changes (with debounce).
CheckDelay 1000 Debounce delay in milliseconds for real‑time checks.
AutoApply True Automatically apply underlines after a check completes.
AutoContextMenu True Automatically handle OnContextPopup to show suggestion menu.
PopupMenu nil An external TPopupMenu to integrate suggestions into (if nil, uses default behaviour).
SubMenu False If True, suggestions are placed in a submenu.
SubMenuCaption 'Suggestions' Caption of the submenu when SubMenu is True.
SubMenuIndex 0 Index where suggestions (or submenu) are inserted in PopupMenu.
Engine seWindows Spell engine: seWindows or seHunspell.
DicPath '' Directory for Hunspell dictionaries (absolute or relative to the application).
DicUrl 'https://raw.githubusercontent.com/plainlib/dictionaries/main/{plaindict}' URL template for downloading dictionaries. Placeholders: {dict} (language code + .aff/.dic), {plaindict} (flat dictionary name), {libredict} (LibreOffice internal path), {wooormdict} (Wooorm dictionary path).
ChunkedCheck False When True, large texts are checked in chunks and underlines are drawn incrementally while the background pass is still running. The pass starts from the currently visible area, then covers the text above and below.
ChunkSize 16384 Size of a single chunk in bytes (used when ChunkedCheck is True). The real chunk is extended to the next whitespace, so a word is never split in half. Minimum 256 at runtime, no minimum in the designer.
CheckVisibleOnly False When True, only the text currently visible in the RichMemo is checked. A polling timer re-runs the check whenever the visible range changes (scroll, resize, or text change), so the rest of the document is never touched. Can be combined with ChunkedCheck.

Events

Event Description
OnSpellCheckComplete Fired after a check finishes (and after underlines are applied, if AutoApply is True). Provides the number of errors found.
OnContextPopup Called before the component’s built‑in context menu handling. Set Handled to True to prevent the component from showing its menu.

Usage

  1. Place a TSpellChecker on a form.
  2. Assign its RichMemo property to a TRichMemo control.
  3. Set the Language property (e.g. 'en-US').
  4. Optionally set RealTime := True to enable live checking.
  5. At runtime, the component will automatically check the text and underline errors. Right‑click on a misspelled word to see suggestions.

Example for Hunspell with automatic download:

var
  Spell: TSpellChecker;
begin
  Spell := TSpellChecker.Create(Self);
  Spell.RichMemo := RichMemo1;
  Spell.Language := 'ru-RU';
  Spell.Engine := seHunspell;
  Spell.DicPath := '.\dictionaries'; // local folder
  Spell.DicUrl := 'https://raw.githubusercontent.com/LibreOffice/dictionaries/master/{libredict}';
  Spell.RealTime := True;
  Spell.CheckDelay := 800;
  Spell.AutoApply := True;
  Spell.ChunkedCheck := True;
  Spell.ChunkSize := 8192; // Roughly 2 to 4 pages
end;

If you want to use a custom PopupMenu with suggestions inserted directly:

Spell.PopupMenu := MyPopupMenu;
Spell.SubMenu := False; // suggestions appear directly in the menu
Spell.SubMenuIndex := 2; // insert after the second item

Chunked checking of large documents

By default the component checks the entire text in one background pass and applies all underlines at once. This is fine for short and medium documents, but on very large texts the user has to wait until the whole pass is finished before any error is highlighted.

Enable ChunkedCheck to split the text into pieces and draw underlines incrementally:

Spell.ChunkedCheck := True;
Spell.ChunkSize := 16384; // roughly 4 to 5 pages of Latin text

How it works:

  • The text is split at whitespace boundaries, so words are never cut in half. A chunk may be larger than ChunkSize if no whitespace is found within a reasonable distance.
  • As soon as the first chunk is processed, its errors are drawn. The user sees results at the top of the document while the rest is still being checked.
  • The pass starts from the area currently visible in the memo, then covers the text above it and finally the text below it. This way, if the user has scrolled to the middle of a long document, fresh underlines appear where he is looking first.
  • Existing underlines from the previous run are kept on screen during the pass and replaced atomically in a single operation at the end. This avoids flicker.
  • Total work stays linear in the number of errors: each chunk draws only its own newly found errors, and the final replace redraws everything once.

Suggested chunk sizes:

Language family Recommended ChunkSize Approximate size
Latin (English, etc.) 16384 – 32768 4 to 8 pages
Cyrillic (Russian) 8192 – 16384 2 to 4 pages
Any, "instant" feel 2048 half a page or less

The property is ignored when ChunkedCheck is False or when the text is shorter than ChunkSize.

During design time the minimum ChunkSize is relaxed to 1 so the behaviour can be tested word by word. At runtime the minimum is 256 to avoid pathological fragmentation.

Checking only the visible area

On very large documents even the chunked pass may spend time on parts the user is not looking at. Enable CheckVisibleOnly to restrict checking to the text that is currently visible in the RichMemo:

Spell.CheckVisibleOnly := True;

How it works:

  • The component polls the visible range every 200 ms. When the range changes (scroll, resize, or text change), the check is re-run for the new range only.
  • The visible range is extended to whole-word boundaries on both ends, so a word that is only partially visible is checked in full and never misreported as a fragment.
  • Only the visible portion is checked in each pass, so the result appears much faster on long documents. Errors outside the visible range are not highlighted until they are scrolled into view.
  • The mode can be combined with ChunkedCheck. If the visible range is larger than ChunkSize, it is still split into chunks and drawn incrementally.

When to use:

  • Large documents (many pages) where checking the whole text in the background would be wasteful.
  • Read-only or preview-style controls where the user mostly scrolls through the text.

When not to use:

  • Short texts where checking everything at once is already fast enough and the user expects the whole document to be highlighted.

The property has no effect while Enabled is False.


TFormGrip (Common Controls formgrip)

TFormGrip is a visual control that draws a size grip in a selected corner of its parent (a form or a panel) and resizes that parent when the grip is dragged. It behaves like the grip found in a StatusBar, but can be placed in any corner and styled freely.

The component does not hook or override any events of its parent. All mouse handling, painting, and resizing are performed inside the control itself, so the parent form's own OnPaint, OnMouseDown, OnMouseMove, OnMouseUp, and OnResize handlers remain untouched.

Features

  • Works with any TWinControl parent, not only with forms.
  • Grip can be placed in any of the four corners of the parent.
  • The control automatically snaps to the chosen corner and cannot be moved away from it; resizing or repositioning the parent keeps the grip in place.
  • Multiple grip drawing styles: dots (triangular arrangement), lines, grid, or solid triangle.
  • Background can either follow the parent colour (ParentColor = True, the default) or use its own Color.
  • Two independent offsets, named after the CSS box model: GripMargin moves the whole control away from the parent corner, while GripPadding insets the drawn pattern inside the control.
  • Resizing respects configurable minimum parent width and height.
  • Double buffered painting with csOpaque, so the grip redraws cleanly during parent resize without flicker or black artefacts.
  • In design time the grip is drawn but does not resize the parent.

Key Properties

Property Default Description
Visible True Shows or hides the grip.
ShowGrip True Controls drawing of the grip pattern.
GripCorner gcBottomRight Corner of the parent: gcBottomRight, gcBottomLeft, gcTopRight, or gcTopLeft.
GripMargin 0 Outer offset - distance between the control and the parent's corner (in pixels).
GripPadding 2 Inner offset - distance between the control's edge and the drawn pattern (in pixels).
GripColor clActiveBorder Colour used to draw the grip pattern.
GripStyle gsDots Drawing style: gsDots, gsLines, gsGrid, or gsSolid.
DotSize 2 Size of the dots (for gsDots and gsGrid).
DotSpacing 3 Distance between dots.
MinParentWidth 100 Minimum parent width allowed during resizing.
MinParentHeight 100 Minimum parent height allowed during resizing.
ParentColor True When True, background follows Parent.Color; otherwise uses Color.
Color clBtnFace Background colour used when ParentColor is False.
Width, Height 16, 16 Size of the grip control in pixels.

Usage

  1. Drop a TFormGrip component from the Common Controls palette onto a form or a panel.
  2. Choose the desired corner using GripCorner and adjust the remaining properties in the Object Inspector.
  3. At runtime the grip appears in the selected corner and resizes its parent when dragged.

Example code to create and configure TFormGrip at runtime:

var
  Grip: TFormGrip;
begin
  Grip := TFormGrip.Create(Self); // Self is the parent control
  Grip.Parent := Self;
  Grip.GripCorner := gcBottomRight;
  Grip.GripStyle := gsLines;
  Grip.GripColor := clGray;
  Grip.GripMargin := 0;
  Grip.GripPadding := 3;
  Grip.Width := 16;
  Grip.Height := 16;
end;

Class hierarchy

The component is split into two classes following the standard Lazarus convention:

  • TCustomFormGrip - base class that implements all behaviour. Inherit from it to create custom variants with your own published properties.
  • TFormGrip - ready-to-use component that publishes the most useful properties of TCustomFormGrip and of the inherited TControl.

TFlatButton (Common Controls flatbutton)

TFlatButton is a custom TSpeedButton descendant that always draws a flat, themed button (similar to toolbar buttons) and provides integrated tooltip support with extensive customisation.

Features

  • Always flat (inherited Flat property is hidden and forced to True).
  • Uses the native theme (via ThemeServices) for normal, hot, and pressed states.
  • Can optionally disable the pressed state drawing (DrawPressed).
  • Allows vertical offset of the caption relative to the icon (OffsetY).
  • Built‑in tooltip system with delay, size, colour, and auto‑hide duration.
  • Tooltips are displayed using TOneShotTooltip and automatically hide when the button is clicked or the tooltip is dismissed.

Key Properties

Property Default Description
DrawPressed True If False, the button never appears pressed (visual state is always normal or hot).
OffsetY 0 Vertical pixel offset for the caption relative to the centre of the icon (positive moves text down).
Tooltip '' The tooltip text to display (translatable caption).
TooltipDelay 0 Delay in milliseconds before the tooltip appears after a click (0 = immediate).
TooltipWidth 0 Width of the tooltip window (0 = auto‑size).
TooltipHeight 0 Height of the tooltip window (0 = auto‑size).
TooltipColor clDefault Background colour of the tooltip (clDefault uses system default).
TooltipDuration 0 Time in milliseconds after which the tooltip auto‑hides (0 = no auto‑hide).

Usage

Place a TFlatButton on a form, set an Images or Glyph for the icon, adjust Caption, and configure the tooltip properties.

Example:

var
  Btn: TFlatButton;
begin
  Btn := TFlatButton.Create(Self);
  Btn.Parent := Self;
  Btn.Caption := 'Save';
  Btn.ImageIndex := 0; // assume an ImageList assigned
  Btn.Tooltip := 'Save the current document';
  Btn.TooltipDelay := 500;
  Btn.TooltipDuration := 3000;
  Btn.OffsetY := 2; // move text slightly down
end;

Installation

  1. Open the package file (designkit.lpk) in Lazarus.
  2. Click Use → Install.
  3. Rebuild the IDE.

The components will appear on the Common Controls tab of the component palette.


DesignKit Package © 2026 by Alexander Tverskoy
Licensed under the MIT License – see the individual source files for details.

About

DesignKit is a Lazarus package that provides a set of visual and non‑visual components to enhance application UI design.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages