Custom drawing implementation
This commit is contained in:
@@ -1,45 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_drawing_board/flutter_drawing_board.dart';
|
||||
|
||||
import 'pdf_page_display.dart';
|
||||
|
||||
/// Drawing overlay for annotating PDF pages.
|
||||
///
|
||||
/// Uses flutter_drawing_board to provide a paint canvas over the PDF.
|
||||
/// Only working in single-page mode.
|
||||
class PaintModeLayer extends StatelessWidget {
|
||||
final PdfPageDisplay pageDisplay;
|
||||
final DrawingController drawingController;
|
||||
|
||||
const PaintModeLayer({
|
||||
super.key,
|
||||
required this.pageDisplay,
|
||||
required this.drawingController,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox.expand(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxSize = Size(constraints.maxWidth, constraints.maxHeight);
|
||||
final (pageSize, _) = pageDisplay.calculateScaledPageSizes(maxSize);
|
||||
|
||||
return DrawingBoard(
|
||||
controller: drawingController,
|
||||
background: SizedBox(
|
||||
width: pageSize.width,
|
||||
height: pageSize.height,
|
||||
child: pageDisplay,
|
||||
),
|
||||
boardConstrained: true,
|
||||
minScale: 1,
|
||||
maxScale: 3,
|
||||
alignment: Alignment.topRight,
|
||||
boardBoundaryMargin: EdgeInsets.zero,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,33 @@ import 'package:flutter/material.dart';
|
||||
import 'package:pdfrx/pdfrx.dart';
|
||||
|
||||
import '../../../core/models/config.dart';
|
||||
import '../drawing/drawing.dart';
|
||||
|
||||
/// Displays PDF pages with optional two-page mode.
|
||||
/// Displays PDF pages with optional two-page mode and drawing overlay.
|
||||
class PdfPageDisplay extends StatelessWidget {
|
||||
final PdfDocument document;
|
||||
final int numPages;
|
||||
final int currentPageNumber;
|
||||
final Config config;
|
||||
|
||||
/// Controller for the left/main page drawing
|
||||
final DrawingController? leftDrawingController;
|
||||
|
||||
/// Controller for the right page drawing (two-page mode only)
|
||||
final DrawingController? rightDrawingController;
|
||||
|
||||
/// Whether drawing is enabled
|
||||
final bool drawingEnabled;
|
||||
|
||||
const PdfPageDisplay({
|
||||
super.key,
|
||||
required this.document,
|
||||
required this.numPages,
|
||||
required this.currentPageNumber,
|
||||
required this.config,
|
||||
this.leftDrawingController,
|
||||
this.rightDrawingController,
|
||||
this.drawingEnabled = false,
|
||||
});
|
||||
|
||||
/// Whether two-page mode is active and we have enough pages.
|
||||
@@ -25,55 +38,102 @@ class PdfPageDisplay extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [_buildLeftPage(), if (_showTwoPages) _buildRightPage()],
|
||||
);
|
||||
}
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxSize = Size(constraints.maxWidth, constraints.maxHeight);
|
||||
final (leftSize, rightSize) = calculateScaledPageSizes(maxSize);
|
||||
|
||||
Widget _buildLeftPage() {
|
||||
return Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
PdfPageView(
|
||||
key: ValueKey(currentPageNumber),
|
||||
document: document,
|
||||
if (_showTwoPages) {
|
||||
// Two-page mode: pages touch each other and are centered together
|
||||
return Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_buildPage(
|
||||
pageNumber: currentPageNumber,
|
||||
pageSize: leftSize,
|
||||
controller: leftDrawingController,
|
||||
),
|
||||
// Only show right page if there is one
|
||||
if (currentPageNumber < numPages)
|
||||
_buildPage(
|
||||
pageNumber: currentPageNumber + 1,
|
||||
pageSize: rightSize!,
|
||||
controller: rightDrawingController,
|
||||
)
|
||||
else
|
||||
// Empty space to keep left page position consistent on last page
|
||||
SizedBox(width: rightSize!.width, height: rightSize.height),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Single page mode
|
||||
return Center(
|
||||
child: _buildPage(
|
||||
pageNumber: currentPageNumber,
|
||||
maximumDpi: 300,
|
||||
alignment: _showTwoPages ? Alignment.centerRight : Alignment.center,
|
||||
pageSize: leftSize,
|
||||
controller: leftDrawingController,
|
||||
),
|
||||
_buildPageIndicator(currentPageNumber),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRightPage() {
|
||||
final rightPageNumber = currentPageNumber + 1;
|
||||
|
||||
return Expanded(
|
||||
Widget _buildPage({
|
||||
required int pageNumber,
|
||||
required Size pageSize,
|
||||
required DrawingController? controller,
|
||||
}) {
|
||||
final pdfPage = SizedBox(
|
||||
width: pageSize.width,
|
||||
height: pageSize.height,
|
||||
child: Stack(
|
||||
children: [
|
||||
PdfPageView(
|
||||
key: ValueKey(rightPageNumber),
|
||||
key: ValueKey(pageNumber),
|
||||
document: document,
|
||||
pageNumber: rightPageNumber,
|
||||
pageNumber: pageNumber,
|
||||
maximumDpi: 300,
|
||||
alignment: Alignment.centerLeft,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
_buildPageIndicator(rightPageNumber),
|
||||
_buildPageIndicator(pageNumber, pageSize),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// If no controller, just show the PDF
|
||||
if (controller == null) {
|
||||
return pdfPage;
|
||||
}
|
||||
|
||||
// Wrap with DrawingBoard
|
||||
return DrawingBoard(
|
||||
boardSize: pageSize,
|
||||
controller: controller,
|
||||
drawingEnabled: drawingEnabled,
|
||||
minScale: 1.0,
|
||||
maxScale: 3.0,
|
||||
alignment: Alignment.center,
|
||||
child: pdfPage,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPageIndicator(int pageNumber) {
|
||||
return Positioned.fill(
|
||||
child: Container(
|
||||
alignment: Alignment.bottomCenter,
|
||||
padding: const EdgeInsets.only(bottom: 5),
|
||||
child: Text('$pageNumber / $numPages'),
|
||||
Widget _buildPageIndicator(int pageNumber, Size pageSize) {
|
||||
return Positioned(
|
||||
bottom: 5,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'$pageNumber / $numPages',
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import '../../../core/models/config.dart';
|
||||
import 'pdf_page_display.dart';
|
||||
|
||||
/// Callback for page turn events.
|
||||
typedef PageTurnCallback = void Function(int delta);
|
||||
typedef PageTurnCallback = dynamic Function(int delta);
|
||||
|
||||
/// Gesture layer for touch-based navigation over PDF pages.
|
||||
///
|
||||
@@ -14,6 +14,7 @@ typedef PageTurnCallback = void Function(int delta);
|
||||
/// - Right side: Turn page forward (+1 or +2 in two-page mode)
|
||||
class TouchNavigationLayer extends StatelessWidget {
|
||||
final PdfPageDisplay pageDisplay;
|
||||
final Widget child;
|
||||
final Config config;
|
||||
final VoidCallback onToggleFullscreen;
|
||||
final VoidCallback onExit;
|
||||
@@ -22,6 +23,7 @@ class TouchNavigationLayer extends StatelessWidget {
|
||||
const TouchNavigationLayer({
|
||||
super.key,
|
||||
required this.pageDisplay,
|
||||
required this.child,
|
||||
required this.config,
|
||||
required this.onToggleFullscreen,
|
||||
required this.onExit,
|
||||
@@ -33,7 +35,7 @@ class TouchNavigationLayer extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTapUp: (details) => _handleTap(context, details),
|
||||
child: pageDisplay,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user