|
|
11 月之前 | |
|---|---|---|
| .. | ||
| Definitions | 11 月之前 | |
| Samples | 11 月之前 | |
| readme.md | 11 月之前 | |
| ui-layout-def.xsd | 11 月之前 | |
Version: 1.1
Documentation Version: 1.1
Author: Dalibor Votruba
URL: quadarax.com/ui-layout-def
A comprehensive XML-based format for describing user interface layouts with inheritance, pattern definitions, view organization, and platform-specific extensions. This format enables cross-platform UI generation with strict validation and modular component libraries.
The UI Layout Definition Format provides a standardized way to define user interfaces that can be translated to various platforms (Windows Forms, WPF, Qt, Web, Mobile). It emphasizes:
Views represent logical business functions (ProductView, OrderView) that group related windows and define shared data context and behaviors.
All controls and structures must be defined in the <patterns> section before use in windows.
Wireframes use slots as placeholders that windows can fill with specific content.
Comprehensive validation rules ensure UI consistency and platform compliance.
<?xml version="1.0" encoding="UTF-8"?>
<ui-layout-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="ui-layout-definition ui-layout-def.xsd">
<!-- Optional: Validation rules with external includes -->
<validation-rules>
<validation-include src="..." important="true/false" />
<rule name="...">...</rule>
</validation-rules>
<!-- Required: Pattern definitions with external includes -->
<patterns>
<pattern-include src="..." important="true/false" />
<control name="...">...</control>
<structure name="...">...</structure>
<wireframe name="...">...</wireframe>
</patterns>
<!-- NEW: View definitions with external includes -->
<views>
<view-include src="..." important="true/false" />
<view name="..." type="..." category="..." inherits="...">...</view>
</views>
<!-- Required: One or more window definitions -->
<window name="..." title="..." wireframe="..." view="...">
<!-- Window content -->
</window>
</ui-layout-def>
Views are logical containers that group related windows, dialogs, and UI components that work together for a specific business function. They provide:
<view name="ProductView" type="business-entity" category="core" inherits="BaseEntityView">
<description>Product management functionality including listing, editing, and details</description>
<!-- View metadata for code generation -->
<metadata>
<model-class>Product</model-class>
<view-model-class>ProductViewModel</view-model-class>
<controller-class>ProductController</controller-class>
<permissions>product.read,product.write</permissions>
</metadata>
<!-- View dependencies -->
<dependencies>
<view-ref name="CategoryView" relationship="lookup" required="false" />
<view-ref name="SupplierView" relationship="reference" required="false" />
<shared-component name="FileUploadComponent" required="true" />
</dependencies>
<!-- Shared data context -->
<data-context>
<property name="currentProduct" type="Product" scope="view" />
<property name="productList" type="ProductList" scope="view" />
<property name="selectedCategory" type="Category" scope="shared" />
</data-context>
<!-- Window associations -->
<windows>
<window-ref name="ProductListWindow" role="main" default="true" />
<window-ref name="ProductEditDialog" role="editor" modal="true" />
<window-ref name="ProductDetailsWindow" role="viewer" />
</windows>
<!-- View-level navigation -->
<navigation>
<action name="show-list" target="ProductListWindow" />
<action name="edit-product" target="ProductEditDialog" context="currentProduct" />
<action name="view-details" target="ProductDetailsWindow" context="currentProduct" />
</navigation>
<!-- Shared behaviors -->
<behaviors>
<behavior name="refresh-data" scope="view" />
<behavior name="validate-product" scope="view" />
<behavior name="save-changes" scope="view" />
</behaviors>
</view>
View Types:
business-entity - Product, Order, Customer managementprocess-flow - OrderProcessing, Checkout workflowsdashboard - MainDashboard, ReportsViewutility - Settings, UserPreferenceswizard - Setup wizards, guided processescomposite - Views composed of multiple sub-viewsmodule - Application modules containing multiple viewsCategories:
core - Essential business functionalityadmin - Administrative functionsreporting - Reports and analyticssystem - System-level functionalityframework - Base views for inheritance<!-- Base entity view -->
<view name="BaseEntityView" type="base" category="framework">
<windows>
<window-ref name="BaseListWindow" role="main" />
<window-ref name="BaseEditDialog" role="editor" />
</windows>
<navigation>
<action name="show-list" target="BaseListWindow" />
<action name="edit-entity" target="BaseEditDialog" />
</navigation>
<behaviors>
<behavior name="refresh-data" />
<behavior name="save-changes" />
</behaviors>
</view>
<!-- Inherited view -->
<view name="ProductView" inherits="BaseEntityView">
<!-- Inherits all windows, navigation, and behaviors from BaseEntityView -->
<!-- Can override or extend with additional functionality -->
<windows>
<!-- Additional product-specific windows -->
<window-ref name="ProductCatalogWindow" role="catalog" />
</windows>
<navigation>
<!-- Override base action -->
<action name="edit-entity" target="ProductEditDialog" context="currentProduct" />
<!-- Add new action -->
<action name="view-catalog" target="ProductCatalogWindow" />
</navigation>
</view>
<dependencies>
<!-- Lookup relationship - uses other view for data selection -->
<view-ref name="CategoryView" relationship="lookup" required="false">
<interaction type="select-category" returns="category-id" />
</view-ref>
<!-- Master-detail relationship -->
<view-ref name="OrderItemView" relationship="detail" required="true">
<interaction type="manage-items" context="current-order" />
</view-ref>
<!-- Reference relationship - shows related data -->
<view-ref name="CustomerView" relationship="reference" required="false">
<interaction type="view-customer" context="customer-id" />
</view-ref>
<!-- Shared component dependency -->
<shared-component name="AddressComponent" required="true" />
<shared-component name="NotificationService" required="true" />
</dependencies>
<view name="OrderManagementView" type="composite" category="core">
<description>Complete order management including orders, items, and customer details</description>
<!-- Composed views -->
<composed-views>
<view-ref name="OrderView" role="primary" layout-slot="main-content" />
<view-ref name="OrderItemView" role="detail" layout-slot="items-panel" />
<view-ref name="CustomerView" role="reference" layout-slot="customer-panel" />
</composed-views>
<!-- Composite layout -->
<layout wireframe="CompositeViewLayout">
<slot name="main-content" view="OrderView" />
<slot name="items-panel" view="OrderItemView" />
<slot name="customer-panel" view="CustomerView" />
</layout>
<!-- Cross-view coordination -->
<coordination>
<rule when="OrderView.order-selected" then="OrderItemView.load-items" />
<rule when="OrderView.customer-changed" then="CustomerView.load-customer" />
</coordination>
</view>
<control name="Button" type="action" category="basic">
<constraints>
<allowed-parents>Panel,FormField</allowed-parents>
<allowed-children>none</allowed-children>
<container>false</container>
</constraints>
<attributes>
<attribute name="text" type="string" default="Button" required="true" />
<attribute name="enabled" type="bool" default="true" />
<attribute name="style" type="enum" values="normal,primary,danger" default="normal" />
</attributes>
<behavior>
<event name="click" required="true" />
</behavior>
</control>
<structure name="FormField" type="pattern" category="composite">
<constraints>
<allowed-parents>Panel</allowed-parents>
<required-slots>input</required-slots>
</constraints>
<attributes>
<attribute name="label-text" type="string" required="true" />
<attribute name="required" type="bool" default="false" />
</attributes>
<template>
<Panel name="fieldContainer">
<Label name="fieldLabel" text="{label-text}" />
<slot name="input" allowed-controls="TextBox,ComboBox" required="true" />
<Label name="validationLabel" visible="false" color="#ff0000" />
</Panel>
</template>
</structure>
<wireframe name="StandardAppLayout" type="base-layout">
<description>Standard application layout with header, sidebar, content, footer</description>
<template>
<Panel name="rootContainer">
<Panel name="headerPanel" height="60">
<slot name="header-content" default="true">
<Label name="appTitle" text="Application Title" />
</slot>
</Panel>
<Panel name="mainContainer" orientation="horizontal">
<Panel name="sidebarPanel" width="250">
<slot name="sidebar-content" />
</Panel>
<Panel name="contentPanel" fill="true">
<slot name="main-content" required="true" />
</Panel>
</Panel>
<Panel name="footerPanel" height="30">
<slot name="footer-content" default="true">
<Label name="statusLabel" text="Ready" />
</slot>
</Panel>
</Panel>
</template>
</wireframe>
Windows can inherit from wireframe layouts and override specific slots:
<window name="MainWindow" title="Main Application" wireframe="StandardAppLayout" view="MainView">
<attributes>
<attribute name="width" value="800" />
<attribute name="height" value="600" />
</attributes>
<view-properties>
<role>main</role>
<default>true</default>
<data-context-binding>mainData</data-context-binding>
</view-properties>
<slot-overrides>
<slot name="header-content">
<Label name="appTitle" text="My Application" />
<Button name="settingsButton" text="Settings" />
</slot>
<slot name="main-content">
<Panel name="dashboardPanel">
<!-- Main content here -->
</Panel>
</slot>
</slot-overrides>
</window>
<window name="WindowName" title="Window Title" wireframe="OptionalWireframe" view="AssociatedView">
<attributes>
<attribute name="width" value="800" />
<attribute name="height" value="600" />
<attribute name="resizable" value="true" />
<attribute name="modal" value="false" />
</attributes>
<!-- NEW: View properties -->
<view-properties>
<role>main</role>
<default>true</default>
<modal>false</modal>
<data-context-binding>entityData</data-context-binding>
<parent-window>ParentWindow</parent-window>
</view-properties>
<!-- For wireframe-based windows -->
<slot-overrides>
<slot name="content">
<!-- Slot content -->
</slot>
</slot-overrides>
<!-- For direct layout windows -->
<Panel name="mainPanel">
<!-- Direct content -->
</Panel>
</window>
<validation-rules>
<!-- View-specific validation rules -->
<rule name="view-window-association">
<description>All windows must be associated with a view</description>
<constraint>Every window must be referenced by at least one view</constraint>
</rule>
<rule name="view-dependency-validation">
<description>View dependencies must be valid</description>
<constraint>Referenced views in dependencies must be defined</constraint>
</rule>
<rule name="view-inheritance-validation">
<description>View inheritance must be valid</description>
<constraint>Inherited views must be defined and compatible</constraint>
</rule>
<rule name="data-context-consistency">
<description>Data context properties must be consistently typed</description>
<constraint>Shared properties across views must have compatible types</constraint>
</rule>
<!-- Existing validation rules -->
<rule name="control-definition-required">
<description>All controls used in windows must be defined in patterns</description>
<constraint>Every control element must reference a defined control or structure pattern</constraint>
</rule>
</validation-rules>
<views>
<view-include src="business-views.xml" important="true" />
<view-include src="admin-views.xml" important="false" />
<!-- Local view definitions -->
</views>
<patterns>
<pattern-include src="windows-controls.xml" important="true" />
<pattern-include src="custom-controls.xml" important="false" />
<!-- Local pattern definitions -->
</patterns>
<validation-rules>
<validation-include src="base-validation.xml" important="true" />
<validation-include src="view-validation.xml" important="false" />
<!-- Local validation rules -->
</validation-rules>
<ui-layout-def>
<validation-rules>
<validation-include src="base-validation.xml" important="true" />
</validation-rules>
<patterns>
<pattern-include src="windows-controls.xml" important="true" />
<!-- Pattern definitions... -->
</patterns>
<views>
<!-- Product management view -->
<view name="ProductView" type="business-entity" category="core">
<metadata>
<model-class>Product</model-class>
<view-model-class>ProductViewModel</view-model-class>
</metadata>
<dependencies>
<view-ref name="CategoryView" relationship="lookup" />
</dependencies>
<data-context>
<property name="currentProduct" type="Product" scope="view" />
<property name="productList" type="ProductList" scope="view" />
</data-context>
<windows>
<window-ref name="ProductListWindow" role="main" default="true" />
<window-ref name="ProductEditDialog" role="editor" modal="true" />
</windows>
<navigation>
<action name="show-list" target="ProductListWindow" />
<action name="edit-product" target="ProductEditDialog" context="currentProduct" />
</navigation>
</view>
<!-- Category lookup view -->
<view name="CategoryView" type="utility" category="core">
<windows>
<window-ref name="CategoryListDialog" role="main" modal="true" />
</windows>
</view>
</views>
<!-- Window definitions -->
<window name="ProductListWindow" title="Product List"
wireframe="StandardAppLayout" view="ProductView">
<view-properties>
<role>main</role>
<default>true</default>
<data-context-binding>productList</data-context-binding>
</view-properties>
<slot-overrides>
<slot name="main-content">
<ListView name="productGrid" view-mode="details">
<columns>
<column name="name" text="Product Name" width="200" />
<column name="category" text="Category" width="150" />
<column name="price" text="Price" width="100" />
</columns>
</ListView>
</slot>
</slot-overrides>
</window>
<window name="ProductEditDialog" title="Edit Product"
wireframe="DialogLayout" view="ProductView">
<view-properties>
<role>editor</role>
<modal>true</modal>
<data-context-binding>currentProduct</data-context-binding>
</view-properties>
<slot-overrides>
<slot name="dialog-body">
<FormField name="nameField" label-text="Product Name:" required="true">
<TextBox name="nameInput" slot="input" />
</FormField>
<FormField name="categoryField" label-text="Category:">
<ComboBox name="categoryCombo" slot="input" />
</FormField>
</slot>
</slot-overrides>
</window>
</ui-layout-def>
Windows Forms / WPF
Qt / KDE
Web / HTML
Mobile
Version 1.1 maintains full backward compatibility with 1.0 documents. Existing documents will work without modification, but won't benefit from view organization features.
<views> sectionYou can migrate gradually by:
// Generated from ProductView definition
public class ProductView : BaseEntityView, IProductView
{
public ProductListWindow ProductListWindow { get; private set; }
public ProductEditDialog ProductEditDialog { get; private set; }
// Data context properties
public Product CurrentProduct { get; set; }
public ObservableCollection<Product> ProductList { get; set; }
// Dependencies
public ICategoryView CategoryView { get; set; }
// Navigation methods
public void ShowList() => ProductListWindow.Show();
public void EditProduct(Product product) => ProductEditDialog.ShowDialog(product);
// View behaviors
public async Task RefreshData() { /* ... */ }
public async Task SaveChanges() { /* ... */ }
}
This format specification enables consistent, validated, cross-platform UI definitions with powerful view organization, inheritance, and modular design capabilities.