Refactor menu structure and add Flutter-specific input and persistence layers
- Moved menu-related classes to a new structure under `src/menu/`. - Introduced `WolfMenuPresentation` to handle menu art and mappings. - Added `MenuManager` tests to ensure menu state reflects game status. - Implemented `FlutterRendererSettingsPersistence` and `FlutterSaveGamePersistence` for managing settings and save files on desktop platforms. - Created `Wolf3dFlutterInput` to handle keyboard and mouse input in a Flutter environment. - Updated README to reflect new package structure and usage instructions. Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -8,6 +8,8 @@ import 'game_data_picker_manager.dart';
|
||||
|
||||
/// GUI-host fallback screen shown when no Wolf3D game data is discovered.
|
||||
class NoGameDataScreen extends StatelessWidget {
|
||||
static const WolfMenuPresentation _menu = WolfMenuPresentation.classic();
|
||||
|
||||
/// Creates the no-data screen with app-owned setup actions.
|
||||
const NoGameDataScreen({
|
||||
super.key,
|
||||
@@ -67,22 +69,22 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
static Color _stateColor(GameDataVersionState state) {
|
||||
switch (state) {
|
||||
case GameDataVersionState.ready:
|
||||
return Color(WolfMenuPalette.emphasisColor);
|
||||
return Color(_menu.emphasisColor);
|
||||
case GameDataVersionState.checksumWarning:
|
||||
return Color(WolfMenuPalette.warningColor);
|
||||
return Color(_menu.warningColor);
|
||||
case GameDataVersionState.incomplete:
|
||||
return Color(WolfMenuPalette.mutedColor);
|
||||
return Color(_menu.mutedColor);
|
||||
}
|
||||
}
|
||||
|
||||
static Color _fileStateColor(GameDataFileState state) {
|
||||
switch (state) {
|
||||
case GameDataFileState.ready:
|
||||
return Color(WolfMenuPalette.emphasisColor);
|
||||
return Color(_menu.emphasisColor);
|
||||
case GameDataFileState.warning:
|
||||
return Color(WolfMenuPalette.warningColor);
|
||||
return Color(_menu.warningColor);
|
||||
case GameDataFileState.missing:
|
||||
return Color(WolfMenuPalette.mutedColor);
|
||||
return Color(_menu.mutedColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
scanResult?.readyVersions ?? <GameDataVersionAnalysis>[];
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Color(WolfMenuPalette.backgroundColor),
|
||||
backgroundColor: Color(_menu.backgroundColor),
|
||||
body: LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||
return SingleChildScrollView(
|
||||
@@ -106,9 +108,9 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
constraints: const BoxConstraints(maxWidth: 640),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(WolfMenuPalette.panelColor),
|
||||
color: Color(_menu.panelColor),
|
||||
border: Border.all(
|
||||
color: Color(WolfMenuPalette.borderColor),
|
||||
color: Color(_menu.borderColor),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
@@ -121,7 +123,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
Text(
|
||||
'WOLF3D DATA NOT FOUND',
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.titleColor),
|
||||
color: Color(_menu.titleColor),
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -131,7 +133,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
'No game files were discovered.\n\n'
|
||||
'Select a game-data directory, or select one or more game-data files.',
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.bodyColor),
|
||||
color: Color(_menu.bodyColor),
|
||||
fontSize: 15,
|
||||
height: 1.4,
|
||||
),
|
||||
@@ -140,7 +142,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
Text(
|
||||
'A complete version can be loaded directly or imported into the app config folder.',
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.emphasisColor),
|
||||
color: Color(_menu.emphasisColor),
|
||||
fontSize: 14,
|
||||
height: 1.35,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -179,7 +181,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
child: Text(
|
||||
'Scanning selected locations...',
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.bodyColor),
|
||||
color: Color(_menu.bodyColor),
|
||||
fontSize: 13,
|
||||
height: 1.3,
|
||||
),
|
||||
@@ -188,8 +190,8 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
if (scanResult != null) ...[
|
||||
const SizedBox(height: 18),
|
||||
_ScanSummary(
|
||||
bodyColor: Color(WolfMenuPalette.bodyColor),
|
||||
mutedColor: Color(WolfMenuPalette.mutedColor),
|
||||
bodyColor: Color(_menu.bodyColor),
|
||||
mutedColor: Color(_menu.mutedColor),
|
||||
scanResult: scanResult!,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
@@ -197,15 +199,11 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
(GameDataVersionAnalysis analysis) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: _VersionCard(
|
||||
panelColor: Color(
|
||||
WolfMenuPalette.backgroundColor,
|
||||
),
|
||||
borderColor: Color(
|
||||
WolfMenuPalette.borderColor,
|
||||
),
|
||||
titleColor: Color(WolfMenuPalette.titleColor),
|
||||
bodyColor: Color(WolfMenuPalette.bodyColor),
|
||||
mutedColor: Color(WolfMenuPalette.mutedColor),
|
||||
panelColor: Color(_menu.backgroundColor),
|
||||
borderColor: Color(_menu.borderColor),
|
||||
titleColor: Color(_menu.titleColor),
|
||||
bodyColor: Color(_menu.bodyColor),
|
||||
mutedColor: Color(_menu.mutedColor),
|
||||
analysis: analysis,
|
||||
),
|
||||
),
|
||||
@@ -217,18 +215,18 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
initialValue:
|
||||
selectedReadyVersion ??
|
||||
readyVersions.first.version,
|
||||
dropdownColor: Color(WolfMenuPalette.panelColor),
|
||||
dropdownColor: Color(_menu.panelColor),
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.bodyColor),
|
||||
color: Color(_menu.bodyColor),
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Complete version',
|
||||
labelStyle: TextStyle(
|
||||
color: Color(WolfMenuPalette.bodyColor),
|
||||
color: Color(_menu.bodyColor),
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color(WolfMenuPalette.borderColor),
|
||||
color: Color(_menu.borderColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -275,7 +273,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
child: Text(
|
||||
pickerError!.trim(),
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.emphasisColor),
|
||||
color: Color(_menu.emphasisColor),
|
||||
fontSize: 13,
|
||||
height: 1.3,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -289,7 +287,7 @@ class NoGameDataScreen extends StatelessWidget {
|
||||
child: Text(
|
||||
'Configured data directory: ${configuredDataDirectory!.trim()}',
|
||||
style: TextStyle(
|
||||
color: Color(WolfMenuPalette.bodyColor),
|
||||
color: Color(_menu.bodyColor),
|
||||
fontSize: 13,
|
||||
height: 1.3,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user