{"id":51624506,"url":"https://github.com/techsenger/shellfx","last_synced_at":"2026-07-12T23:30:20.108Z","repository":{"id":296624499,"uuid":"936262459","full_name":"techsenger/shellfx","owner":"techsenger","description":"Techsenger ShellFX  – A platform for building JavaFX applications using an extended MVP pattern.","archived":false,"fork":false,"pushed_at":"2026-07-06T12:19:14.000Z","size":9850,"stargazers_count":35,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-06T14:08:31.572Z","etag":null,"topics":["javafx","javafx-application","javafx-component","javafx-components","javafx-desktop-app","javafx-desktop-apps","javafx-gui","javafx-library","javafx-project","mvp","mvp-architecture","mvp-library","mvp-pattern"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/techsenger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"techsenger"}},"created_at":"2025-02-20T19:43:04.000Z","updated_at":"2026-07-06T12:19:33.000Z","dependencies_parsed_at":"2025-06-01T10:49:35.376Z","dependency_job_id":"f627ce27-a6c5-4fd8-939d-222d00def65b","html_url":"https://github.com/techsenger/shellfx","commit_stats":null,"previous_names":["techsenger/tabshell","techsenger/shellfx"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/techsenger/shellfx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techsenger%2Fshellfx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techsenger%2Fshellfx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techsenger%2Fshellfx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techsenger%2Fshellfx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/techsenger","download_url":"https://codeload.github.com/techsenger/shellfx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techsenger%2Fshellfx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35405750,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javafx","javafx-application","javafx-component","javafx-components","javafx-desktop-app","javafx-desktop-apps","javafx-gui","javafx-library","javafx-project","mvp","mvp-architecture","mvp-library","mvp-pattern"],"created_at":"2026-07-12T23:30:18.339Z","updated_at":"2026-07-12T23:30:20.101Z","avatar_url":"https://github.com/techsenger.png","language":"Java","funding_links":["https://github.com/sponsors/techsenger"],"categories":[],"sub_categories":[],"readme":"# Techsenger ShellFX\n\nTechsenger ShellFX is a platform for building JavaFX applications, where an application is structured\nas a tree of MVP components, each of which has its own lifecycle, history, etc. The platform provides abstract\nclasses for creating the main types of components: window, tab, area, page, dialog, and popup.\n\nIt also includes ready-to-use implementations of containers (including a docking layout) and dialogs (including a\nuniversal file chooser). In addition, the platform provides powerful devtools that allow you to inspect both the MVP\ncomponent tree and the underlying JavaFX scene graph. These tools make it easy to understand how the platform works\nand are invaluable during development.\n\nShellFX is built around two core subsystems: the dynamic main menu and the workspace. The main menu is assembled\nat runtime and automatically adapts to the currently focused component. The workspace provides the structural\nfoundation of the application and defines how components are arranged and interact visually. The platform supports\ndifferent types of workspace models.\n\n`ShellFX` is built according to the KISS principle. We aimed to keep it as simple as possible — with no magic and\nno overly complex solutions. For example, the platform is based on a slightly extended classic MVP pattern and provides\ncomponents for the core parts of an application, such as windows, tabs, dialogs, and others. The main idea was to\nallow developers to start working with the platform within a single day, and we believe this goal has been achieved.\n\nShellFX is built on top of the [PatternFX](https://github.com/techsenger/patternfx) framework.\n\n## Table of Contents\n* [Demo](#demo)\n    * [Workspaces](#demo-workspaces)\n    * [Pages](#demo-pages)\n    * [Dialogs](#demo-dialogs)\n    * [DevTools](#demo-devtools)\n* [Features](#features)\n* [When to Use?](#when-to-use)\n* [Modules](#modules)\n* [Component Overview](#component-overview)\n* [Core Components](#core)\n    * [Shell](#core-shell)\n    * [Window](#core-window)\n    * [Tab](#core-tab)\n    * [Page](#core-page)\n    * [Dialog](#core-dialog)\n    * [Popup](#core-popup)\n    * [Area](#core-area)\n* [Layout Components](#layout)\n    * [TabHost](#layout-tab-host)\n    * [DockHost](#layout-dock-host)\n    * [PageHost](#layout-page-host)\n    * [TreePageHost](#layout-tree-page-host)\n* [Shared Components](#shared)\n    * [FindBase](#shared-find-base)\n    * [FindPanel](#shared-find-panel)\n* [Dialog Components](#dialog)\n    * [AlertDialog](#dialog-alert)\n    * [FileChooserDialog](#dialog-file-chooser)\n    * [NameValueDialog](#dialog-name-value)\n* [DevTools Components](#devtools)\n    * [DevToolsTabDock](#devtools-tab-dock)\n    * [ComponentTab](#devtools-component-tab)\n    * [NodeTab](#devtools-node-tab)\n    * [EventTab](#devtools-event-tab)\n    * [StylesheetTab](#devtools-stylesheet-tab)\n    * [EnvironmentTab](#devtools-environment-tab)\n* [Extension Registries](#registries)\n    * [Control Registry](#registries-control)\n* [Naming Convention](#naming-convention)\n* [Quick Start](#quick-start)\n* [Requirements](#requirements)\n* [Dependencies](#dependencies)\n* [Code Building](#code-building)\n* [Running Demo](#running-demo)\n* [License](#license)\n* [Contributing](#contributing)\n* [Support Us](#support-us)\n\n## Demo \u003ca name=\"demo\"\u003e\u003c/a\u003e\n\n### Workspaces \u003ca name=\"demo-workspaces\"\u003e\u003c/a\u003e\n\n![ShellFX Workspace](https://raw.githubusercontent.com/techsenger/demo-media/main/1/1.png)\n\n![ShellFX Workspace](https://raw.githubusercontent.com/techsenger/demo-media/main/1/2.png)\n\n### Pages \u003ca name=\"demo-pages\"\u003e\u003c/a\u003e\n\n![ShellFX Pages](https://raw.githubusercontent.com/techsenger/demo-media/main/1/3.png)\n\n### Dialogs \u003ca name=\"demo-dialogs\"\u003e\u003c/a\u003e\n\n![ShellFX Pages](https://raw.githubusercontent.com/techsenger/demo-media/main/1/4.png)\n\n### DevTools \u003ca name=\"demo-devtools\"\u003e\u003c/a\u003e\n\n![ShellFX DevTools Components](https://raw.githubusercontent.com/techsenger/demo-media/main/1/5.png)\n\n![ShellFX DevTools Nodes](https://raw.githubusercontent.com/techsenger/demo-media/main/1/6.png)\n\n![ShellFX DevTools Events](https://raw.githubusercontent.com/techsenger/demo-media/main/1/7.png)\n\n## Features \u003ca name=\"features\"\u003e\u003c/a\u003e\n\nKey features of ShellFX include:\n\n* Dynamically configurable menu.\n* Support for different types of workspace.\n* Abstract classes to simplify component development.\n* A set of ready-made components that can be used out of the box.\n* Support for different layouts, including a docking layout.\n* Set of devtools for inspecting the application at both the component layer and the JavaFX scene graph layer.\n* Ability to preserve component history.\n* Support for inline popups and dialogs with two scopes — window and tab.\n* Window styling that matches the theme.\n* Support for 7 themes (4 dark and 3 light).\n* API for working with all colors in the palettes of all themes\n* Styling with CSS.\n\n## When to Use \u003ca name=\"when-to-use\"\u003e\u003c/a\u003e\n\nShellFX is well suited for medium to large JavaFX applications that require a structured UI architecture and\nflexible workspace management.\n\nIt is particularly effective for projects that:\n\n- Rely on a component-based MVP architecture.\n- Contain multiple tabs or require complex workspace layouts (including docking-based layouts).\n- Need dynamic menus, theming support, and centralized shell-level infrastructure.\n- Benefit from built-in DevTools for inspecting both the component tree and the JavaFX scene graph.\n\nShellFX provides a scalable foundation for applications where UI complexity grows over time and clear structural\nboundaries are essential.\n\nTypical application types include:\n\n- Enterprise systems managing different data entities.\n- Code editors and lightweight IDEs.\n- Database and query tools.\n- File managers and content browsers.\n- Monitoring and analytics dashboards.\n- Tools that require parallel workflows within multiple tabs or panels.\n\nThe tab-based approach allows users to maintain workflow context while switching between different tasks, making\ncomplex applications more intuitive and productive.\n\n## Modules\u003ca name=\"modules\"\u003e\u003c/a\u003e\n\nThe platform consists of the following modules:\n\n* Material — provides UI elements (menus, text areas, etc.) and supporting classes.\n* Core — includes the shell itself, base classes for component development, settings, and core utility classes.\n* Layout — offers abstract components for creating tabs with various layouts.\n* Shared — includes components that are used by other components from different modules.\n* Icons — contains the Material Design Icons font and module-specific stylesheets that utilize these icons. To use\ncustom icons instead, simply create your own stylesheets and add them to Shell.\n* Storage — provides abstractions for working with file systems. The module includes a default implementation for the\nlocal file system. Additional storage providers (for Google Drive, Dropbox, FTP, and similar) can be implemented\nseparately.\n* Dialogs — provides ready-to-use dialogs: alert, file chooser, confirmation etc.\n* DevTools — contains tools for exploring component tree and JavaFX scene graph.\n* Demo — showcases ShellFX's core functionality, provides examples for building custom components, and\npresents ready-made components.\n\n## Component Overview \u003ca name=\"component-overview\"\u003e\u003c/a\u003e\n\nThe following diagram shows the basic components, containers, and their implementations in the `core` and `layout`\nmodules:\n\n```mermaid\nclassDiagram\n\nclass Parent {\n    \u003c\u003cinterface\u003e\u003e\n}\n\nclass PageContainer {\n    \u003c\u003cinterface\u003e\u003e\n}\n\nclass TreePageContainer {\n    \u003c\u003cinterface\u003e\u003e\n}\n\nclass PopupContainer {\n    \u003c\u003cinterface\u003e\u003e\n}\n\nclass WindowContainer {\n    \u003c\u003cinterface\u003e\u003e\n}\n\nclass TabContainer {\n    \u003c\u003cinterface\u003e\u003e\n}\n\nclass AbstractParent\nclass AbstractChild\n\nclass AbstractArea\nclass AbstractPage\nclass AbstractPopup\n\nclass AbstractPageHost\nclass PageHost\nclass TreePageHost\n\nclass TabHost\nclass TabDock\n\nclass AbstractWindow\nclass AbstractDialog\nclass AbstractHostWindow\nclass DefaultShell\n\nclass AbstractTab\nclass AbstractHostTab\n\nParent \u003c|-- PageContainer\nParent \u003c|-- TreePageContainer\nParent \u003c|-- PopupContainer\nParent \u003c|-- TabContainer\n\nPopupContainer \u003c|-- WindowContainer\n\nParent \u003c|.. AbstractParent\n\nAbstractParent \u003c|-- AbstractChild\n\nAbstractChild \u003c|-- AbstractArea\nAbstractChild \u003c|-- AbstractWindow\nAbstractChild \u003c|-- AbstractTab\n\nAbstractArea \u003c|-- AbstractPage\nAbstractArea \u003c|-- AbstractPopup\nAbstractArea \u003c|-- AbstractPageHost\nAbstractArea \u003c|-- TabHost\n\nAbstractPageHost \u003c|-- PageHost\nAbstractPageHost \u003c|-- TreePageHost\n\nTabHost \u003c|-- TabDock\n\nAbstractWindow \u003c|-- AbstractDialog\nAbstractWindow \u003c|-- AbstractHostWindow\n\nAbstractHostWindow \u003c|-- DefaultShell\n\nAbstractTab \u003c|-- AbstractHostTab\n\nPageContainer \u003c|.. PageHost\nTreePageContainer \u003c|.. TreePageHost\n\nTabContainer \u003c|.. TabHost\n\nWindowContainer \u003c|.. AbstractHostWindow\nWindowContainer \u003c|.. AbstractHostTab\n\n%% composition: 0..N TabDock inside TabDockHost\nDockHost \"1\" o-- \"0..*\" TabDock\nAbstractArea \u003c|-- DockHost\n```\n\n## Core Components \u003ca name=\"core\"\u003e\u003c/a\u003e\n\nThese components form the architectural foundation of the platform, and all higher-level platform components are built\nupon them.\n\nShellFX is built on top of the PatternFX platform, which supports working both with and without a component tree.\nIn ShellFX, all components form a tree structure, and multiple trees may exist depending on the number of `Window`s.\nFor this reason, all ShellFX core components inherit from the `Parent` and `Child` components provided by PatternFX.\n\nEach component is defined by an interface accompanied by a base implementation. This approach ensures loose coupling\nwhile still providing default implementations out of the box. It also allows developers to replace or extend the default\nbehavior with custom implementations when required. For instance, the platform consistently references `Shell`\nthrough the `ShellFxView` interface rather than a concrete class.\n\nWhen working with components, there are several important points to keep in mind:\n\n1. The developer must control the component lifecycle. Component initialization is performed either manually or in\nthe `open*` or `show*` methods of `Composer`, which may delegate this logic to `create*` methods (using `create*`\nmethods makes it easy to replace the component being created). Component deinitialization is performed either manually\nor in the `close*` or `hide*` methods of `Composer`. See [Naming Convention](#naming-convention) for details.\n\n2. Working with components involves maintaining two hierarchies — the component tree and the JavaFX scene graph.\nTherefore, any addition or removal of a component must be reflected in both structures. For example, removing a component\nfrom the node tree without removing it from the component tree will result in a memory leak. DevTools provide the ability\nto inspect and monitor both hierarchies.\n\n### Shell \u003ca name=\"core-shell\"\u003e\u003c/a\u003e\n\n`Shell` is the main and top-level component. It extends the `HostWindow` component and inherits its responsibilities for\nmanaging the JavaFX `Stage` and window-level infrastructure. In addition, `Shell` defines the primary application\nstructure and user experience layer.\n\nIt is responsible for the following tasks:\n\n* Dynamic menu management.\n* Workspace management.\n* Context management.\n\nThe Shell core does not contain any business logic. It is only a shell for other components that contain logic.\n\nWorking with the main menu of the `Shell` is carried out in two directions:\n\n1. Configuring menu elements\n2. Managing the state of elements and responding to user actions\n\nThe configuration of menu elements is performed dynamically and in any order, with the final result being unknown in\nadvance. This feature is crucial in cases where plugins/extensions are used, as they can be added/removed dynamically by\nthe user. Each plugin may introduce its own menu items and interact with existing menus. Therefore, it is impossible\nto predict the final structure of the menu that the user will work with.\n\nThe implementation of this feature is structured as follows. There are three key elements: the menu, the group, and the\nitem. Each element has its own name, which is used for identification. A menu consists of groups separated by a\nseparator. Items are added to groups, and empty groups are ignored. The factories of all three elements are\nregistered/unregistered in the `ControlRegistry`. When the menu needs to be updated, this `ControlRegistry` is used\nby `Shell` to construct the final menu. See [ControlRegistry](#registries-control) for details.\n\nThe `MenuManager` is responsible for managing the state of menu elements and responding to their actions. It\ninteracts with a component that provides a port implementing the `MenuAwarePort` interface.\n\nThe algorithm works as follows. First, the component that has focus is determined. The `Shell` tracks changes to\nthe focused node using `Scene#focusOwnerProperty()`. When this property changes, the component that owns the node is\nidentified, and the result is stored in `ShellFxView#focusedProperty()`. Note that if a component should become focused\nwhen the user clicks on an empty area of that component (for example, a `Pane`), you must explicitly call\n`pane.requestFocus()`.\n\nAt the same time, the focused component may not participate in menu formation (for example, it could be just a toolbar).\nTherefore, after the focused component changes, `Shell` searches from the focused component up to the root of the\ntree — the Shell — for the first component whose port implements `MenuAwarePort`. Note that `Shell` can also form\nthe main menu, but this is usually done only when the workspace is empty. See also `ShellFxView#menuAwareProperty()`.\n\nIt is also important to remember that the `MenuManager` also interacts with `MenuAwarePort` when the user uses accelerators.\n\nTo gain a complete understanding of working with the menu, it is recommended to familiarize yourself with the\n`MenuAwarePort` interface, experiment with the menu in the demo, and pay attention to log messages at the debug level.\n\nThe second key part of ShellFX is the workspace, which represents one of the available layouts. ShellFX supports\ndifferent types of workspace:\n\n1. Browser-like. This workspace is created using the `TabHost` component with a flag indicating that it is a workspace.\nAdditionally, the tabs added to this `TabHost` contain a docking layout created with the `DockHost` component.\n2. IDE-like. This workspace is a straightforward docking layout created with the `DockHost` component.\n\n### Window \u003ca name=\"core-window\"\u003e\u003c/a\u003e\n\n`Window` is one of the core components of the platform and is available in two variants: `WindowType#NESTED` and\n`WindowType#TOP_LEVEL`.\n\n`NESTED` windows are internal windows managed by `WindowManager`. `WindowManager` allows an unlimited number of\nwindows to be opened simultaneously, tracks the active window, manages window state, and provides various window\narrangement operations such as cascade, tile, and others.\n\nThe platform provides two implementations of window hosts: `HostWindow` and `HostTab`. This allows nested windows\nto be displayed either inside another window or inside a tab. The latter approach is particularly useful for\ntab-based applications, where each tab can maintain its own set of dialogs and auxiliary windows, similar to\nhow modern web browsers isolate dialogs and popups per tab.\n\n`TOP_LEVEL` windows are created in a separate `Stage` and are integrated with the operating system's windowing environment.\n\nDespite their different implementations, both `NESTED` and `TOP_LEVEL` windows are accessed through the same API.\nAs a result, components built on top of `Window` (such as dialogs, wizards, or utility windows) can be displayed\neither inside the application or in separate system windows without any changes to application code. This allows\nwindow-based components to be implemented once and reused with any window type.\n\n### Tab \u003ca name=\"core-tab\"\u003e\u003c/a\u003e\n\n`Tab` is an abstract component used for creating custom tab implementations. In ShellFX, `Tab` is one of the central\nplatform components, since the primary application functionality is delivered through tabs.\n\n`Tab` can be added to any component that implements the `TabContainer` interface. The platform\nprovides two components that implement this interface: `TabHost` and `TabDock`, where `TabDock` extends `TabHost`.\n\n### Page \u003ca name=\"core-page\"\u003e\u003c/a\u003e\n\n`Page` is a component that represents a titled, selectable element. A key feature of this component is its lazy\ninitialization. For example, if a container displays one of N `Page`s, only the `Page` that the user actually chooses to\nview will be initialized.\n\n`Page` can be added to any component that implements the `PageContainer` interface. The default implementation of\nthis interface is `PageHost`.\n\n### Dialog \u003ca name=\"core-dialog\"\u003e\u003c/a\u003e\n\n`Dialog` inherits `Window` and is a specialized component designed for user interaction and result acquisition.\nSince `Dialog` inherits `Window`, it can be displayed in any environment that supports windows and uses the same\nAPI as regular windows.\n\nAll dialogs in ShellFX are asynchronous. Opening a dialog does not block the application's execution flow or freeze\nthe user interface. Instead, user responses are delivered through callbacks, events, observable properties, or\nother asynchronous mechanisms. This approach keeps the UI responsive and simplifies background processing.\n\nDialogs can be displayed either as `NESTED` or `TOP_LEVEL` windows. Nested dialogs are rendered within a\n`WindowContainer` and appear as an integral part of the application's user interface. Top-level dialogs are displayed\nin a separate `Stage` and are integrated with the operating system's windowing environment.\n\nNested dialogs can be displayed in any implementation of `WindowContainer`. The platform provides two implementations:\n`HostWindow` and `HostTab`. This allows dialogs to be associated either with a window or with a specific tab.\nFor example, in a browser-like application, each tab can maintain its own set of dialogs and auxiliary windows,\nisolated from all other tabs.\n\n### Popup \u003ca name=\"core-popup\"\u003e\u003c/a\u003e\n\nAll `Popup`s in ShellFX are inline and have a scope that affects what will be blocked when the `Popup` is open.\n\nInline `Popup`s are components that appear embedded within the current application window, typically overlaid on top\nof the existing content. They are contextually tied to a specific section (e.g., a `Shell` or `Tab`) and do not\ncreate a separate OS-level window. In contrast, modal window `Popup`s (or native `Popup`s) open as standalone\nOS-managed windows with their own frames and system controls, completely independent of the parent UI.\n\nThere are two types of scope: `Window` and `Tab`. `Popup`s in the `Tab` scope are bound to a specific tab and are visible\nonly while that tab is open. `Popup`s in the `Window` scope are global to the `Window` and remain visible even when all\ntabs are closed.\n\n`Popup` can be added to any component that implements the `PopupContainer` interface. The platform provides two\ncomponents that implement this interface: `Tab` and `Window`.\n\n### Area \u003ca name=\"core-area\"\u003e\u003c/a\u003e\n\n`Area` is an abstract base component that represents a rectangular region. Naturally, `AreaFxView#getNode()` returns a\n`Region`.\n\n## Layout Components \u003ca name=\"layout\"\u003e\u003c/a\u003e\n\nLayout components are responsible for arranging `Tab`, `Page`, and, in some cases, `Area` components and their derivatives.\n\n### TabHost \u003ca name=\"layout-tab-host\"\u003e\u003c/a\u003e\n\n`TabHost` is the primary component that can contain `Tab` components; therefore, it implements the `TabContainer` interface.\nThis component provides all the necessary APIs for working with tabs — adding, selecting, removing, transferring\ntab ports, and more.\n\n### DockHost \u003ca name=\"layout-dock-host\"\u003e\u003c/a\u003e\n\n`DockHost` is the main component of the docking layout and one of the most complex components in the platform.\nBefore describing how it works, let’s examine its child components.\n\n`SplitSpace` is a component that extends `Area`. It internally contains a `SplitPane` node and is responsible for\narranging child components either vertically or horizontally.\n\n`TabDock` extends `TabHost`, meaning it can contain tabs. In addition, it introduces docking-specific functionality\nsuch as dragging an entire `TabDock` from one layout position to another, collapsing it into a `SideBar`, and\nsimilar behaviors.\n\n`SideBar` is a component that displays collapsed `TabDock` instances. It is important to note that a `SideBar` can\nbe shown even when it contains no collapsed `TabDock` components, using `SideBarPolicy`. This is useful when the\n`SideBar` is intended to host additional UI elements besides collapsed `TabDock`s.\n\nNow that the components are introduced, let’s outline how everything works together. A docking layout is always\nrepresented as a tree. Therefore, the layout must be constructed using `SplitSpace` nodes. A `SplitSpace` can contain\nother `SplitSpace` instances (to change orientation), `TabDock` instances (to host `Tab`s), or any `Area`-based\ncomponent as a leaf node. After constructing the component tree, the method `Composer#setRoot(SplitSpaceFxView\u003c?\u003e)`\nmust be called.\n\nIn addition to building the component tree, `DockHost` requires specifying the main component — the component relative\nto which all other components are positioned. The main component can be an `Area` or any class derived from it\n(including `TabDock` and `SplitSpace`). It is set using the method `Composer#setMain(AreaFxView\u003c?\u003e)`.\n\n### PageHost \u003ca name=\"layout-page-host\"\u003e\u003c/a\u003e\n\n`PageHost` is a simple component that displays `Page` components and performs their lazy initialization.\nIt can be used to display navigable pages with a flat menu-like structure in diffent components - tabs, dialogs etc.\n\n### TreePageHost \u003ca name=\"layout-tree-page-host\"\u003e\u003c/a\u003e\n\n`TreePageHost` is almost identical to `PageHost`, except for the menu structure: `PageHost` uses a flat menu\n(`ListView`), whereas `TreePageHost` uses a hierarchical menu (`TreeView`).\n\n## Shared Components \u003ca name=\"shared\"\u003e\u003c/a\u003e\n\nShared components are auxiliary components built on top of Core components and used by components from other modules.\n\n### FindBase \u003ca name=\"shared-find-base\"\u003e\u003c/a\u003e\n`FindBase` is an abstract base search component that contains the entire search view implementation, including both\nsubmit search and instant search functionality. Since child components may be of different types (toolbar, panel, etc.),\nthis component includes only minimal CSS styling. It is important to note that this component does not contain any\nlogic for executing the search itself. At the same time, the base `*FindPort` interfaces are provided without\nimplementations.\n\n### FindPanel \u003ca name=\"shared-find-panel\"\u003e\u003c/a\u003e\n`FindPanel` is an abstract class for find panels that are placed at the bottom of other components. It is important\nto note that this component does not contain any logic for executing the search itself.\n\n## Dialog Components \u003ca name=\"dialog\"\u003e\u003c/a\u003e\n\nIn this section, the dialogs from the `dialogs` module are described. This module contains implementations of the most\ncommonly used dialogs.\n\n### AlertDialog \u003ca name=\"dialog-alert\"\u003e\u003c/a\u003e\n\n`AlertDialog` is a dialog for common user notification scenarios such as informational messages, warnings, errors,\nand confirmation requests.\n\n### FileChooserDialog \u003ca name=\"dialog-file-chooser\"\u003e\u003c/a\u003e\n\n`FileChooserDialog` is a dialog for selecting a file when opening or saving. The dialog type is defined using the\n`FileChooserType` enumeration.\n\nIt is important to note that this dialog works with files provided by classes from the `storage` module. This makes\nit possible to use the dialog with virtually any file storage implementation, provided that an appropriate `FileStorage`\nimplementation is supplied.\n\n### NameValueDialog \u003ca name=\"dialog-name-value\"\u003e\u003c/a\u003e\n\n`NameValueDialog` is a simple dialog for displaying name–value pairs. The parameter name is shown in a `TextField`,\nwhile the value is displayed in a `TextArea`.\n\n## DevTools Components \u003ca name=\"devtools\"\u003e\u003c/a\u003e\n\nDevTools components are tools for inspecting and analyzing the application at two levels: the component tree and\nthe JavaFX scene graph. They are primarily intended for developers building components on top of the platform.\n\n### DevToolsTabDock \u003ca name=\"devtools-tab-dock\"\u003e\u003c/a\u003e\n\nThis component is a container for `Tab` components and provides shared tab management mechanisms. It can be added to\nany layout, whether a simple layout or a docking layout.\n\n### ComponentTab \u003ca name=\"devtools-component-tab\"\u003e\u003c/a\u003e\n\nThis component allows exploring the tree of active components and inspecting their properties. In addition, it\nprovides information about the class hierarchy of the selected component.\n\n### NodeTab \u003ca name=\"devtools-node-tab\"\u003e\u003c/a\u003e\n\n`NodeTab` is a tool for analyzing the JavaFX scene graph. It allows traversing the node tree and inspecting node\nproperties. The component also enables opening reference documentation (Javadoc) for both classes and their properties.\n\n### EventTab \u003ca name=\"devtools-event-tab\"\u003e\u003c/a\u003e\n\nThis component allows recording node events. It can operate with or without filters. Events can be filtered by\nselected component, message, event type, and other criteria.\n\n### StylesheetTab \u003ca name=\"devtools-stylesheet-tab\"\u003e\u003c/a\u003e\n\nThis component allows inspecting which stylesheets are applied to nodes within the scene.\n\n### EnvironmentTab \u003ca name=\"devtools-environment-tab\"\u003e\u003c/a\u003e\n\nThis component provides access to platform settings, system properties, and environment variables.\n\n## Extension Registries \u003ca name=\"registries\"\u003e\u003c/a\u003e\n\nAn extension registry is a runtime mechanism that allows components, plugins, and modules to dynamically contribute\nfunctionality to the platform without introducing direct compile-time dependencies between components. Extensions can\nbe added or removed at runtime, and registrations may occur in any order.\n\n### Control Registry \u003ca name=\"registries-control\"\u003e\u003c/a\u003e\n\n`ControlRegistry` manages UI control contributions such as menus, menu groups, and menu items. This registry is used\nto manage Shell’s main menu.\n\nHowever, this registry does not assemble final UI controls. For example, it does not create a `ToolBar`. Instead, it\nonly stores metadata about elements that can later be used to construct UI components such as toolbars. The assembly of\nfinal control elements is handled by user-defined or default builders, such as `MenuBuilder.\n\n## Naming Convention \u003ca name=\"naming-convention\"\u003e\u003c/a\u003e\n\nShellFX is built on top of PatternFX and fully conforms to its patterns. Because of this, the naming of classes and\ninterfaces for components follows a consistent scheme:\n\n1. A unique name (may be omitted for brevity) — `Alert`, `File`, `Info`, etc.\n2. The component role — `Tab`, `Window`, `Popup`, `Area`, `Panel`, `ToolBar`, etc.\n3. The component element — `View`, `Presenter`, `FxView`, `Params`, `Port`, `History` etc.\n\nExamples: `AlertDialogFxView`, `EditorTabPresenter`, `InfoPopupParams`, `ToolBarPort`\n\nThis approach is justified by the following reasons. When a complex component is split into multiple components\n(due to complexity, reuse of components, or use of a docking layout), there may be several components with the same\nunique name but different roles — such as `FooTab` and `FooArea`. Another reason is that the role of a component\nimmediately makes it clear how to work with it and where to place it.\n\nWhen working with `Composer` methods, there are two categories of methods:\n\n1. Methods that create/destroy a component and compose/decompose it. It is important to note that these methods\nmanage the component lifecycle, meaning they are responsible for component initialization and deinitialization.\nSuch methods include: `open*`, `close*`, `show*`, and `hide*`.\n\n2. Methods that only compose/decompose a component. These methods are responsible solely for structural component\ncomposition and do not manage the component lifecycle. Such methods include: `add*`, `remove*`, and `replace*`.\n\nExamples of `Composer` methods using `open*` and `close*`:\n\n| Component | Create + Add         | Remove + Destroy      | Add Only            | Remove Only            |\n|-----------|----------------------|-----------------------|---------------------|------------------------|\n| Window    | `openWindow(params)` | `closeWindow(window)` | `addWindow(window)` | `removeWindow(window)` |\n| Tab       | `openTab(params)`    | `closeTab(tab)`       | `addTab(tab)`       | `removeTab(tab)`       |\n| Dialog    | `openDialog(params)` | `closeDialog(dialog)` | `addDialog(dialog)` | `removeDialog(dialog)` |\n| Popup     | `openPopup(params)`  | `closePopup(popup)`   | `addPopup(popup)`   | `removePopup(popup)`   |\n| Page      | `openPage(params)`   | `closePage(page)`     | `addPage(page)`     | `removePage(page)`     |\n| Area      | `openArea(params)`   | `closeArea(area)`     | `addArea(area)`     | `removeArea(area)`     |\n\n## Quick Start \u003ca name=\"quick-start\"\u003e\u003c/a\u003e\n\nTo get started with ShellFX, it is recommended to follow these steps:\n\n1. Familiarize yourself with the [PatternFX](https://github.com/techsenger/patternfx) framework,\nthe [MVP](https://github.com/techsenger/patternfx#templates-mvp) template, and its demo.\n2. Explore and run the demo. See [Running Demo](#running-demo) for details.\n\n## Requirements \u003ca name=\"requirements\"\u003e\u003c/a\u003e\n\nThe library requires Java 25 and JavaFX 25.\n\n## Dependencies \u003ca name=\"dependencies\"\u003e\u003c/a\u003e\n\nThis project is available on Maven Central. Minimal set of required dependencies:\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.techsenger.shellfx\u003c/groupId\u003e\n    \u003cartifactId\u003eshellfx-material\u003c/artifactId\u003e\n    \u003cversion\u003e${shellfx.version}\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.techsenger.shellfx\u003c/groupId\u003e\n    \u003cartifactId\u003eshellfx-core\u003c/artifactId\u003e\n    \u003cversion\u003e${shellfx.version}\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.techsenger.shellfx\u003c/groupId\u003e\n    \u003cartifactId\u003eshellfx-layout\u003c/artifactId\u003e\n    \u003cversion\u003e${shellfx.version}\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.techsenger.shellfx\u003c/groupId\u003e\n    \u003cartifactId\u003eshellfx-icons\u003c/artifactId\u003e\n    \u003cversion\u003e${shellfx.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Code Building \u003ca name=\"code-building\"\u003e\u003c/a\u003e\n\nTo build the library use standard Git and Maven commands:\n\n    git clone https://github.com/techsenger/shellfx\n    cd shellfx\n    mvn clean install\n\n## Running Demo \u003ca name=\"running-demo\"\u003e\u003c/a\u003e\n\nTo run the demo, execute the following commands in the project root:\n\n    cd shellfx-demo\n    mvn javafx:run\n\nPlease note, that debugger settings are in `pom.xml` file.\n\n## License \u003ca name=\"license\"\u003e\u003c/a\u003e\n\nTechsenger ShellFX is licensed under the Apache License, Version 2.0.\n\n## Contributing \u003ca name=\"contributing\"\u003e\u003c/a\u003e\n\nWe welcome all contributions. You can help by reporting bugs, suggesting improvements, or submitting pull requests\nwith fixes and new features. If you have any questions, feel free to reach out — we’ll be happy to assist you.\n\n## Support Us \u003ca name=\"support-us\"\u003e\u003c/a\u003e\n\nYou can support our open-source work through [GitHub Sponsors](https://github.com/sponsors/techsenger).\nYour contribution helps us maintain projects, develop new features, and provide ongoing improvements.\nMultiple sponsorship tiers are available, each offering different levels of recognition and benefits.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechsenger%2Fshellfx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechsenger%2Fshellfx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechsenger%2Fshellfx/lists"}