From 1b5d8f2dbd9c4c834f70fbef099b52a1ce792a9e Mon Sep 17 00:00:00 2001 From: Jean Bovet Date: Sat, 8 May 2021 19:22:02 -0700 Subject: [PATCH] Moved information to the right side of the window --- BChess.xcodeproj/project.pbxproj | 12 +-- .../xcschemes/BChess (macOS).xcscheme | 88 +++++++++++++++++++ Shared/Engine/Engine/ChessEngine.hpp | 2 +- Shared/Engine/Engine/ChessGame.cpp | 2 +- Shared/Engine/Helpers/FPGN.cpp | 17 ++-- Shared/Engine/Helpers/FPGN.hpp | 3 +- Shared/Views/ContentView.swift | 47 +++++----- ...mationView.swift => InformationView.swift} | 18 ++-- Shared/Views/TopInformationView.swift | 17 ++-- 9 files changed, 150 insertions(+), 56 deletions(-) create mode 100644 BChess.xcodeproj/xcshareddata/xcschemes/BChess (macOS).xcscheme rename Shared/Views/{BottomInformationView.swift => InformationView.swift} (85%) diff --git a/BChess.xcodeproj/project.pbxproj b/BChess.xcodeproj/project.pbxproj index 28fc485..1ebeb59 100644 --- a/BChess.xcodeproj/project.pbxproj +++ b/BChess.xcodeproj/project.pbxproj @@ -74,8 +74,8 @@ A79515AA25ABE31100AEA95F /* SquareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515A825ABE31100AEA95F /* SquareView.swift */; }; A79515B425ABE34300AEA95F /* TopInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515B325ABE34300AEA95F /* TopInformationView.swift */; }; A79515B525ABE34300AEA95F /* TopInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515B325ABE34300AEA95F /* TopInformationView.swift */; }; - A79515BF25ABE36700AEA95F /* BottomInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515BE25ABE36700AEA95F /* BottomInformationView.swift */; }; - A79515C025ABE36700AEA95F /* BottomInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515BE25ABE36700AEA95F /* BottomInformationView.swift */; }; + A79515BF25ABE36700AEA95F /* InformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515BE25ABE36700AEA95F /* InformationView.swift */; }; + A79515C025ABE36700AEA95F /* InformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515BE25ABE36700AEA95F /* InformationView.swift */; }; A79515CA25ABE38F00AEA95F /* LastMoveModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515C925ABE38F00AEA95F /* LastMoveModifier.swift */; }; A79515CB25ABE38F00AEA95F /* LastMoveModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515C925ABE38F00AEA95F /* LastMoveModifier.swift */; }; A79515D525ABE3A400AEA95F /* SelectionModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79515D425ABE3A400AEA95F /* SelectionModifier.swift */; }; @@ -258,7 +258,7 @@ A795159D25ABE1D700AEA95F /* PiecesFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiecesFactory.swift; sourceTree = ""; }; A79515A825ABE31100AEA95F /* SquareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SquareView.swift; sourceTree = ""; }; A79515B325ABE34300AEA95F /* TopInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopInformationView.swift; sourceTree = ""; }; - A79515BE25ABE36700AEA95F /* BottomInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomInformationView.swift; sourceTree = ""; }; + A79515BE25ABE36700AEA95F /* InformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InformationView.swift; sourceTree = ""; }; A79515C925ABE38F00AEA95F /* LastMoveModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastMoveModifier.swift; sourceTree = ""; }; A79515D425ABE3A400AEA95F /* SelectionModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionModifier.swift; sourceTree = ""; }; A79515DF25ABE3D300AEA95F /* Selection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Selection.swift; sourceTree = ""; }; @@ -534,7 +534,7 @@ A79515D425ABE3A400AEA95F /* SelectionModifier.swift */, A79515A825ABE31100AEA95F /* SquareView.swift */, A79515B325ABE34300AEA95F /* TopInformationView.swift */, - A79515BE25ABE36700AEA95F /* BottomInformationView.swift */, + A79515BE25ABE36700AEA95F /* InformationView.swift */, A795163C25ABE66600AEA95F /* BoardView.swift */, A79515F525ABE44000AEA95F /* PiecesView.swift */, A7A30EDC25AEBD7C00729432 /* LabelsView.swift */, @@ -878,7 +878,7 @@ A7FE31EE25AA96B900A75936 /* ChessMoveGenerator.cpp in Sources */, A79514EC25AAE2C400AEA95F /* FENgineInfo+Extension.swift in Sources */, A79515EB25ABE41000AEA95F /* Position.swift in Sources */, - A79515BF25ABE36700AEA95F /* BottomInformationView.swift in Sources */, + A79515BF25ABE36700AEA95F /* InformationView.swift in Sources */, A7FE31EB25AA96B900A75936 /* MoveList.cpp in Sources */, A7FE324D25AAD61200A75936 /* FEngineMove.mm in Sources */, A77F66D525A832270030E61D /* BChessUIApp.swift in Sources */, @@ -925,7 +925,7 @@ A7FE321A25AA96D000A75936 /* ChessBoardHash.cpp in Sources */, A79514F925AAE2C500AEA95F /* FENgineInfo+Extension.swift in Sources */, A79515EC25ABE41000AEA95F /* Position.swift in Sources */, - A79515C025ABE36700AEA95F /* BottomInformationView.swift in Sources */, + A79515C025ABE36700AEA95F /* InformationView.swift in Sources */, A7FE31FD25AA96C500A75936 /* ChessState.cpp in Sources */, A7FE321925AA96D000A75936 /* FFEN.cpp in Sources */, A7BC72E52636003F008FBBB4 /* NewGameView.swift in Sources */, diff --git a/BChess.xcodeproj/xcshareddata/xcschemes/BChess (macOS).xcscheme b/BChess.xcodeproj/xcshareddata/xcschemes/BChess (macOS).xcscheme new file mode 100644 index 0000000..571e9bf --- /dev/null +++ b/BChess.xcodeproj/xcshareddata/xcschemes/BChess (macOS).xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Shared/Engine/Engine/ChessEngine.hpp b/Shared/Engine/Engine/ChessEngine.hpp index 709d9a5..357d712 100644 --- a/Shared/Engine/Engine/ChessEngine.hpp +++ b/Shared/Engine/Engine/ChessEngine.hpp @@ -62,7 +62,7 @@ class ChessEngine { } std::string getPGNForDisplay() { - return FPGN::getGame(game, FPGN::Formatting::history); + return FPGN::getGame(game, FPGN::Formatting::history, 0, game.getNumberOfMoves()); } std::string getPieceAt(File file, Rank rank) { diff --git a/Shared/Engine/Engine/ChessGame.cpp b/Shared/Engine/Engine/ChessGame.cpp index 3f9daf2..42ea832 100644 --- a/Shared/Engine/Engine/ChessGame.cpp +++ b/Shared/Engine/Engine/ChessGame.cpp @@ -131,7 +131,7 @@ bool ChessGame::canUndoMove() { } bool ChessGame::canRedoMove() { - return moveIndexes.moveCursor < getNumberOfMoves(); + return moveIndexes.moveCursor < moveIndexes.moves.size(); } void ChessGame::undoMove() { diff --git a/Shared/Engine/Helpers/FPGN.cpp b/Shared/Engine/Helpers/FPGN.cpp index 13a7769..93823e2 100644 --- a/Shared/Engine/Helpers/FPGN.cpp +++ b/Shared/Engine/Helpers/FPGN.cpp @@ -751,6 +751,7 @@ static void getPGN(ChessBoard board, // The chess board representation which is std::string & pgn, // The PGN being constructed int moveIndex, // The current move index int fromMoveIndex, // The move index at which we starts to build up the PGN + int toMoveIndex, // The move index at which to stop building up the PGN int fullMoveIndex, // The number of full move that have been done so far bool mainLine, // True if this node/move represents the main line, false if it represents a variation bool recursive, // True if this method should continue to traverse the next move and all its variation, false to just output this move and return @@ -762,6 +763,10 @@ static void getPGN(ChessBoard board, // The chess board representation which is if (formatting == FPGN::Formatting::line && moveIndex == fromMoveIndex && !skip) { pgn = ""; } + + if (moveIndex >= toMoveIndex && !skip) { + return; + } FPGN::SANType sanType = FPGN::SANType::full; auto matchingMoves = getMatchingMoves(board, MOVE_TO(move), piece, MOVE_PROMOTION_PIECE(move), FileUndefined, RankUndefined); @@ -850,31 +855,31 @@ static void getPGN(ChessBoard board, // The chess board representation which is // If there is only one variation, it is easy: it is the main line // so continue recursively to traverse it. auto & main = node.variations[0]; - getPGN(board, formatting, main, pgn, moveIndex+1, fromMoveIndex, fullMoveIndex, /*mainline*/true, /*recursive*/true, /*skip*/false); + getPGN(board, formatting, main, pgn, moveIndex+1, fromMoveIndex, toMoveIndex, fullMoveIndex, /*mainline*/true, /*recursive*/true, /*skip*/false); } else { // If there are more than one variation, we need to print first the main variation but for only one move // For example: 1. e4 e5 auto & main = node.variations[0]; - getPGN(board, formatting, main, pgn, moveIndex+1, fromMoveIndex, fullMoveIndex, /*mainline*/true, /*recursive*/false, /*skip*/false); + getPGN(board, formatting, main, pgn, moveIndex+1, fromMoveIndex, toMoveIndex, fullMoveIndex, /*mainline*/true, /*recursive*/false, /*skip*/false); // And then print all the other variations in full (recursively) // For example: 1. e4 e5 (1... d5) for (int vindex=1; vindex 0) { pgn += " ("; } - getPGN(outputBoard, formatting, node, pgn, 0, fromIndex, fullMoveIndex, /*mainline*/vindex == 0, /*recursive*/true, /*skip*/false); + getPGN(outputBoard, formatting, node, pgn, 0, fromIndex, toIndex, fullMoveIndex, /*mainline*/vindex == 0, /*recursive*/true, /*skip*/false); if (vindex > 0) { pgn += ")"; } diff --git a/Shared/Engine/Helpers/FPGN.hpp b/Shared/Engine/Helpers/FPGN.hpp index 19b1a85..f661702 100644 --- a/Shared/Engine/Helpers/FPGN.hpp +++ b/Shared/Engine/Helpers/FPGN.hpp @@ -77,7 +77,8 @@ class FPGN { // fromIndex: the index from which to start building the PGN. Used to display a line from a game during analysis, // which means we only want to display the game after the current move (to show the thinking of the computer). // This parameter takes effect only if the Formatting is set to line - static std::string getGame(ChessGame game, Formatting formatting = FPGN::Formatting::storage, int fromIndex = 0); + // toIndex: the index at which to stop building the PGN. + static std::string getGame(ChessGame game, Formatting formatting = FPGN::Formatting::storage, int fromIndex = 0, int toIndex = INT_MAX); private: std::string pgn = ""; diff --git a/Shared/Views/ContentView.swift b/Shared/Views/ContentView.swift index 1f411b4..29f7cee 100644 --- a/Shared/Views/ContentView.swift +++ b/Shared/Views/ContentView.swift @@ -17,32 +17,33 @@ struct ContentView: View { @State private var newGameSheetEditMode = false var body: some View { - VStack(alignment: .leading) { - if (showInfo || document.state != .play) { - HStack { - TopInformationView(document: document) - Spacer() - AnalyzeActionsView(document: $document) - .hide(document.state == .play) - Spacer() + HStack(alignment: .top) { + VStack(alignment: .leading) { + ColorInformationView(document: $document, isWhite: document.rotated ? true: false) + ZStack { + BoardView(document: $document) + .if(document.state == .analyze) { + $0.border(Color.yellow, width: 4) + } + .if(document.state == .train) { + $0.border(Color.green, width: 4) + } + LabelsView(document: $document) + PiecesView(document: $document) } + .padding() + .padding(.bottom, 20) // Because the labels are "leaking" a bit below the board space itself + ColorInformationView(document: $document, isWhite: document.rotated ? false: true) } - - ZStack { - BoardView(document: $document) - .if(document.state == .analyze) { - $0.border(Color.yellow, width: 4) - } - .if(document.state == .train) { - $0.border(Color.green, width: 4) - } - LabelsView(document: $document) - PiecesView(document: $document) - }.padding() - if (showInfo) { - BottomInformationView(document: document) - .padding(.top) + VStack { + AnalyzeActionsView(document: $document) + .hide(document.state == .play) + + if (showInfo) { + InformationView(document: document) + .frame(minWidth: 250, idealWidth: 250, maxWidth: 300, alignment: .center) + } } } .padding() diff --git a/Shared/Views/BottomInformationView.swift b/Shared/Views/InformationView.swift similarity index 85% rename from Shared/Views/BottomInformationView.swift rename to Shared/Views/InformationView.swift index 1d75067..79fe5cc 100644 --- a/Shared/Views/BottomInformationView.swift +++ b/Shared/Views/InformationView.swift @@ -8,7 +8,7 @@ import SwiftUI -struct BottomInformationView: View { +struct InformationView: View { let document: ChessDocument @@ -64,22 +64,22 @@ struct BottomInformationView: View { VStack(alignment: .leading) { if let opening = document.engine.openingName() { Text(opening) + .padding(.bottom) } else { if document.state == .play { - HStack { - Text("Eval").bold() + HStack() { + Image(systemName: "cpu") Text(value()) } + .padding(.bottom) HStack { - Text("Stats").bold() + Text(Image(systemName: "speedometer")) Text(speed()) } + .padding(.bottom) } } - HStack { - Text("Moves").bold() - Text(document.engine.pgnFormattedForDisplay()) - } + Text(document.engine.pgnFormattedForDisplay()) } } } @@ -87,6 +87,6 @@ struct BottomInformationView: View { struct BottomInformationView_Previews: PreviewProvider { static var previews: some View { let doc = ChessDocument(pgn: "1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nc3 dxe5 *") - BottomInformationView(document: doc) + InformationView(document: doc) } } diff --git a/Shared/Views/TopInformationView.swift b/Shared/Views/TopInformationView.swift index 135990d..72e0dc3 100644 --- a/Shared/Views/TopInformationView.swift +++ b/Shared/Views/TopInformationView.swift @@ -10,7 +10,7 @@ import SwiftUI struct ColorInformationView: View { - let document: ChessDocument + @Binding var document: ChessDocument let isWhite: Bool func capturedPieces() -> [String] { @@ -86,13 +86,12 @@ struct ColorInformationView: View { struct TopInformationView: View { - let document: ChessDocument - - + @Binding var document: ChessDocument + var body: some View { VStack(alignment: .leading) { - ColorInformationView(document: document, isWhite: true) - ColorInformationView(document: document, isWhite: false) + ColorInformationView(document: $document, isWhite: true) + ColorInformationView(document: $document, isWhite: false) } } } @@ -101,15 +100,15 @@ struct TopInformationView_Previews: PreviewProvider { static var previews: some View { Group { let doc = ChessDocument(pgn: "1. e4 e5") - TopInformationView(document: doc) + TopInformationView(document: .constant(doc)) } Group { let doc = ChessDocument(pgn: "1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nc3 dxe5 ") - TopInformationView(document: doc) + TopInformationView(document: .constant(doc)) } Group { let doc = ChessDocument(pgn: "1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nc3 dxe5 5. d4 exd4 6. Qxd4 Qxd4 7. Nd5 Nxd5 8. Bb5+ c6 9. Bxc6+ Nxc6 *") - TopInformationView(document: doc) + TopInformationView(document: .constant(doc)) } } }