# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0] - 2026-09-23

Version 2.0.0 reworks how a page change is drawn. The transition API becomes a painter: a transition
declares its duration and draws one frame at a time, and the framework owns the clock, the animation,
and the completion. Drawing follows the [MicroEJ MWT transition
example](https://github.com/MicroEJ/ExampleJava-MWT/tree/master/transition) — the container
paints nothing of its own while a transition runs, so the previous frame stays on the display and is
the outgoing page. Only the incoming page is captured, and that buffer is now reused between
transitions instead of being allocated per navigation.

### Added

- Add `Transition.getDuration()`, `Transition.start(TransitionContext)` and
  `Transition.render(GraphicsContext, TransitionContext, float)`: a transition declares how long it
  lasts and draws one frame per `render` call, at the progress the framework computes.
- Add `TransitionContext.drawIncoming(GraphicsContext, int, int, int)` and
  `TransitionContext.getIncomingImage()`: the two ways a frame draws the incoming page.
- Add `TransitionContext.getNavigationKind()`, reporting `FORWARD`, `BACK`, or `REPLACE`, so a
  transition can adapt to the navigation that caused it.
- Add the `BOTTOM_TO_TOP` and `TOP_TO_BOTTOM` directions to `SlideTransition`, which now mirrors its
  direction on a back navigation by default; a constructor flag turns the mirroring off.
- Add easing to the shipped transitions: `SlideTransition` and `FadeTransition` take an
  `ej.motion.Function` and default to a quadratic ease-out.
- Add `Navigator.releaseTransitionBuffer()`, giving back the memory of the buffer the transitions
  draw the incoming page from.
- Add the `ej.navigation.transition.snapshots` BON constant (`true` by default). Setting it to `false`
  removes that buffer: the frames draw the incoming page live, and `FadeTransition` becomes instant.

### Changed

- The framework runs the animation, instead of the transition registering one of its own. A transition
  holds no timer and signals no completion, and a transition whose duration is `0` — including
  `Transition.IMMEDIATE` — is completed without being started and without drawing a frame.
- Only the incoming page is captured, into a buffer that stays allocated for the following
  transitions. Before, the fade captured a buffer per navigation and freed it at the end.
- Pointer events are ignored while a transition runs.
- The transitions now require a VEE Port whose buffer refresh strategy restores the previous frame
  into the back buffer (`single`, `predraw`, `legacy`, or the direct buffer policy), and an images
  heap that can hold one image the size of the page content area. See the README.

### Fixed

- Fix the first navigation on a desktop the application already shows: the page was not laid out and
  the display kept its previous content.

### Removed

- Remove `TransitionListener` and `Transition.run(TransitionContext, TransitionListener)`: the
  framework owns the timing and the completion, so there is nothing left for a transition to signal.
  - Migration: implement `getDuration()`, `start(TransitionContext)` and
    `render(GraphicsContext, TransitionContext, float)` instead of `run`, and drop the
    `onTransitionEnd()` call.
- Remove `TransitionContext.getOutgoingContent()`, `TransitionContext.getIncomingContent()`,
  `TransitionContext.positionContents(int, int, int, int)`, `TransitionContext.blendIncoming(int)`
  and `TransitionContext.animate(Animation)`.
  - Migration: a frame draws the incoming page with `drawIncoming(g, x, y, alpha)` at the coordinates
    and the opacity that used to be passed to `positionContents` and `blendIncoming`. The outgoing
    page is no longer reachable: it is the frame already on the display, so it can be neither moved
    nor faded. A slide that used to push both pages now moves the incoming one over a stationary
    outgoing one.

## [1.0.1] - 2026-08-24

### Changed

- Update the license terms so that MicroEJ SDK licensees can, at their option, apply the MicroEJ SDK
  EULA to the executable software delivered by MicroEJ Corp., while the source code stays under the
  open-source license.

## [1.0.0] - 2026-08-19

### Changed

- Discard the page replaced by `replaceWith(int)` instead of keeping it in a one-entry backstack.
  The history depth is still unchanged by the replacement, but the replaced page is dropped, so the
  next `navigateBack()` reveals the entry beneath the replacing one.
  - Before, with a history of `[HOME, LIST]`: `replaceWith(DETAILS)` gave `[HOME, DETAILS]` and
    stashed `LIST`, so `navigateBack()` returned to `LIST`. Any other navigation cleared that slot.
  - Now, with the same history: `replaceWith(DETAILS)` gives `[HOME, DETAILS]` and `LIST` is gone,
    so `navigateBack()` goes to `HOME`.
  - Migration: use `navigateTo(int)` instead of `replaceWith(int)` wherever the replaced page must
    stay reachable by back navigation.

## [0.2.0] - 2026-08-18

Version 0.2.0 keeps the whole v1 navigation model — the multi-level history, back navigation, page
lifecycle, and listeners — and layers page-key identity, a factory, in-place replacement,
transitions, and a single application-wide navigator on top. The removals are `removeFromHistory`
and `setStylesheet`.

### Added

- Add `PageFactory`, the single static, non-cached factory that builds a `Page` from its `int` key and
  the argument the navigation carried, through `create(int, Object)`.
- Add `replaceWith(int)` / `replaceWith(int, Transition)`: replace the active page in place, keeping
  the replaced page in a **one-entry backstack** so the next `navigateBack()` returns to it.
- Add a transitions API in the `ej.navigation.transition` package: `Transition` (with the `IMMEDIATE`
  default), `TransitionListener`, `TransitionContext`, and the shipped `FadeTransition` and
  `SlideTransition`, rendering through the `TransitionContext` they receive; set the default with
  `setTransition(Transition)`, and pass a transition to any navigation via its overload.
- Add `getActiveKey()` and `getHistoryKeys()` alongside `getActivePage()` / `getHistory()`.
- Add argument-carrying navigation on the two operations that build a page: `navigateTo(int, Object)` /
  `navigateTo(int, Object, Transition)` and `replaceWith(int, Object)` /
  `replaceWith(int, Object, Transition)`. The argument is forwarded to `PageFactory.create(int, Object)`,
  which injects it into the page's constructor; the navigator keeps no reference to it. Back navigation
  has no such form, as it never consults the factory.
- Defer a navigation requested reentrantly, from a `Page` lifecycle callback or a `NavigationListener`
  callback of the navigation in progress, with `MicroUI.callSerially(Runnable)` instead of running it
  inline; the deferred operation reaches the factory with the argument of the original call.

### Changed

- Navigation identifies pages by `int` key resolved through the `PageFactory` instead of by `Page`
  instance: `navigateTo(int)` / `navigateBackTo(int)` replace `navigateTo(Page)` /
  `navigateBackTo(Page)`. `navigateBack()`, `getActivePage()`, `getHistory()`, and
  `NavigationListener` are unchanged. Migration: build the pages in a `PageFactory` and replace
  `navigator.navigateTo(new HomePage(navigator))` with `navigator.navigateTo(Pages.HOME)`.
- Make `Navigator` a single application-wide instance, initialized once with the `Desktop` it drives
  and the `PageFactory` that builds its pages, and rejecting any operation requested before
  initialization. Migration: replace `new Navigator(desktop)` with
  `Navigator.initialize(desktop, factory)`, then obtain the navigator with `Navigator.getInstance()`.
- History identity is now per **entry**: the same key may appear more than once in the history.

### Removed

- Remove `removeFromHistory(Page)`; history entries are now managed only through navigation
  operations (`navigateTo` / `navigateBack` / `navigateBackTo` / `replaceWith`), so out-of-band
  removal of a non-active page is no longer supported.
- Remove `setStylesheet(Stylesheet)`; the application applies the stylesheet on the `Desktop` it
  supplies to the `Navigator`.

## [0.1.0] - 2026-07-06

### Added

- Add `Navigator` controller owning the navigation history and driving a MWT `Desktop`, created with
  a default `Desktop` (`Navigator()`) or an application-supplied one (`Navigator(Desktop)`) to
  customize the render policy or input handling.
- Add `Page` base class with `getContent`, `onEntered`, and `onExited` lifecycle callbacks;
  a page carries its per-navigation data through its own constructor.
- Add instance-based navigation operations `navigateTo(Page)`, `navigateBack()`, and
  `navigateBackTo(Page)`; the application constructs the page and hands the instance to the navigator.
- Add history queries `getActivePage()` and `getHistory()` (pages oldest-first), and
  `removeFromHistory(Page)` to drop a non-active page without navigating.
- Add `setStylesheet(Stylesheet)` to apply one stylesheet to the widgets of every page.
- Add `NavigationListener` with a single `onNavigation(exitedPage, enteredPage)` callback, notified
  once per navigation of the outgoing and incoming page (`exitedPage` is `null` on the first
  navigation).

_Copyright 2026 MicroEJ Corp. All rights reserved._\
_This library is provided in source code for use, modification and test, subject to license terms._\
_Any modification of the source code will break MicroEJ Corp. warranties on the whole library._\
_Build: 7E4D1F7C_
