From a36a9f73ffe43d1b470332cec6c8b7da7afc7c65 Mon Sep 17 00:00:00 2001 From: Raul Avila Catala Date: Wed, 26 Aug 2026 02:21:56 -0600 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20refactor=20Core=20+=20xModules=20F1?= =?UTF-8?q?-F8=20=E2=80=94=20migraci=C3=B3n=20namespaces=20Share,=20HWND?= =?UTF-8?q?=20trampol=C3=ADn,=20View=20y=20registro=20MEF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - F1 inventario usings CoreModule/WindowingModule/LayoutModule - F2 git mv CoreModule→Core, WindowingModule→Core/Windowing, LayoutModule→Core/LayoutEngine, View.cs→Share/ - F3 renombrado namespaces + interfaces públicas a Share (Core 100% internal) - F3.5 plugin infra IControlActivator/ControlActivatorRegistry (ModuleInitializer) + View ViewBase dual overload + ControlBase→Core - F4 WndProc [UnmanagedCallersOnly] HWND-based ConcurrentDictionary + AlternativeWindow funcional - F5 Generator FQN Share + GetTypeByMetadataName robusto - F6 Sample/Templates usings Share + fix IcoGen Core - F7 docs README/CONTRIBUTING system_design - F8 build/pack verificación Closes #18 --- CONTRIBUTING.md | 45 +++++++----- README.md | 23 +++--- .../EasyBehaviorGenerator.cs | 24 ++++--- .../Common/ControlActivatorRegistry.cs | 27 +++++++ .../Common/IControlActivator.cs | 6 ++ .../Backend => Core}/Application.cs | 27 ++++--- .../Frontend => Core}/BehaviorBuilderImpl.cs | 4 +- .../{CoreModule/Backend => Core}/Constants.cs | 2 +- .../Infrastructure => Core}/ControlBase.cs | 11 ++- .../{CoreModule/Backend => Core}/Entities.cs | 4 +- .../Backend => Core}/HandleRegistry.cs | 11 ++- .../Infrastructure => Core}/IconGenerator.cs | 4 +- .../LayoutEngine}/ChildrenBuilderImpl.cs | 33 ++++++--- .../LayoutEngine}/ContentBuilderImpl.cs | 8 +-- .../LayoutEngine}/DockLayoutStrategy.cs | 5 +- .../LayoutEngine}/GridLayoutStrategy.cs | 5 +- .../HorizontalStackLayoutStrategy.cs | 5 +- .../LayoutEngine}/ILayoutStrategy.cs | 4 +- .../LayoutEngine}/ILayoutable.cs | 5 +- .../LayoutEngine}/LayoutBuilderImpl.cs | 9 ++- .../LayoutEngine}/LayoutEngine.cs | 4 +- .../VerticalStackLayoutStrategy.cs | 5 +- .../LayoutEngine}/ViewBuilderImpl.cs | 8 +-- .../LayoutEngine}/WindowConfigBuilder.cs | 8 +-- .../Backend => Core}/LayoutModels.cs | 7 +- .../Backend => Core}/MasterRouter.cs | 18 ++++- .../Backend => Core}/Procedures.cs | 2 +- .../{CoreModule/Backend => Core}/RECT.cs | 4 +- .../ResourcesDictionaryImpl.cs | 4 +- .../{CoreModule/Backend => Core}/Win32.cs | 4 +- .../Windowing}/AlternativeWindowImpl.cs | 5 +- .../Core/Windowing/Constants.cs | 2 + .../Backend => Core/Windowing}/Entities.cs | 6 +- .../Core/Windowing/Enums.cs | 2 + .../Backend => Core/Windowing}/Procedures.cs | 35 +++------- .../Backend => Core/Windowing}/UserControl.cs | 7 +- .../Backend => Core/Windowing}/Win32.cs | 6 +- .../Backend => Core/Windowing}/WindowImpl.cs | 5 +- .../Backend/ControlInstanceProvider.cs | 23 ------ .../CoreModule/Frontend/IBehaviorBuilder.cs | 3 - .../LayoutModule/Frontend/Enums.cs | 8 --- .../LayoutModule/Frontend/IDockable.cs | 8 --- .../LayoutModule/Frontend/IStackLayout.cs | 8 --- src/EasyWindowsApplication/Share/Enums.cs | 11 +++ .../Frontend => Share}/GridDefinitions.cs | 2 +- .../Frontend => Share}/IAlternativeWindow.cs | 5 +- .../IApplicationLayoutPhase.cs | 7 +- .../IApplicationPostBehaviorPhase.cs | 2 +- .../IApplicationPostLayoutPhase.cs | 2 +- .../Frontend => Share}/IBaseWindow.cs | 2 +- .../Share/IBehaviorBuilder.cs | 3 + .../Frontend => Share}/IChildrenBuilder.cs | 7 +- .../Share/IContentBuilder.cs | 4 +- .../Frontend => Share}/IDockStackLayout.cs | 5 +- src/EasyWindowsApplication/Share/IDockable.cs | 7 ++ .../Frontend => Share}/IGridLayout.cs | 4 +- .../IHorizontalStackLayout.cs | 2 +- .../Frontend => Share}/ILayout.cs | 2 +- .../Frontend => Share}/ILayoutBuilder.cs | 7 +- .../ILayoutBuilderAfterWindow.cs | 5 +- .../IResourcesDictionary.cs | 2 +- .../Share/IStackLayout.cs | 7 ++ .../IVerticalStackLayout.cs | 2 +- src/EasyWindowsApplication/Share/IView.cs | 5 ++ .../Frontend => Share}/IViewBuilder.cs | 6 +- .../Frontend => Share}/IWindow.cs | 5 +- .../Frontend => Share}/IWindowConfig.cs | 6 +- .../IWindowsScrollConfig.cs | 5 +- .../Share/Infrastructure/ControlAccess.cs | 4 +- .../Share/Infrastructure/View.cs | 22 ------ .../Frontend => Share}/LayoutLength.cs | 5 +- .../Frontend => Share}/LayoutOptions.cs | 5 +- src/EasyWindowsApplication/Share/View.cs | 70 +++++++++++++++++++ .../Frontend => Share}/WindowsScroll.cs | 5 +- .../Win32ControlsModule/Backend/Controls.cs | 5 +- .../Win32ControlsModule/Backend/Procedures.cs | 4 +- .../Backend/Win32ControlActivator.cs | 16 +++++ .../Frontend/ControlBuilderExtensions.cs | 3 +- .../Win32ControlsModule/Frontend/IControl.cs | 4 +- .../Win32ControlsModule/Frontend/IpAddress.cs | 6 +- .../Win32ControlsModule/Initializer.cs | 15 ++++ .../WindowingModule/Backend/Constants.cs | 2 - .../WindowingModule/Backend/Enums.cs | 2 - .../WindowingModule/Frontend/Enums.cs | 7 -- .../WindowingModule/Frontend/IView.cs | 5 -- .../WindowsApplication.cs | 7 +- src/ProjectTemplates/EasyWinApp/Behavior.cs | 4 +- .../EasyWinApp/Controls/CustomCtrl.cs | 3 +- .../EasyWinApp/EasyWinApp.csproj | 2 +- src/ProjectTemplates/EasyWinApp/Layout.cs | 3 +- src/ProjectTemplates/EasyWinApp/Resources.cs | 2 +- .../EasyWinApp/Views/MainWindowView.cs | 3 +- .../EasyWinApp/Views/MsgErrorWindowView.cs | 3 +- .../SimpleEasyWinApp/Program.cs | 4 +- .../SimpleEasyWinApp/SimpleEasyWinApp.csproj | 2 +- src/Sample/Program.cs | 5 +- src/Sample/Sample.csproj | 2 +- 97 files changed, 432 insertions(+), 347 deletions(-) create mode 100644 src/EasyWindowsApplication/Common/ControlActivatorRegistry.cs create mode 100644 src/EasyWindowsApplication/Common/IControlActivator.cs rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/Application.cs (72%) rename src/EasyWindowsApplication/{CoreModule/Frontend => Core}/BehaviorBuilderImpl.cs (81%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/Constants.cs (98%) rename src/EasyWindowsApplication/{Share/Infrastructure => Core}/ControlBase.cs (96%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/Entities.cs (95%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/HandleRegistry.cs (71%) rename src/EasyWindowsApplication/{Share/Infrastructure => Core}/IconGenerator.cs (96%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/ChildrenBuilderImpl.cs (54%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/ContentBuilderImpl.cs (88%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/DockLayoutStrategy.cs (96%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/GridLayoutStrategy.cs (96%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/HorizontalStackLayoutStrategy.cs (95%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/ILayoutStrategy.cs (75%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/ILayoutable.cs (75%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/LayoutBuilderImpl.cs (82%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/LayoutEngine.cs (87%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/VerticalStackLayoutStrategy.cs (96%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/ViewBuilderImpl.cs (86%) rename src/EasyWindowsApplication/{LayoutModule/Backend => Core/LayoutEngine}/WindowConfigBuilder.cs (87%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/LayoutModels.cs (86%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/MasterRouter.cs (90%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/Procedures.cs (83%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/RECT.cs (62%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/ResourcesDictionaryImpl.cs (94%) rename src/EasyWindowsApplication/{CoreModule/Backend => Core}/Win32.cs (98%) rename src/EasyWindowsApplication/{WindowingModule/Backend => Core/Windowing}/AlternativeWindowImpl.cs (84%) create mode 100644 src/EasyWindowsApplication/Core/Windowing/Constants.cs rename src/EasyWindowsApplication/{WindowingModule/Backend => Core/Windowing}/Entities.cs (84%) create mode 100644 src/EasyWindowsApplication/Core/Windowing/Enums.cs rename src/EasyWindowsApplication/{WindowingModule/Backend => Core/Windowing}/Procedures.cs (77%) rename src/EasyWindowsApplication/{WindowingModule/Backend => Core/Windowing}/UserControl.cs (88%) rename src/EasyWindowsApplication/{WindowingModule/Backend => Core/Windowing}/Win32.cs (93%) rename src/EasyWindowsApplication/{WindowingModule/Backend => Core/Windowing}/WindowImpl.cs (82%) delete mode 100644 src/EasyWindowsApplication/CoreModule/Backend/ControlInstanceProvider.cs delete mode 100644 src/EasyWindowsApplication/CoreModule/Frontend/IBehaviorBuilder.cs delete mode 100644 src/EasyWindowsApplication/LayoutModule/Frontend/Enums.cs delete mode 100644 src/EasyWindowsApplication/LayoutModule/Frontend/IDockable.cs delete mode 100644 src/EasyWindowsApplication/LayoutModule/Frontend/IStackLayout.cs rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/GridDefinitions.cs (84%) rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IAlternativeWindow.cs (70%) rename src/EasyWindowsApplication/{CoreModule/Frontend => Share}/IApplicationLayoutPhase.cs (51%) rename src/EasyWindowsApplication/{CoreModule/Frontend => Share}/IApplicationPostBehaviorPhase.cs (57%) rename src/EasyWindowsApplication/{CoreModule/Frontend => Share}/IApplicationPostLayoutPhase.cs (73%) rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IBaseWindow.cs (69%) create mode 100644 src/EasyWindowsApplication/Share/IBehaviorBuilder.cs rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IChildrenBuilder.cs (58%) rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/IDockStackLayout.cs (56%) create mode 100644 src/EasyWindowsApplication/Share/IDockable.cs rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/IGridLayout.cs (68%) rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/IHorizontalStackLayout.cs (51%) rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/ILayout.cs (64%) rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/ILayoutBuilder.cs (55%) rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/ILayoutBuilderAfterWindow.cs (72%) rename src/EasyWindowsApplication/{CoreModule/Frontend => Share}/IResourcesDictionary.cs (90%) create mode 100644 src/EasyWindowsApplication/Share/IStackLayout.cs rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/IVerticalStackLayout.cs (50%) create mode 100644 src/EasyWindowsApplication/Share/IView.cs rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IViewBuilder.cs (83%) rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IWindow.cs (66%) rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IWindowConfig.cs (78%) rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/IWindowsScrollConfig.cs (79%) delete mode 100644 src/EasyWindowsApplication/Share/Infrastructure/View.cs rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/LayoutLength.cs (83%) rename src/EasyWindowsApplication/{LayoutModule/Frontend => Share}/LayoutOptions.cs (68%) create mode 100644 src/EasyWindowsApplication/Share/View.cs rename src/EasyWindowsApplication/{WindowingModule/Frontend => Share}/WindowsScroll.cs (92%) create mode 100644 src/EasyWindowsApplication/Win32ControlsModule/Backend/Win32ControlActivator.cs create mode 100644 src/EasyWindowsApplication/Win32ControlsModule/Initializer.cs delete mode 100644 src/EasyWindowsApplication/WindowingModule/Backend/Constants.cs delete mode 100644 src/EasyWindowsApplication/WindowingModule/Backend/Enums.cs delete mode 100644 src/EasyWindowsApplication/WindowingModule/Frontend/Enums.cs delete mode 100644 src/EasyWindowsApplication/WindowingModule/Frontend/IView.cs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31890bc..b0c4feb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,20 +67,22 @@ El framework está organizado en módulos bajo `src/EasyWindowsApplication/`: | Módulo | Capa | Responsabilidad | |---|---|---| -| `CoreModule` | Backend + Frontend | Punto de entrada (`WindowsApplication`), fases del Fluent API, Resources, Behavior, MasterRouter, HandleRegistry | -| `LayoutModule` | Backend + Frontend | `ILayoutBuilder`, layouts (Grid, Stack, Dock), `IContentBuilder`, `IChildrenBuilder`, `IViewBuilder` | -| `Share` | Frontend (público) | Tipos públicos de la API de usuario: `Color`, `Thickness`, `IContentBuilder`, `LayoutLength`, `LayoutOptions` | -| `Share/Infrastructure` | Frontend (público técnico) | Tipos `public` **por razones técnicas** con `[EditorBrowsable(Never)]`: `ControlAccess`, `IconGenerator`, `ControlBase`, `View` | -| `Win32ControlsModule` | Backend + Frontend | Interfaces de controles (`IButton`, `ILabel`, `IEdit`, ...) y sus implementaciones Win32 | -| `WindowingModule` | Backend + Frontend | Ventanas (`IWindow`, `IAlternativeWindow`), posicionamiento (`WindowPositionOnScreen`) | +| `Core` | `internal` (100%) | Punto de entrada (`WindowsApplication` → `Share/IApplicationLayoutPhase`), `Application`, `MasterRouter` (trampolín HWND-based), `HandleRegistry` (ConcurrentDictionary HWND→Router), `ControlBase`, `IconGenerator` | +| `Core/Windowing` | `internal` | `WindowImpl`, `AlternativeWindowImpl`, `Procedures` (CreateMainWindow/CreateAlternativeWindow con `[UnmanagedCallersOnly]`), `UserControl` | +| `Core/LayoutEngine` | `internal` | `LayoutEngine`, `ILayoutBuilder`, layouts (Grid, Stack, Dock), `ChildrenBuilderImpl` (usa `ControlActivatorRegistry`), `ViewBuilderImpl` | +| `Common` | `internal` | `ControlActivatorRegistry` + `IControlActivator` (registry genérico `Register/Create`, `EnsureInitialized()` + `ControlActivatorGenerator` `IIncrementalGenerator` con `InternalsVisibleTo`, MEF compile-time) — rompe ciclo `Common ↔ Core` sin `ModuleInitializer` (`CA2255`) | +| `Share` | `public` | API usuario: `IWindow`, `IAlternativeWindow`, `IWindowConfig`, `IChildrenBuilder` (dual overload `Action>` + `Func,View>`), `View` struct readonly (`Name/Margin/Width/Height/Background/Dock/Grid/OnClick/Text`), `LayoutLength`, `GridDefinitions`, `IResourcesDictionary`, etc. | +| `Share/Infrastructure` | `public` técnico | `[EditorBrowsable(Never)]`: `ControlAccess` (punto usado por Source Generator), `ViewBase` base para controles custom (ej. `IpAddress`) | +| `Win32ControlsModule` | Frontend `public` / Backend `internal` | Interfaces (`IButton`, `ILabel` …) heredando `IControl` + Backend (`Button`, `Label` → `Core.ControlBase`) + `Win32ControlActivator` (`IControlActivator`, `internal`, auto-registrado vía `ControlActivatorGenerator` + `EnsureInitialized()` en `Core/Application`) | +| `Generators` | `Analyzer` | `EasyBehaviorGenerator` (FQN `Share` + `GetTypeByMetadataName`) + `ControlActivatorGenerator` (descubre `IControlActivator` en `Compilation`, genera `ControlActivatorRegistrations.g.cs`, `InternalsVisibleTo`) | ### Principios de organización -- **`Common`** — código compartido entre módulos, pero de acceso **`internal`** (no visible para consumidores). -- **`Share`** — código compartido entre módulos, pero de acceso **`public`** (expuesto a consumidores del framework). -- **`Share/Infrastructure`** — código compartido entre módulos, `public` **por razones técnicas** (lo alcanzan el código generado, los targets de build o la herencia interna), pero **NO** parte de la API de usuario → obligatorio `[EditorBrowsable(EditorBrowsableState.Never)]`. Si un archivo ahí no lo tiene, es un bug. -- **`CoreModule/Frontend`** — interfaces de las fases del Fluent API (`IApplicationLayoutPhase` → `IApplicationPostLayoutPhase` → `IApplicationPostBehaviorPhase`) que guían por IntelliSense el orden correcto. -- **`Backend`** — implementaciones `internal` de esas interfaces. +- **`Common`** — código compartido `internal` (no visible para consumidores). Contiene `ControlActivatorRegistry` (evita reflexión, factorías genéricas). +- **`Share`** — API `public` para consumidores. Todo lo que devuelve `WindowsApplication` (`IApplicationLayoutPhase` etc.) vive aquí. +- **`Share/Infrastructure`** — `public` por razones técnicas (`[EditorBrowsable(Never)]`). Solo `ControlAccess` y `ViewBase` permanecen aquí; `ControlBase`/`IconGenerator` migraron a `Core/`. +- **`Core/**`** — 100% `internal`. Nada `public` aquí (si aparece `public` es bug, debe ser `internal` o moverse a `Share`). Implementaciones puras. +- **`Win32ControlsModule/Frontend`** — `public` interfaces controles; `Backend` — `internal` implementaciones que heredan `Core.ControlBase` y se registran vía `IControlActivator`. --- @@ -118,10 +120,10 @@ Resources/ ## Source Generators -El proyecto `EasyWindowsApplication.Generators` contiene `EasyBehaviorGenerator`, un `IIncrementalGenerator` que: +El proyecto `EasyWindowsApplication.Generators` contiene `EasyBehaviorGenerator`, un `IIncrementalGenerator` que (FQN actualizados a `EasyWindowsApplication.Share.*` + robustez `GetTypeByMetadataName`): -1. **Detecta** llamadas `.Name("...")`** dentro de lambdas `View(...)` y `Window(...)` en el `Layout`. -2. **Genera** `EasyBehaviorExtensions` — un *extension property* para cada nombre, tipado con la interfaz del control: +1. **Detecta** llamadas `.Name("...")`** dentro de lambdas `View(...)` (ahora `View` es `Share/View` struct) y `Window(...)` / `AlternativeWindow(...)` en el `Layout`. +2. **Genera** `EasyBehaviorExtensions` — un *extension property* para cada nombre, tipado con la interfaz del control (FQN `global::EasyWindowsApplication.Share.IWindow` / `IAlternativeWindow` / `global::EasyWindowsApplication.Share.IBehaviorBuilder`): ```csharp // Auto-generado (ejemplo) extension(IBehaviorBuilder bh) { @@ -141,6 +143,9 @@ El proyecto `EasyWindowsApplication.Generators` contiene `EasyBehaviorGenerator` > **Naming**: referenciar un control desde `Behavior` requiere `.Name()` explícito; sin `.Name()` no se genera accessor (el control sigue funcionando en el Layout por HWND). El auto-naming fue evaluado y **rechazado** (deriva semántica silenciosa al editar el Layout). +- **Robustez FQN**: `ISettingsBuilder` se resuelve vía `Compilation.GetTypeByMetadataName("EasyWindowsApplication.Share.ISettingsBuilder")` + `SymbolEqualityComparer.Default` (no string comparison). Si `GetTypeByMetadataName` retorna `null`, el gate `UseWinApi` no se activa. +- **View**: el generador detecta `View` genérico con `T : IControl`; `IWindow`/`IAlternativeWindow` usan FQN `Share` (antes `WindowingModule.Frontend`). + --- ## Pipeline de iconos SVG→ICO @@ -171,11 +176,13 @@ Los proyectos de plantilla incluyen un `Target` de MSBuild (`GenerateAppIcon`) q Documenta aquí las decisiones de arquitectura relevantes. Usa ADRs (Architecture Decision Records) en `docs/adr/`. -- **Fluent API con interfaces de fase** — El IntelliSense guía el orden `Resources → Layout → Behavior → Initialize` mediante interfaces (`IApplicationLayoutPhase`, `IApplicationPostLayoutPhase`, `IApplicationPostBehaviorPhase`). -- **Controles como interfaces** (`IButton`, `ILabel`, ...) — permite que el Source Generator genere tipos débilesmente acoplados y facilita testing/mocking. -- **MasterRouter** — centraliza el bucle de mensajes (`WndProc` → `DefWindowProcW`) y despacha eventos tipados (`WM.COMMAND` → `Click`). -- **ControlAccess** — punto de acceso público para resolver controles por nombre desde el Behavior (usado por las propiedades generadas). Vive en `Share/Infrastructure` (técnico, `[EditorBrowsable(Never)]`). `SetController` se cablea en `Application.Behavior(...)`. -- **`UseWinApi()` como bifurcación explícita** — elegir controles nativos por HWND (comctl32) frente a los futuros controles GDI/GDI+ personalizados. Es un gate **compile-time** (`EAWIN002`), no un flag decorativo: el consumidor es el Source Generator, que decide qué accessors existen. Con los módulos MVU futuros, lo que reciba el lambda de `.Behavior(...)` dependerá del mismo flag. +- **Fluent API con interfaces de fase** — El IntelliSense guía el orden `Resources → Layout → Behavior → Initialize` mediante interfaces (`IApplicationLayoutPhase`, `IApplicationPostLayoutPhase`, `IApplicationPostBehaviorPhase`) ahora en `Share/` (antes `CoreModule/Frontend`). `WindowsApplication` devuelve `IApplicationLayoutPhase` público. +- **Controles como interfaces** (`IButton`, `ILabel`, ...) — permite que el Source Generator genere tipos débilesmente acoplados y facilita testing/mocking. `Button`/`Label` heredan `Core.ControlBase` (antes `Share.Infrastructure.ControlBase`). +- **MasterRouter** — centraliza el bucle de mensajes con trampolín `[UnmanagedCallersOnly(CallConvs=[Stdcall])]` + lookup HWND-based (`HandleRegistry.ConcurrentDictionary`), `try/catch` que evita tumbar proceso, despacha eventos tipados (`WM.COMMAND` → `Click`). El delegado estático sobrescrito fue eliminado (evita GC). +- **ControlAccess / ControlActivatorRegistry / ControlActivatorGenerator** — `ControlAccess` sigue en `Share/Infrastructure` (usado por `EasyBehaviorGenerator`). `ControlActivatorRegistry` en `Common/` (genérico `Register/Create`, `Shared` + `EnsureInitialized()` + `partial RegisterGeneratedActivators()`) rompe acoplamiento `Core → Win32ControlsModule` sin `ModuleInitializer` (`CA2255` en `Library`). `ControlActivatorGenerator` (`IIncrementalGenerator` en `Generators`, descubre `IControlActivator` en `Compilation` vía `GetTypeByMetadataName` + `AllInterfaces`, genera `ControlActivatorRegistrations.g.cs` con `new Win32ControlActivator().RegisterActivators(Shared)` y futuros plugins; usa `` para mantener `internal`. +- **View struct** — `Share/View` readonly struct `where T : class, IControl` con `Instance` + fluents (`Name/Margin/Width/Height/Background/Dock/Grid/OnClick/Text`). Dual overload en `IChildrenBuilder`: `View(Action>)` + `View(Func,View>)` instanciando `View(control)` vía `ControlActivatorRegistry`. +- **`UseWinApi()` como bifurcación explícita** — gate **compile-time** (`EAWIN002`), consumidor Source Generator decide accessors. `IconGenerator` migró `Share/Infrastructure` → `Core/` (ahora `Core.IconGenerator`, IcoGen usa `EasyWindowsApplication.Core`). +- **AlternativeWindow** — ahora funcional: `Procedures.CreateAlternativeWindow` registra clase `WS_POPUP|CAPTION|SYSMENU` y `HandleRegistry.RegisterRouter(hwnd, router)`; `Application.RegisterAlternative` crea hwnd real, aplica BackgroundBrush y `Show()`. --- diff --git a/README.md b/README.md index 2bb4b70..9007104 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ Crear una aplicación nativa nunca fue tan limpio. Todo se divide en 4 bloques l ```csharp using EasyWindowsApplication; +using EasyWindowsApplication.Share; using EasyWindowsApplication.Win32ControlsModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; int counter = 0; @@ -43,7 +43,7 @@ WindowsApplication ) .Behavior(bh => { - var btn = bh.BtnGuardar; // tipado por Source Generator + var btn = bh.BtnGuardar; // tipado por Source Generator (View wrapper) btn.OnClick(() => { counter++; @@ -152,14 +152,15 @@ WindowsApplication ``` EasyWindowsApplication/src/ ├── EasyWindowsApplication/ # Framework principal -│ ├── CoreModule/ # Fases del Fluent API, Resources, Behavior -│ ├── LayoutModule/ # ILayoutBuilder, Grid, Stack layouts -│ ├── Share/ # Tipos públicos (Color, Thickness, IContentBuilder) -│ │ └── Infrastructure/ # Tipos públicos técnicos ([EditorBrowsable(Never)]) -│ ├── Win32ControlsModule/ # IButton, ILabel, IEdit, ICheckBox, ... -│ ├── WindowingModule/ # IWindow, WindowPositionOnScreen -│ └── WindowsApplication.cs # Punto de entrada del Fluent API -├── EasyWindowsApplication.Generators/ # Source Generator (EasyBehaviorGenerator) +│ ├── Core/ # Fases Fluent API, Resources, Behavior, MasterRouter (100% internal) +│ │ ├── Windowing/ # WindowImpl, AlternativeWindowImpl, Procedures (HWND-based WndProc) +│ │ └── LayoutEngine/ # ILayoutBuilder, Grid/Stack/Dock layouts, ViewBuilder +│ ├── Common/ # ControlActivatorRegistry + ControlActivatorGenerator (IIncrementalGenerator, InternalsVisibleTo) +│ ├── Share/ # API pública usuario (IWindow, ILayoutBuilder, View struct, Color, Thickness) +│ │ └── Infrastructure/ # Técnicos [EditorBrowsable(Never)]: ControlAccess +│ ├── Win32ControlsModule/ # IButton, ILabel... + Backend (Button, Label → Core.ControlBase) +│ └── WindowsApplication.cs # Punto de entrada Fluent API (devuelve Share/IApplicationLayoutPhase) +├── EasyWindowsApplication.Generators/ # Source Generator (FQN Share.* + GetTypeByMetadataName) └── ProjectTemplates/ ├── EasyWinApp/ # Plantilla `dotnet new easywinapp` └── SimpleEasyWinApp/ # Plantilla `dotnet new simpleeasywinapp` @@ -167,7 +168,7 @@ EasyWindowsApplication/src/ ## Cómo funciona -El **Source Generator** analiza tu `Layout` en tiempo de compilación: cada `.Name("BtnGuardar")` dentro de un `View` o `Window` genera una propiedad tipada (`bh.BtnGuardar`) en `Behavior`. Al compilar, ya no necesitas localizar controles por string — si el nombre no coincide, el compilador te lo dice. En runtime, el `MasterRouter` centraliza el bucle de mensajes de Win32 y despacha eventos tipados (`Click`, etc.) de forma automatica. +El **Source Generator** `EasyBehaviorGenerator` analiza tu `Layout` en tiempo de compilación: cada `.Name("BtnGuardar")` dentro de un `View` (struct `View` wrapper con `Action>` + `Func,View>`) o `Window` genera una propiedad tipada (`bh.BtnGuardar`) en `Behavior`. En runtime, el `MasterRouter` usa un trampolín `[UnmanagedCallersOnly]` con lookup HWND-based (`HandleRegistry.ConcurrentDictionary`) y despacha eventos tipados (`Click`, etc.); `ControlActivatorRegistry` en `Common/` (poblado en `Application.Initialize()` vía `ControlActivatorGenerator` — `IIncrementalGenerator` con `InternalsVisibleTo`, MEF compile-time) elimina el acoplamiento `Core → Win32Controls` sin `ModuleInitializer` (`CA2255`). Para usar los controles nativos del módulo Win32, activa `UseWinApi()` en Resources. **Es obligatorio**: si declaras un control (`View`) sin él, el compilador lo rechaza con `EAWIN002` y no se genera ningún accessor: diff --git a/src/EasyWindowsApplication.Generators/EasyBehaviorGenerator.cs b/src/EasyWindowsApplication.Generators/EasyBehaviorGenerator.cs index ec43c69..c609258 100644 --- a/src/EasyWindowsApplication.Generators/EasyBehaviorGenerator.cs +++ b/src/EasyWindowsApplication.Generators/EasyBehaviorGenerator.cs @@ -1,4 +1,4 @@ - + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -93,7 +93,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) sb.AppendLine("#pragma warning disable CS0612, CS0618, CS1591"); sb.AppendLine(); - var ib = "global::EasyWindowsApplication.CoreModule.Frontend.IBehaviorBuilder"; + var ib = "global::EasyWindowsApplication.Share.IBehaviorBuilder"; sb.AppendLine("namespace EasyWindowsApplication"); sb.AppendLine("{"); @@ -233,12 +233,12 @@ private static bool IsNameCandidate(SyntaxNode node) if (parentMa.Name.Identifier.Text == "Window") { - return new NamedInfo(name, "global::EasyWindowsApplication.WindowingModule.Frontend.IWindow", isWindowType: true, location); + return new NamedInfo(name, "global::EasyWindowsApplication.Share.IWindow", isWindowType: true, location); } if (parentMa.Name.Identifier.Text == "AlternativeWindow") { - return new NamedInfo(name, "global::EasyWindowsApplication.WindowingModule.Frontend.IAlternativeWindow", isWindowType: true, location); + return new NamedInfo(name, "global::EasyWindowsApplication.Share.IAlternativeWindow", isWindowType: true, location); } return null; @@ -278,11 +278,17 @@ private static bool IsUseWinApiSymbol(GeneratorSyntaxContext context) if (inv.Expression is not MemberAccessExpressionSyntax ma) return false; var symbol = context.SemanticModel.GetSymbolInfo(ma).Symbol; - return symbol is IMethodSymbol method - && method.Name == "UseWinApi" - && method.ContainingType is { } containingType - && containingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) - == "global::EasyWindowsApplication.CoreModule.Frontend.ISettingsBuilder"; + if (symbol is not IMethodSymbol method || method.Name != "UseWinApi") + return false; + if (method.ContainingType is not { } containingType) + return false; + var iSettingsBuilder = context.SemanticModel.Compilation.GetTypeByMetadataName( + "EasyWindowsApplication.Share.ISettingsBuilder"); + if (iSettingsBuilder is null) + { + return false; + } + return containingType.Equals(iSettingsBuilder, SymbolEqualityComparer.Default); } private static bool IsViewControlCandidate(SyntaxNode node) diff --git a/src/EasyWindowsApplication/Common/ControlActivatorRegistry.cs b/src/EasyWindowsApplication/Common/ControlActivatorRegistry.cs new file mode 100644 index 0000000..83faabb --- /dev/null +++ b/src/EasyWindowsApplication/Common/ControlActivatorRegistry.cs @@ -0,0 +1,27 @@ +namespace EasyWindowsApplication.Common; + +internal sealed class ControlActivatorRegistry +{ + private readonly Dictionary> _factories = new(); + + internal void Register(Func factory) where T : class + { + _factories[typeof(T)] = () => factory()!; + } + + internal T Create() where T : class + { + if (_factories.TryGetValue(typeof(T), out var f)) + return (T)f(); + throw new InvalidOperationException($"No control implementation registered for '{typeof(T).FullName}'."); + } + + internal object CreateFor(Type type) + { + if (_factories.TryGetValue(type, out var f)) + return f(); + throw new InvalidOperationException($"No control implementation registered for '{type.FullName}'."); + } + + internal static ControlActivatorRegistry Shared { get; } = new(); +} diff --git a/src/EasyWindowsApplication/Common/IControlActivator.cs b/src/EasyWindowsApplication/Common/IControlActivator.cs new file mode 100644 index 0000000..7452353 --- /dev/null +++ b/src/EasyWindowsApplication/Common/IControlActivator.cs @@ -0,0 +1,6 @@ +namespace EasyWindowsApplication.Common; + +internal interface IControlActivator +{ + void RegisterActivators(ControlActivatorRegistry registry); +} diff --git a/src/EasyWindowsApplication/CoreModule/Backend/Application.cs b/src/EasyWindowsApplication/Core/Application.cs similarity index 72% rename from src/EasyWindowsApplication/CoreModule/Backend/Application.cs rename to src/EasyWindowsApplication/Core/Application.cs index 3f1e10f..16729f6 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/Application.cs +++ b/src/EasyWindowsApplication/Core/Application.cs @@ -1,11 +1,9 @@ -using EasyWindowsApplication.CoreModule.Frontend; -using EasyWindowsApplication.LayoutModule.Backend; -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; +using EasyWindowsApplication.Core.LayoutEngine; +using EasyWindowsApplication.Core.Windowing; using EasyWindowsApplication.Share.Infrastructure; -using EasyWindowsApplication.WindowingModule.Frontend; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal sealed class Application : IApplicationLayoutPhase, @@ -68,9 +66,9 @@ public void Initialize() private void RegisterMain(WindowModel window) { - var hwnd = WindowingModule.Backend.Procedures.CreateMainWindow(_router, window.Title, window.Width, window.Height); + var hwnd = Core.Windowing.Procedures.CreateMainWindow(_router, window.Title, window.Width, window.Height); - var win = new WindowingModule.Backend.WindowImpl( + var win = new Core.Windowing.WindowImpl( hwnd, window.Name, window.Title, window.Width, window.Height, window.Position); if (window.Background.HasValue) @@ -85,7 +83,14 @@ private void RegisterMain(WindowModel window) private void RegisterAlternative(WindowModel window) { - _registry.RegisterWindow(new WindowingModule.Backend.AlternativeWindowImpl( - 0, 0, window.Name, window.Title, window.Width, window.Height, window.Position)); + var hwnd = Core.Windowing.Procedures.CreateAlternativeWindow(_router, 0, window.Title, window.Width, window.Height); + var win = new Core.Windowing.AlternativeWindowImpl(hwnd, 0, window.Name, window.Title, window.Width, window.Height, window.Position); + if (window.Background.HasValue) + { + var brush = Win32.CreateSolidBrush(window.Background.Value.ToCOLORREF()); + _router.RegisterWindowBackgroundBrush(hwnd, brush); + } + _registry.RegisterWindow(win); + win.Show(); } -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/CoreModule/Frontend/BehaviorBuilderImpl.cs b/src/EasyWindowsApplication/Core/BehaviorBuilderImpl.cs similarity index 81% rename from src/EasyWindowsApplication/CoreModule/Frontend/BehaviorBuilderImpl.cs rename to src/EasyWindowsApplication/Core/BehaviorBuilderImpl.cs index 300834b..5d2852b 100644 --- a/src/EasyWindowsApplication/CoreModule/Frontend/BehaviorBuilderImpl.cs +++ b/src/EasyWindowsApplication/Core/BehaviorBuilderImpl.cs @@ -1,7 +1,7 @@ -using EasyWindowsApplication.CoreModule.Backend; +using EasyWindowsApplication.Share; using EasyWindowsApplication.Share.Infrastructure; -namespace EasyWindowsApplication.CoreModule.Frontend; +namespace EasyWindowsApplication.Core; internal sealed class BehaviorBuilderImpl : IBehaviorBuilder, ControlAccess.IBehaviorServicesController { diff --git a/src/EasyWindowsApplication/CoreModule/Backend/Constants.cs b/src/EasyWindowsApplication/Core/Constants.cs similarity index 98% rename from src/EasyWindowsApplication/CoreModule/Backend/Constants.cs rename to src/EasyWindowsApplication/Core/Constants.cs index d49f152..dd7eb01 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/Constants.cs +++ b/src/EasyWindowsApplication/Core/Constants.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal static class WS { diff --git a/src/EasyWindowsApplication/Share/Infrastructure/ControlBase.cs b/src/EasyWindowsApplication/Core/ControlBase.cs similarity index 96% rename from src/EasyWindowsApplication/Share/Infrastructure/ControlBase.cs rename to src/EasyWindowsApplication/Core/ControlBase.cs index 939f888..0f33e1c 100644 --- a/src/EasyWindowsApplication/Share/Infrastructure/ControlBase.cs +++ b/src/EasyWindowsApplication/Core/ControlBase.cs @@ -1,13 +1,12 @@ -using System.ComponentModel; +using System.ComponentModel; using System.Runtime.InteropServices; -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.LayoutModule.Backend; -using EasyWindowsApplication.LayoutModule.Frontend; + +using EasyWindowsApplication.Core.LayoutEngine; using EasyWindowsApplication.Share; using EasyWindowsApplication.Win32ControlsModule.Frontend; -using static EasyWindowsApplication.CoreModule.Backend.Win32; +using static EasyWindowsApplication.Core.Win32; -namespace EasyWindowsApplication.Share.Infrastructure; +namespace EasyWindowsApplication.Core; [EditorBrowsable(EditorBrowsableState.Never)] public abstract class ControlBase : IControl, IClickEventSource, ILayoutable, IDockable diff --git a/src/EasyWindowsApplication/CoreModule/Backend/Entities.cs b/src/EasyWindowsApplication/Core/Entities.cs similarity index 95% rename from src/EasyWindowsApplication/CoreModule/Backend/Entities.cs rename to src/EasyWindowsApplication/Core/Entities.cs index 6857490..e6e84c1 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/Entities.cs +++ b/src/EasyWindowsApplication/Core/Entities.cs @@ -1,6 +1,6 @@ -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; [StructLayout(LayoutKind.Sequential)] internal struct SIZE diff --git a/src/EasyWindowsApplication/CoreModule/Backend/HandleRegistry.cs b/src/EasyWindowsApplication/Core/HandleRegistry.cs similarity index 71% rename from src/EasyWindowsApplication/CoreModule/Backend/HandleRegistry.cs rename to src/EasyWindowsApplication/Core/HandleRegistry.cs index c25b5e0..d9c8a63 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/HandleRegistry.cs +++ b/src/EasyWindowsApplication/Core/HandleRegistry.cs @@ -1,10 +1,17 @@ +using System.Collections.Concurrent; using EasyWindowsApplication.Win32ControlsModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal sealed class HandleRegistry { + private static readonly ConcurrentDictionary _routersByHwnd = new(); + + internal static void RegisterRouter(nint hwnd, MasterRouter router) => _routersByHwnd[hwnd] = router; + internal static void UnregisterRouter(nint hwnd) => _routersByHwnd.TryRemove(hwnd, out _); + internal static MasterRouter? GetRouter(nint hwnd) => _routersByHwnd.TryGetValue(hwnd, out var r) ? r : null; + private readonly Dictionary _hwndToControl = new(); private readonly Dictionary _nameToControl = new(StringComparer.Ordinal); private readonly Dictionary _windowByName = new(StringComparer.Ordinal); diff --git a/src/EasyWindowsApplication/Share/Infrastructure/IconGenerator.cs b/src/EasyWindowsApplication/Core/IconGenerator.cs similarity index 96% rename from src/EasyWindowsApplication/Share/Infrastructure/IconGenerator.cs rename to src/EasyWindowsApplication/Core/IconGenerator.cs index b1c99eb..92db279 100644 --- a/src/EasyWindowsApplication/Share/Infrastructure/IconGenerator.cs +++ b/src/EasyWindowsApplication/Core/IconGenerator.cs @@ -1,8 +1,8 @@ -using System.ComponentModel; +using System.ComponentModel; using SkiaSharp; using Svg.Skia; -namespace EasyWindowsApplication.Share.Infrastructure; +namespace EasyWindowsApplication.Core; [EditorBrowsable(EditorBrowsableState.Never)] public static class IconGenerator diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/ChildrenBuilderImpl.cs b/src/EasyWindowsApplication/Core/LayoutEngine/ChildrenBuilderImpl.cs similarity index 54% rename from src/EasyWindowsApplication/LayoutModule/Backend/ChildrenBuilderImpl.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/ChildrenBuilderImpl.cs index b5b6001..68cfeeb 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/ChildrenBuilderImpl.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/ChildrenBuilderImpl.cs @@ -1,9 +1,9 @@ -using EasyWindowsApplication.CoreModule.Backend; +using EasyWindowsApplication.Common; +using EasyWindowsApplication.Core; using EasyWindowsApplication.Share; using EasyWindowsApplication.Win32ControlsModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class ChildrenBuilderImpl : IChildrenBuilder { @@ -11,15 +11,30 @@ internal sealed class ChildrenBuilderImpl : IChildrenBuilder internal ChildrenBuilderImpl(ContentModel content) => _content = content; - public IChildrenBuilder View(Action configure) where T : IControl + public IChildrenBuilder View(Action> configure) where T : class, IControl { - var control = ControlInstanceProvider.Create(); - configure(control); + var control = ControlActivatorRegistry.Shared.Create(); + var view = new View(control); + configure(view); + + _content.Children.Add(new ViewModel + { + Name = view.Instance.Name, + Control = view.Instance + }); + return this; + } + + public IChildrenBuilder View(Func, View> configure) where T : class, IControl + { + var control = ControlActivatorRegistry.Shared.Create(); + var view = new View(control); + var result = configure(view); _content.Children.Add(new ViewModel { - Name = control.Name, - Control = control + Name = result.Instance.Name, + Control = result.Instance }); return this; } @@ -40,4 +55,4 @@ public IChildrenBuilder View(Action configure) public IChildrenBuilder DockTop() => this; public IChildrenBuilder DockRight() => this; public IChildrenBuilder DockBottom() => this; -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/ContentBuilderImpl.cs b/src/EasyWindowsApplication/Core/LayoutEngine/ContentBuilderImpl.cs similarity index 88% rename from src/EasyWindowsApplication/LayoutModule/Backend/ContentBuilderImpl.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/ContentBuilderImpl.cs index 6de9d10..22cc175 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/ContentBuilderImpl.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/ContentBuilderImpl.cs @@ -1,9 +1,7 @@ -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.LayoutModule.Frontend; +using EasyWindowsApplication.Core; using EasyWindowsApplication.Share; -using EasyWindowsApplication.WindowingModule.Frontend; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class ContentBuilderImpl : IContentBuilder { @@ -50,4 +48,4 @@ public IContentBuilder Children(Action configure) public IContentBuilder ColumnSpacing(float pixels) => this; public IContentBuilder DefaultDock(DockPosition position) => this; public IContentBuilder ShouldExpandLastChild(bool expand) => this; -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/DockLayoutStrategy.cs b/src/EasyWindowsApplication/Core/LayoutEngine/DockLayoutStrategy.cs similarity index 96% rename from src/EasyWindowsApplication/LayoutModule/Backend/DockLayoutStrategy.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/DockLayoutStrategy.cs index 6a9065a..5cbcb95 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/DockLayoutStrategy.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/DockLayoutStrategy.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class DockLayoutStrategy : ILayoutStrategy { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/GridLayoutStrategy.cs b/src/EasyWindowsApplication/Core/LayoutEngine/GridLayoutStrategy.cs similarity index 96% rename from src/EasyWindowsApplication/LayoutModule/Backend/GridLayoutStrategy.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/GridLayoutStrategy.cs index 8fe80c4..2dbc678 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/GridLayoutStrategy.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/GridLayoutStrategy.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class GridLayoutStrategy : ILayoutStrategy { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/HorizontalStackLayoutStrategy.cs b/src/EasyWindowsApplication/Core/LayoutEngine/HorizontalStackLayoutStrategy.cs similarity index 95% rename from src/EasyWindowsApplication/LayoutModule/Backend/HorizontalStackLayoutStrategy.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/HorizontalStackLayoutStrategy.cs index d5c692d..8e47659 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/HorizontalStackLayoutStrategy.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/HorizontalStackLayoutStrategy.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class HorizontalStackLayoutStrategy : ILayoutStrategy { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/ILayoutStrategy.cs b/src/EasyWindowsApplication/Core/LayoutEngine/ILayoutStrategy.cs similarity index 75% rename from src/EasyWindowsApplication/LayoutModule/Backend/ILayoutStrategy.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/ILayoutStrategy.cs index b557a58..9c6fe4b 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/ILayoutStrategy.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/ILayoutStrategy.cs @@ -1,6 +1,6 @@ -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal interface ILayoutStrategy { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/ILayoutable.cs b/src/EasyWindowsApplication/Core/LayoutEngine/ILayoutable.cs similarity index 75% rename from src/EasyWindowsApplication/LayoutModule/Backend/ILayoutable.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/ILayoutable.cs index 0b057a1..d26d8b3 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/ILayoutable.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/ILayoutable.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal interface ILayoutable { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/LayoutBuilderImpl.cs b/src/EasyWindowsApplication/Core/LayoutEngine/LayoutBuilderImpl.cs similarity index 82% rename from src/EasyWindowsApplication/LayoutModule/Backend/LayoutBuilderImpl.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/LayoutBuilderImpl.cs index 7346bf9..e7556e4 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/LayoutBuilderImpl.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/LayoutBuilderImpl.cs @@ -1,8 +1,7 @@ -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; +using EasyWindowsApplication.Core; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class LayoutBuilderImpl : ILayoutBuilder, ILayoutBuilderAfterWindow { @@ -39,4 +38,4 @@ public ILayoutBuilderAfterWindow AlternativeWindow(Action configu _app.AddWindow(model); return this; } -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/LayoutEngine.cs b/src/EasyWindowsApplication/Core/LayoutEngine/LayoutEngine.cs similarity index 87% rename from src/EasyWindowsApplication/LayoutModule/Backend/LayoutEngine.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/LayoutEngine.cs index 5d207c4..e6b629a 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/LayoutEngine.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/LayoutEngine.cs @@ -1,6 +1,6 @@ -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class LayoutEngine { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/VerticalStackLayoutStrategy.cs b/src/EasyWindowsApplication/Core/LayoutEngine/VerticalStackLayoutStrategy.cs similarity index 96% rename from src/EasyWindowsApplication/LayoutModule/Backend/VerticalStackLayoutStrategy.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/VerticalStackLayoutStrategy.cs index d6c9209..c541b82 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/VerticalStackLayoutStrategy.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/VerticalStackLayoutStrategy.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class VerticalStackLayoutStrategy : ILayoutStrategy { diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/ViewBuilderImpl.cs b/src/EasyWindowsApplication/Core/LayoutEngine/ViewBuilderImpl.cs similarity index 86% rename from src/EasyWindowsApplication/LayoutModule/Backend/ViewBuilderImpl.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/ViewBuilderImpl.cs index 18076a6..0042b07 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/ViewBuilderImpl.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/ViewBuilderImpl.cs @@ -1,9 +1,7 @@ -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.LayoutModule.Frontend; +using EasyWindowsApplication.Core; using EasyWindowsApplication.Share; -using EasyWindowsApplication.WindowingModule.Frontend; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class ViewBuilderImpl : IViewBuilder { @@ -36,4 +34,4 @@ public IViewBuilder Content(Action configure) Model.SubContent = content.Model; return this; } -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/LayoutModule/Backend/WindowConfigBuilder.cs b/src/EasyWindowsApplication/Core/LayoutEngine/WindowConfigBuilder.cs similarity index 87% rename from src/EasyWindowsApplication/LayoutModule/Backend/WindowConfigBuilder.cs rename to src/EasyWindowsApplication/Core/LayoutEngine/WindowConfigBuilder.cs index 1d4481d..f1f5251 100644 --- a/src/EasyWindowsApplication/LayoutModule/Backend/WindowConfigBuilder.cs +++ b/src/EasyWindowsApplication/Core/LayoutEngine/WindowConfigBuilder.cs @@ -1,9 +1,7 @@ -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.LayoutModule.Frontend; +using EasyWindowsApplication.Core; using EasyWindowsApplication.Share; -using EasyWindowsApplication.WindowingModule.Frontend; -namespace EasyWindowsApplication.LayoutModule.Backend; +namespace EasyWindowsApplication.Core.LayoutEngine; internal sealed class WindowConfigBuilder : IWindowConfig { @@ -59,4 +57,4 @@ private IWindowContentConfig RegisterContent(Action configure) } } -internal sealed class WindowContentConfig : IWindowContentConfig { } \ No newline at end of file +internal sealed class WindowContentConfig : IWindowContentConfig { } diff --git a/src/EasyWindowsApplication/CoreModule/Backend/LayoutModels.cs b/src/EasyWindowsApplication/Core/LayoutModels.cs similarity index 86% rename from src/EasyWindowsApplication/CoreModule/Backend/LayoutModels.cs rename to src/EasyWindowsApplication/Core/LayoutModels.cs index b689221..ebfb15b 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/LayoutModels.cs +++ b/src/EasyWindowsApplication/Core/LayoutModels.cs @@ -1,8 +1,7 @@ -using EasyWindowsApplication.Share; +using EasyWindowsApplication.Share; using EasyWindowsApplication.Win32ControlsModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal interface IContentModel; internal interface IViewModel; @@ -31,4 +30,4 @@ internal sealed class ViewModel : IViewModel internal string Name { get; set; } = ""; internal IControl? Control { get; set; } internal ContentModel? SubContent { get; set; } -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/CoreModule/Backend/MasterRouter.cs b/src/EasyWindowsApplication/Core/MasterRouter.cs similarity index 90% rename from src/EasyWindowsApplication/CoreModule/Backend/MasterRouter.cs rename to src/EasyWindowsApplication/Core/MasterRouter.cs index 375eb20..7eef885 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/MasterRouter.cs +++ b/src/EasyWindowsApplication/Core/MasterRouter.cs @@ -1,9 +1,10 @@ +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using EasyWindowsApplication.Common; using EasyWindowsApplication.Share; using EasyWindowsApplication.Win32ControlsModule.Frontend; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal sealed class MasterRouter { @@ -66,6 +67,21 @@ internal void ClearScrollOffset(nint hwnd) _scrollOffsets.Remove(hwnd); } + [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })] + internal static nint WndProcTrampoline(nint hwnd, uint msg, nint wParam, nint lParam) + { + try + { + var router = HandleRegistry.GetRouter(hwnd); + return router?.WndProc(hwnd, msg, wParam, lParam) ?? Win32.DefWindowProcW(hwnd, msg, wParam, lParam); + } + catch (Exception ex) + { + System.Diagnostics.Debug.Fail(ex.ToString()); + return Win32.DefWindowProcW(hwnd, msg, wParam, lParam); + } + } + internal nint WndProc(nint hwnd, uint msg, nint wParam, nint lParam) { if (msg == WM.DESTROY && hwnd == _mainHwnd) diff --git a/src/EasyWindowsApplication/CoreModule/Backend/Procedures.cs b/src/EasyWindowsApplication/Core/Procedures.cs similarity index 83% rename from src/EasyWindowsApplication/CoreModule/Backend/Procedures.cs rename to src/EasyWindowsApplication/Core/Procedures.cs index fe22424..8db87fa 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/Procedures.cs +++ b/src/EasyWindowsApplication/Core/Procedures.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal static class Procedures { diff --git a/src/EasyWindowsApplication/CoreModule/Backend/RECT.cs b/src/EasyWindowsApplication/Core/RECT.cs similarity index 62% rename from src/EasyWindowsApplication/CoreModule/Backend/RECT.cs rename to src/EasyWindowsApplication/Core/RECT.cs index cc6ac0a..b4287fd 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/RECT.cs +++ b/src/EasyWindowsApplication/Core/RECT.cs @@ -1,6 +1,6 @@ -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; [StructLayout(LayoutKind.Sequential)] internal struct RECT diff --git a/src/EasyWindowsApplication/CoreModule/Backend/ResourcesDictionaryImpl.cs b/src/EasyWindowsApplication/Core/ResourcesDictionaryImpl.cs similarity index 94% rename from src/EasyWindowsApplication/CoreModule/Backend/ResourcesDictionaryImpl.cs rename to src/EasyWindowsApplication/Core/ResourcesDictionaryImpl.cs index 11e69dd..58ee463 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/ResourcesDictionaryImpl.cs +++ b/src/EasyWindowsApplication/Core/ResourcesDictionaryImpl.cs @@ -1,6 +1,6 @@ -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; -using EasyWindowsApplication.CoreModule.Frontend; +using EasyWindowsApplication.Share; internal sealed class ResourcesDictionaryImpl : IResourcesDictionary { diff --git a/src/EasyWindowsApplication/CoreModule/Backend/Win32.cs b/src/EasyWindowsApplication/Core/Win32.cs similarity index 98% rename from src/EasyWindowsApplication/CoreModule/Backend/Win32.cs rename to src/EasyWindowsApplication/Core/Win32.cs index 058b414..cd324c3 100644 --- a/src/EasyWindowsApplication/CoreModule/Backend/Win32.cs +++ b/src/EasyWindowsApplication/Core/Win32.cs @@ -1,6 +1,6 @@ -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; -namespace EasyWindowsApplication.CoreModule.Backend; +namespace EasyWindowsApplication.Core; internal static partial class Win32 { diff --git a/src/EasyWindowsApplication/WindowingModule/Backend/AlternativeWindowImpl.cs b/src/EasyWindowsApplication/Core/Windowing/AlternativeWindowImpl.cs similarity index 84% rename from src/EasyWindowsApplication/WindowingModule/Backend/AlternativeWindowImpl.cs rename to src/EasyWindowsApplication/Core/Windowing/AlternativeWindowImpl.cs index 221fa35..9be6eac 100644 --- a/src/EasyWindowsApplication/WindowingModule/Backend/AlternativeWindowImpl.cs +++ b/src/EasyWindowsApplication/Core/Windowing/AlternativeWindowImpl.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.Share; -using EasyWindowsApplication.WindowingModule.Frontend; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.WindowingModule.Backend; +namespace EasyWindowsApplication.Core.Windowing; internal sealed class AlternativeWindowImpl : IAlternativeWindow { diff --git a/src/EasyWindowsApplication/Core/Windowing/Constants.cs b/src/EasyWindowsApplication/Core/Windowing/Constants.cs new file mode 100644 index 0000000..399115f --- /dev/null +++ b/src/EasyWindowsApplication/Core/Windowing/Constants.cs @@ -0,0 +1,2 @@ +// Window-specific constants are in Core (shared by all modules). +// This file reserved for Windowing-only constants in the future. diff --git a/src/EasyWindowsApplication/WindowingModule/Backend/Entities.cs b/src/EasyWindowsApplication/Core/Windowing/Entities.cs similarity index 84% rename from src/EasyWindowsApplication/WindowingModule/Backend/Entities.cs rename to src/EasyWindowsApplication/Core/Windowing/Entities.cs index cce9301..1ed19a1 100644 --- a/src/EasyWindowsApplication/WindowingModule/Backend/Entities.cs +++ b/src/EasyWindowsApplication/Core/Windowing/Entities.cs @@ -1,7 +1,7 @@ -using System.Runtime.InteropServices; -using EasyWindowsApplication.CoreModule.Backend; +using System.Runtime.InteropServices; +using EasyWindowsApplication.Core; -namespace EasyWindowsApplication.WindowingModule.Backend; +namespace EasyWindowsApplication.Core.Windowing; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct WNDCLASSEXW diff --git a/src/EasyWindowsApplication/Core/Windowing/Enums.cs b/src/EasyWindowsApplication/Core/Windowing/Enums.cs new file mode 100644 index 0000000..323328b --- /dev/null +++ b/src/EasyWindowsApplication/Core/Windowing/Enums.cs @@ -0,0 +1,2 @@ +// Placeholder — implementación futura +namespace EasyWindowsApplication.Core.Windowing; diff --git a/src/EasyWindowsApplication/WindowingModule/Backend/Procedures.cs b/src/EasyWindowsApplication/Core/Windowing/Procedures.cs similarity index 77% rename from src/EasyWindowsApplication/WindowingModule/Backend/Procedures.cs rename to src/EasyWindowsApplication/Core/Windowing/Procedures.cs index 8e7efe7..c63c7f0 100644 --- a/src/EasyWindowsApplication/WindowingModule/Backend/Procedures.cs +++ b/src/EasyWindowsApplication/Core/Windowing/Procedures.cs @@ -1,20 +1,15 @@ -using System.Runtime.InteropServices; -using EasyWindowsApplication.CoreModule.Backend; +using System.Runtime.InteropServices; +using EasyWindowsApplication.Core; -namespace EasyWindowsApplication.WindowingModule.Backend; - -internal delegate nint WNDPROC(nint hWnd, uint Msg, nint wParam, nint lParam); +namespace EasyWindowsApplication.Core.Windowing; internal static class Procedures { private const int SW_SHOWNORMAL = 1; - private static WNDPROC? _wndProcDelegate; - private static MasterRouter? _router; - - internal static void SetRouter(MasterRouter router) => _router = router; + internal static void SetRouter(MasterRouter router) { } - internal static nint CreateMainWindow( + internal static unsafe nint CreateMainWindow( MasterRouter router, string title, float width, @@ -35,8 +30,7 @@ internal static nint CreateMainWindow( string className = $"EasyWinApp_{Guid.NewGuid():N}"; nint classNamePtr = Marshal.StringToHGlobalUni(className); - _wndProcDelegate = WndProcCallback; - nint wndProcPtr = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate); + nint wndProcPtr = (nint)(delegate* unmanaged[Stdcall])&MasterRouter.WndProcTrampoline; var wndClass = new WNDCLASSEXW { @@ -74,13 +68,13 @@ internal static nint CreateMainWindow( if (hwnd == 0) throw new InvalidOperationException($"CreateWindowExW failed: {Marshal.GetLastWin32Error()}"); - _router = router; + HandleRegistry.RegisterRouter(hwnd, router); router.RegisterMainHwnd(hwnd); return hwnd; } - internal static nint CreateAlternativeWindow( + internal static unsafe nint CreateAlternativeWindow( MasterRouter router, nint ownerHwnd, string title, @@ -92,8 +86,7 @@ internal static nint CreateAlternativeWindow( string className = $"EasyWinAlt_{Guid.NewGuid():N}"; nint classNamePtr = Marshal.StringToHGlobalUni(className); - _wndProcDelegate = WndProcCallback; - nint wndProcPtr = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate); + nint wndProcPtr = (nint)(delegate* unmanaged[Stdcall])&MasterRouter.WndProcTrampoline; var wndClass = new WNDCLASSEXW { @@ -131,16 +124,8 @@ internal static nint CreateAlternativeWindow( if (hwnd == 0) throw new InvalidOperationException($"CreateWindowExW failed: {Marshal.GetLastWin32Error()}"); - _router = router; + HandleRegistry.RegisterRouter(hwnd, router); return hwnd; } - - private static nint WndProcCallback(nint hwnd, uint msg, nint wParam, nint lParam) - { - if (_router is not null) - return _router.WndProc(hwnd, msg, wParam, lParam); - - return CoreModule.Backend.Win32.DefWindowProcW(hwnd, msg, wParam, lParam); - } } diff --git a/src/EasyWindowsApplication/WindowingModule/Backend/UserControl.cs b/src/EasyWindowsApplication/Core/Windowing/UserControl.cs similarity index 88% rename from src/EasyWindowsApplication/WindowingModule/Backend/UserControl.cs rename to src/EasyWindowsApplication/Core/Windowing/UserControl.cs index 18d4d07..1faa651 100644 --- a/src/EasyWindowsApplication/WindowingModule/Backend/UserControl.cs +++ b/src/EasyWindowsApplication/Core/Windowing/UserControl.cs @@ -1,8 +1,7 @@ -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.LayoutModule.Backend; -using EasyWindowsApplication.Share.Infrastructure; +using EasyWindowsApplication.Core; +using EasyWindowsApplication.Core.LayoutEngine; -namespace EasyWindowsApplication.WindowingModule.Backend; +namespace EasyWindowsApplication.Core.Windowing; internal sealed class UserControl : ControlBase { diff --git a/src/EasyWindowsApplication/WindowingModule/Backend/Win32.cs b/src/EasyWindowsApplication/Core/Windowing/Win32.cs similarity index 93% rename from src/EasyWindowsApplication/WindowingModule/Backend/Win32.cs rename to src/EasyWindowsApplication/Core/Windowing/Win32.cs index be6b908..07073d3 100644 --- a/src/EasyWindowsApplication/WindowingModule/Backend/Win32.cs +++ b/src/EasyWindowsApplication/Core/Windowing/Win32.cs @@ -1,7 +1,7 @@ -using System.Runtime.InteropServices; -using EasyWindowsApplication.CoreModule.Backend; +using System.Runtime.InteropServices; +using EasyWindowsApplication.Core; -namespace EasyWindowsApplication.WindowingModule.Backend; +namespace EasyWindowsApplication.Core.Windowing; internal static partial class Win32 { diff --git a/src/EasyWindowsApplication/WindowingModule/Backend/WindowImpl.cs b/src/EasyWindowsApplication/Core/Windowing/WindowImpl.cs similarity index 82% rename from src/EasyWindowsApplication/WindowingModule/Backend/WindowImpl.cs rename to src/EasyWindowsApplication/Core/Windowing/WindowImpl.cs index c97da6e..f34f90b 100644 --- a/src/EasyWindowsApplication/WindowingModule/Backend/WindowImpl.cs +++ b/src/EasyWindowsApplication/Core/Windowing/WindowImpl.cs @@ -1,7 +1,6 @@ -using EasyWindowsApplication.Share; -using EasyWindowsApplication.WindowingModule.Frontend; +using EasyWindowsApplication.Share; -namespace EasyWindowsApplication.WindowingModule.Backend; +namespace EasyWindowsApplication.Core.Windowing; internal sealed class WindowImpl : IWindow { diff --git a/src/EasyWindowsApplication/CoreModule/Backend/ControlInstanceProvider.cs b/src/EasyWindowsApplication/CoreModule/Backend/ControlInstanceProvider.cs deleted file mode 100644 index 122d8c9..0000000 --- a/src/EasyWindowsApplication/CoreModule/Backend/ControlInstanceProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -using EasyWindowsApplication.Win32ControlsModule.Frontend; - -namespace EasyWindowsApplication.CoreModule.Backend; - -internal static class ControlInstanceProvider -{ - internal static T Create() where T : IControl - => (T)CreateFor(typeof(T)); - - internal static IControl CreateFor(Type type) - { - if (type == typeof(IButton)) - return new Win32ControlsModule.Backend.Button(); - if (type == typeof(Win32ControlsModule.Backend.Button)) - return new Win32ControlsModule.Backend.Button(); - if (type == typeof(ILabel)) - return new Win32ControlsModule.Backend.Label(); - if (type == typeof(Win32ControlsModule.Backend.Label)) - return new Win32ControlsModule.Backend.Label(); - - throw new InvalidOperationException($"No control implementation registered for '{type.FullName}'."); - } -} \ No newline at end of file diff --git a/src/EasyWindowsApplication/CoreModule/Frontend/IBehaviorBuilder.cs b/src/EasyWindowsApplication/CoreModule/Frontend/IBehaviorBuilder.cs deleted file mode 100644 index 0ffc43f..0000000 --- a/src/EasyWindowsApplication/CoreModule/Frontend/IBehaviorBuilder.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace EasyWindowsApplication.CoreModule.Frontend; - -public interface IBehaviorBuilder { } diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/Enums.cs b/src/EasyWindowsApplication/LayoutModule/Frontend/Enums.cs deleted file mode 100644 index 4d7e953..0000000 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/Enums.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace EasyWindowsApplication.LayoutModule.Frontend; - - -public enum GridUnitType { Absolute, Auto, Star } - -public enum LayoutAlignment { Start, Center, End, Fill } - -public enum DockPosition { Left, Top, Right, Bottom } diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/IDockable.cs b/src/EasyWindowsApplication/LayoutModule/Frontend/IDockable.cs deleted file mode 100644 index 3888d87..0000000 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/IDockable.cs +++ /dev/null @@ -1,8 +0,0 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.LayoutModule.Frontend; - -public interface IDockable -{ - DockPosition Dock { get; } -} diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/IStackLayout.cs b/src/EasyWindowsApplication/LayoutModule/Frontend/IStackLayout.cs deleted file mode 100644 index 40452c2..0000000 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/IStackLayout.cs +++ /dev/null @@ -1,8 +0,0 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.LayoutModule.Frontend; - -public interface IStackLayout : ILayout -{ - float Spacing { get; set; } -} diff --git a/src/EasyWindowsApplication/Share/Enums.cs b/src/EasyWindowsApplication/Share/Enums.cs index 2f42878..3df1ef0 100644 --- a/src/EasyWindowsApplication/Share/Enums.cs +++ b/src/EasyWindowsApplication/Share/Enums.cs @@ -1,3 +1,14 @@ namespace EasyWindowsApplication.Share; +public enum WindowPositionOnScreen { Center, Manual } +public enum ScrollBarVisibility { Default, Always, Never } + +public enum ScrollOrientation { Vertical, Horizontal, Both, Neither } + + +public enum GridUnitType { Absolute, Auto, Star } + +public enum LayoutAlignment { Start, Center, End, Fill } + +public enum DockPosition { Left, Top, Right, Bottom } \ No newline at end of file diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/GridDefinitions.cs b/src/EasyWindowsApplication/Share/GridDefinitions.cs similarity index 84% rename from src/EasyWindowsApplication/LayoutModule/Frontend/GridDefinitions.cs rename to src/EasyWindowsApplication/Share/GridDefinitions.cs index 92aad1a..07bb407 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/GridDefinitions.cs +++ b/src/EasyWindowsApplication/Share/GridDefinitions.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.LayoutModule.Frontend; +namespace EasyWindowsApplication.Share; public readonly struct RowDefinition { diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IAlternativeWindow.cs b/src/EasyWindowsApplication/Share/IAlternativeWindow.cs similarity index 70% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IAlternativeWindow.cs rename to src/EasyWindowsApplication/Share/IAlternativeWindow.cs index 0bc15d5..d883fe8 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IAlternativeWindow.cs +++ b/src/EasyWindowsApplication/Share/IAlternativeWindow.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.WindowingModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IAlternativeWindow : IBaseWindow { diff --git a/src/EasyWindowsApplication/CoreModule/Frontend/IApplicationLayoutPhase.cs b/src/EasyWindowsApplication/Share/IApplicationLayoutPhase.cs similarity index 51% rename from src/EasyWindowsApplication/CoreModule/Frontend/IApplicationLayoutPhase.cs rename to src/EasyWindowsApplication/Share/IApplicationLayoutPhase.cs index 74078af..8e68bee 100644 --- a/src/EasyWindowsApplication/CoreModule/Frontend/IApplicationLayoutPhase.cs +++ b/src/EasyWindowsApplication/Share/IApplicationLayoutPhase.cs @@ -1,8 +1,7 @@ -using EasyWindowsApplication.LayoutModule.Frontend; - -namespace EasyWindowsApplication.CoreModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IApplicationLayoutPhase { IApplicationPostLayoutPhase Layout(Action configure); -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/CoreModule/Frontend/IApplicationPostBehaviorPhase.cs b/src/EasyWindowsApplication/Share/IApplicationPostBehaviorPhase.cs similarity index 57% rename from src/EasyWindowsApplication/CoreModule/Frontend/IApplicationPostBehaviorPhase.cs rename to src/EasyWindowsApplication/Share/IApplicationPostBehaviorPhase.cs index 8fee916..3376736 100644 --- a/src/EasyWindowsApplication/CoreModule/Frontend/IApplicationPostBehaviorPhase.cs +++ b/src/EasyWindowsApplication/Share/IApplicationPostBehaviorPhase.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.CoreModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IApplicationPostBehaviorPhase { diff --git a/src/EasyWindowsApplication/CoreModule/Frontend/IApplicationPostLayoutPhase.cs b/src/EasyWindowsApplication/Share/IApplicationPostLayoutPhase.cs similarity index 73% rename from src/EasyWindowsApplication/CoreModule/Frontend/IApplicationPostLayoutPhase.cs rename to src/EasyWindowsApplication/Share/IApplicationPostLayoutPhase.cs index 7c5ffae..acf69d4 100644 --- a/src/EasyWindowsApplication/CoreModule/Frontend/IApplicationPostLayoutPhase.cs +++ b/src/EasyWindowsApplication/Share/IApplicationPostLayoutPhase.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.CoreModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IApplicationPostLayoutPhase { diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IBaseWindow.cs b/src/EasyWindowsApplication/Share/IBaseWindow.cs similarity index 69% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IBaseWindow.cs rename to src/EasyWindowsApplication/Share/IBaseWindow.cs index c7d9ab7..76f5705 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IBaseWindow.cs +++ b/src/EasyWindowsApplication/Share/IBaseWindow.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.WindowingModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IBaseWindow { diff --git a/src/EasyWindowsApplication/Share/IBehaviorBuilder.cs b/src/EasyWindowsApplication/Share/IBehaviorBuilder.cs new file mode 100644 index 0000000..f26de30 --- /dev/null +++ b/src/EasyWindowsApplication/Share/IBehaviorBuilder.cs @@ -0,0 +1,3 @@ +namespace EasyWindowsApplication.Share; + +public interface IBehaviorBuilder { } diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IChildrenBuilder.cs b/src/EasyWindowsApplication/Share/IChildrenBuilder.cs similarity index 58% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IChildrenBuilder.cs rename to src/EasyWindowsApplication/Share/IChildrenBuilder.cs index 1738b93..e2c7184 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IChildrenBuilder.cs +++ b/src/EasyWindowsApplication/Share/IChildrenBuilder.cs @@ -1,10 +1,11 @@ -using EasyWindowsApplication.Win32ControlsModule.Frontend; +using EasyWindowsApplication.Win32ControlsModule.Frontend; -namespace EasyWindowsApplication.WindowingModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IChildrenBuilder { - IChildrenBuilder View(Action configure) where T : IControl; + IChildrenBuilder View(Action> configure) where T : class, IControl; + IChildrenBuilder View(Func, View> configure) where T : class, IControl; IChildrenBuilder View(Action configure); IChildrenBuilder Row(int row); diff --git a/src/EasyWindowsApplication/Share/IContentBuilder.cs b/src/EasyWindowsApplication/Share/IContentBuilder.cs index a78300e..29057c8 100644 --- a/src/EasyWindowsApplication/Share/IContentBuilder.cs +++ b/src/EasyWindowsApplication/Share/IContentBuilder.cs @@ -1,6 +1,4 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; - + namespace EasyWindowsApplication.Share; public interface IContentBuilder diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/IDockStackLayout.cs b/src/EasyWindowsApplication/Share/IDockStackLayout.cs similarity index 56% rename from src/EasyWindowsApplication/LayoutModule/Frontend/IDockStackLayout.cs rename to src/EasyWindowsApplication/Share/IDockStackLayout.cs index 0a148cf..b7da142 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/IDockStackLayout.cs +++ b/src/EasyWindowsApplication/Share/IDockStackLayout.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.LayoutModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IDockLayout : ILayout { diff --git a/src/EasyWindowsApplication/Share/IDockable.cs b/src/EasyWindowsApplication/Share/IDockable.cs new file mode 100644 index 0000000..ba5ef98 --- /dev/null +++ b/src/EasyWindowsApplication/Share/IDockable.cs @@ -0,0 +1,7 @@ + +namespace EasyWindowsApplication.Share; + +public interface IDockable +{ + DockPosition Dock { get; } +} diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/IGridLayout.cs b/src/EasyWindowsApplication/Share/IGridLayout.cs similarity index 68% rename from src/EasyWindowsApplication/LayoutModule/Frontend/IGridLayout.cs rename to src/EasyWindowsApplication/Share/IGridLayout.cs index 51c878f..4aa7e98 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/IGridLayout.cs +++ b/src/EasyWindowsApplication/Share/IGridLayout.cs @@ -1,6 +1,6 @@ -using EasyWindowsApplication.LayoutModule.Backend; +using EasyWindowsApplication.Core.LayoutEngine; -namespace EasyWindowsApplication.LayoutModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IGridLayout : IStackLayout { diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/IHorizontalStackLayout.cs b/src/EasyWindowsApplication/Share/IHorizontalStackLayout.cs similarity index 51% rename from src/EasyWindowsApplication/LayoutModule/Frontend/IHorizontalStackLayout.cs rename to src/EasyWindowsApplication/Share/IHorizontalStackLayout.cs index ccb2cbf..98ae25a 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/IHorizontalStackLayout.cs +++ b/src/EasyWindowsApplication/Share/IHorizontalStackLayout.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.LayoutModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IHorizontalStackLayout : IStackLayout { diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/ILayout.cs b/src/EasyWindowsApplication/Share/ILayout.cs similarity index 64% rename from src/EasyWindowsApplication/LayoutModule/Frontend/ILayout.cs rename to src/EasyWindowsApplication/Share/ILayout.cs index 8c48cc3..b37bef7 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/ILayout.cs +++ b/src/EasyWindowsApplication/Share/ILayout.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace EasyWindowsApplication.LayoutModule.Frontend; +namespace EasyWindowsApplication.Share; public interface ILayout { diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/ILayoutBuilder.cs b/src/EasyWindowsApplication/Share/ILayoutBuilder.cs similarity index 55% rename from src/EasyWindowsApplication/LayoutModule/Frontend/ILayoutBuilder.cs rename to src/EasyWindowsApplication/Share/ILayoutBuilder.cs index 386669d..fedb52d 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/ILayoutBuilder.cs +++ b/src/EasyWindowsApplication/Share/ILayoutBuilder.cs @@ -1,9 +1,8 @@ -using EasyWindowsApplication.WindowingModule.Frontend; - -namespace EasyWindowsApplication.LayoutModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface ILayoutBuilder { ILayoutBuilderAfterWindow Window(); ILayoutBuilderAfterWindow Window(Action configure); -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/ILayoutBuilderAfterWindow.cs b/src/EasyWindowsApplication/Share/ILayoutBuilderAfterWindow.cs similarity index 72% rename from src/EasyWindowsApplication/LayoutModule/Frontend/ILayoutBuilderAfterWindow.cs rename to src/EasyWindowsApplication/Share/ILayoutBuilderAfterWindow.cs index b6165f1..80591d5 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/ILayoutBuilderAfterWindow.cs +++ b/src/EasyWindowsApplication/Share/ILayoutBuilderAfterWindow.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.WindowingModule.Frontend; - -namespace EasyWindowsApplication.LayoutModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface ILayoutBuilderAfterWindow { diff --git a/src/EasyWindowsApplication/CoreModule/Frontend/IResourcesDictionary.cs b/src/EasyWindowsApplication/Share/IResourcesDictionary.cs similarity index 90% rename from src/EasyWindowsApplication/CoreModule/Frontend/IResourcesDictionary.cs rename to src/EasyWindowsApplication/Share/IResourcesDictionary.cs index 32110ac..ea4db29 100644 --- a/src/EasyWindowsApplication/CoreModule/Frontend/IResourcesDictionary.cs +++ b/src/EasyWindowsApplication/Share/IResourcesDictionary.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.CoreModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IResourcesDictionary { diff --git a/src/EasyWindowsApplication/Share/IStackLayout.cs b/src/EasyWindowsApplication/Share/IStackLayout.cs new file mode 100644 index 0000000..55abc28 --- /dev/null +++ b/src/EasyWindowsApplication/Share/IStackLayout.cs @@ -0,0 +1,7 @@ + +namespace EasyWindowsApplication.Share; + +public interface IStackLayout : ILayout +{ + float Spacing { get; set; } +} diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/IVerticalStackLayout.cs b/src/EasyWindowsApplication/Share/IVerticalStackLayout.cs similarity index 50% rename from src/EasyWindowsApplication/LayoutModule/Frontend/IVerticalStackLayout.cs rename to src/EasyWindowsApplication/Share/IVerticalStackLayout.cs index 19c5f19..e492ff7 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/IVerticalStackLayout.cs +++ b/src/EasyWindowsApplication/Share/IVerticalStackLayout.cs @@ -1,4 +1,4 @@ -namespace EasyWindowsApplication.LayoutModule.Frontend; +namespace EasyWindowsApplication.Share; public interface IVerticalStackLayout : IStackLayout { diff --git a/src/EasyWindowsApplication/Share/IView.cs b/src/EasyWindowsApplication/Share/IView.cs new file mode 100644 index 0000000..54c9d1f --- /dev/null +++ b/src/EasyWindowsApplication/Share/IView.cs @@ -0,0 +1,5 @@ +namespace EasyWindowsApplication.Share; + +public interface IView : IBaseWindow +{ +} diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IViewBuilder.cs b/src/EasyWindowsApplication/Share/IViewBuilder.cs similarity index 83% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IViewBuilder.cs rename to src/EasyWindowsApplication/Share/IViewBuilder.cs index ff3c8ef..e8282ab 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IViewBuilder.cs +++ b/src/EasyWindowsApplication/Share/IViewBuilder.cs @@ -1,7 +1,5 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.WindowingModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IViewBuilder { diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IWindow.cs b/src/EasyWindowsApplication/Share/IWindow.cs similarity index 66% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IWindow.cs rename to src/EasyWindowsApplication/Share/IWindow.cs index 99f551a..f1e543c 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IWindow.cs +++ b/src/EasyWindowsApplication/Share/IWindow.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.WindowingModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IWindow : IBaseWindow { diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IWindowConfig.cs b/src/EasyWindowsApplication/Share/IWindowConfig.cs similarity index 78% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IWindowConfig.cs rename to src/EasyWindowsApplication/Share/IWindowConfig.cs index 114dd9d..2e4eae0 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IWindowConfig.cs +++ b/src/EasyWindowsApplication/Share/IWindowConfig.cs @@ -1,7 +1,5 @@ -using EasyWindowsApplication.LayoutModule.Frontend; -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.WindowingModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IWindowConfig { diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/IWindowsScrollConfig.cs b/src/EasyWindowsApplication/Share/IWindowsScrollConfig.cs similarity index 79% rename from src/EasyWindowsApplication/WindowingModule/Frontend/IWindowsScrollConfig.cs rename to src/EasyWindowsApplication/Share/IWindowsScrollConfig.cs index a413bfb..e4d3c11 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/IWindowsScrollConfig.cs +++ b/src/EasyWindowsApplication/Share/IWindowsScrollConfig.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.WindowingModule.Frontend; + +namespace EasyWindowsApplication.Share; public interface IWindowsScrollConfig { diff --git a/src/EasyWindowsApplication/Share/Infrastructure/ControlAccess.cs b/src/EasyWindowsApplication/Share/Infrastructure/ControlAccess.cs index 1ff78a5..8330329 100644 --- a/src/EasyWindowsApplication/Share/Infrastructure/ControlAccess.cs +++ b/src/EasyWindowsApplication/Share/Infrastructure/ControlAccess.cs @@ -1,6 +1,6 @@ -using System.ComponentModel; +using System.ComponentModel; using EasyWindowsApplication.Win32ControlsModule.Frontend; -using EasyWindowsApplication.WindowingModule.Frontend; +using EasyWindowsApplication.Share; namespace EasyWindowsApplication.Share.Infrastructure; diff --git a/src/EasyWindowsApplication/Share/Infrastructure/View.cs b/src/EasyWindowsApplication/Share/Infrastructure/View.cs deleted file mode 100644 index 569bbf5..0000000 --- a/src/EasyWindowsApplication/Share/Infrastructure/View.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.ComponentModel; -using EasyWindowsApplication.Win32ControlsModule.Frontend; - -namespace EasyWindowsApplication.Share.Infrastructure; - -[EditorBrowsable(EditorBrowsableState.Never)] -public abstract class View : ControlBase where TSelf : View -{ - internal View() { } - - public new TSelf OnMessage(uint msg, Win32MessageHandler handler) - { - base.OnMessage(msg, handler); - return (TSelf)this; - } - - public new TSelf OnClick(Action handler) - { - base.OnClick(handler); - return (TSelf)this; - } -} diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/LayoutLength.cs b/src/EasyWindowsApplication/Share/LayoutLength.cs similarity index 83% rename from src/EasyWindowsApplication/LayoutModule/Frontend/LayoutLength.cs rename to src/EasyWindowsApplication/Share/LayoutLength.cs index 207ad34..073fc59 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/LayoutLength.cs +++ b/src/EasyWindowsApplication/Share/LayoutLength.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.LayoutModule.Frontend; + +namespace EasyWindowsApplication.Share; public readonly struct LayoutLength { diff --git a/src/EasyWindowsApplication/LayoutModule/Frontend/LayoutOptions.cs b/src/EasyWindowsApplication/Share/LayoutOptions.cs similarity index 68% rename from src/EasyWindowsApplication/LayoutModule/Frontend/LayoutOptions.cs rename to src/EasyWindowsApplication/Share/LayoutOptions.cs index 21cb4e8..47b5595 100644 --- a/src/EasyWindowsApplication/LayoutModule/Frontend/LayoutOptions.cs +++ b/src/EasyWindowsApplication/Share/LayoutOptions.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.LayoutModule.Frontend; + +namespace EasyWindowsApplication.Share; public class LayoutOptions { diff --git a/src/EasyWindowsApplication/Share/View.cs b/src/EasyWindowsApplication/Share/View.cs new file mode 100644 index 0000000..98cd7cb --- /dev/null +++ b/src/EasyWindowsApplication/Share/View.cs @@ -0,0 +1,70 @@ +using System.ComponentModel; +using EasyWindowsApplication.Core; +using EasyWindowsApplication.Win32ControlsModule.Frontend; + +namespace EasyWindowsApplication.Share; + +[EditorBrowsable(EditorBrowsableState.Never)] +public abstract class ViewBase : ControlBase where TSelf : ViewBase +{ + internal ViewBase() { } + + public new TSelf OnMessage(uint msg, Win32MessageHandler handler) + { + base.OnMessage(msg, handler); + return (TSelf)this; + } + + public new TSelf OnClick(Action handler) + { + base.OnClick(handler); + return (TSelf)this; + } +} + +public readonly struct View where T : class, IControl +{ + public T Instance { get; } + + public View(T instance) => Instance = instance; + + public View Name(string name) { Instance.Name = name; return this; } + + public View Margin(float uniform) { Instance.Margin = new Thickness(uniform); return this; } + public View Margin(float vertical, float horizontal) { Instance.Margin = new Thickness(vertical, horizontal); return this; } + public View Margin(float top, float right, float bottom, float left) { Instance.Margin = new Thickness(top, right, bottom, left); return this; } + + public View Padding(float uniform) { Instance.Padding = new Thickness(uniform); return this; } + public View Padding(float vertical, float horizontal) { Instance.Padding = new Thickness(vertical, horizontal); return this; } + public View Padding(float top, float right, float bottom, float left) { Instance.Padding = new Thickness(top, right, bottom, left); return this; } + + public View Width(float width) { Instance.LayoutWidth = LayoutLength.Absolute(width); return this; } + public View Height(float height) { Instance.LayoutHeight = LayoutLength.Absolute(height); return this; } + + public View Background(Color color) { Instance.BackgroundColor = color; return this; } + + public View Dock(DockPosition dock) { Instance.Dock = dock; return this; } + public View DockLeft() { Instance.Dock = DockPosition.Left; return this; } + public View DockTop() { Instance.Dock = DockPosition.Top; return this; } + public View DockRight() { Instance.Dock = DockPosition.Right; return this; } + public View DockBottom() { Instance.Dock = DockPosition.Bottom; return this; } + + public View Row(int row) { Instance.GridRow = row; return this; } + public View Column(int column) { Instance.GridColumn = column; return this; } + public View RowSpan(int span) { Instance.GridRowSpan = span; return this; } + public View ColumnSpan(int span) { Instance.GridColumnSpan = span; return this; } + + public View OnClick(Action handler) { Instance.OnClick(handler); return this; } + + public View Text(string text) + { + if (Instance is IText t) t.Text = text; + return this; + } + + public View OnMessage(uint msg, Win32MessageHandler handler) + { + if (Instance is ControlBase cb) cb.OnMessage(msg, handler); + return this; + } +} diff --git a/src/EasyWindowsApplication/WindowingModule/Frontend/WindowsScroll.cs b/src/EasyWindowsApplication/Share/WindowsScroll.cs similarity index 92% rename from src/EasyWindowsApplication/WindowingModule/Frontend/WindowsScroll.cs rename to src/EasyWindowsApplication/Share/WindowsScroll.cs index 176445e..98c66ab 100644 --- a/src/EasyWindowsApplication/WindowingModule/Frontend/WindowsScroll.cs +++ b/src/EasyWindowsApplication/Share/WindowsScroll.cs @@ -1,6 +1,5 @@ -using EasyWindowsApplication.Share; - -namespace EasyWindowsApplication.WindowingModule.Frontend; + +namespace EasyWindowsApplication.Share; internal sealed class WindowsScroll : IWindowsScrollConfig { diff --git a/src/EasyWindowsApplication/Win32ControlsModule/Backend/Controls.cs b/src/EasyWindowsApplication/Win32ControlsModule/Backend/Controls.cs index 591b3cc..bc0fa9b 100644 --- a/src/EasyWindowsApplication/Win32ControlsModule/Backend/Controls.cs +++ b/src/EasyWindowsApplication/Win32ControlsModule/Backend/Controls.cs @@ -1,5 +1,4 @@ -using EasyWindowsApplication.CoreModule.Backend; -using EasyWindowsApplication.Share.Infrastructure; +using EasyWindowsApplication.Core; using EasyWindowsApplication.Win32ControlsModule.Frontend; namespace EasyWindowsApplication.Win32ControlsModule.Backend; @@ -15,4 +14,4 @@ public void SetStyle(uint style, bool redraw = true) { } public sealed class Label : ControlBase, ILabel { public string Text { get; set; } = ""; -} \ No newline at end of file +} diff --git a/src/EasyWindowsApplication/Win32ControlsModule/Backend/Procedures.cs b/src/EasyWindowsApplication/Win32ControlsModule/Backend/Procedures.cs index 41a75b0..6eae7be 100644 --- a/src/EasyWindowsApplication/Win32ControlsModule/Backend/Procedures.cs +++ b/src/EasyWindowsApplication/Win32ControlsModule/Backend/Procedures.cs @@ -1,5 +1,5 @@ -using System.Runtime.InteropServices; -using EasyWindowsApplication.CoreModule.Backend; +using System.Runtime.InteropServices; +using EasyWindowsApplication.Core; namespace EasyWindowsApplication.Win32ControlsModule.Backend; diff --git a/src/EasyWindowsApplication/Win32ControlsModule/Backend/Win32ControlActivator.cs b/src/EasyWindowsApplication/Win32ControlsModule/Backend/Win32ControlActivator.cs new file mode 100644 index 0000000..e529d03 --- /dev/null +++ b/src/EasyWindowsApplication/Win32ControlsModule/Backend/Win32ControlActivator.cs @@ -0,0 +1,16 @@ +using EasyWindowsApplication.Common; +using EasyWindowsApplication.Win32ControlsModule.Frontend; + +namespace EasyWindowsApplication.Win32ControlsModule.Backend; + +internal sealed class Win32ControlActivator : IControlActivator +{ + public void RegisterActivators(ControlActivatorRegistry registry) + { + registry.Register(() => new Button()); + registry.Register(() => new Label()); + // Register concrete types as well for direct resolution if needed + registry.Register