feat: horizontal flip with R key, baked into crop save (v1.6.0)

- R mirrors the view about the viewport centre and clears the active effects
  (same reset as double right click); pressing R again restores the original
  orientation. Pan/zoom are kept.
- Image switch, fill/fit toggle and right double click also clear the flip.
- Crop save (Ctrl+S) mirrors the output too, so the saved JPEG matches the
  on-screen view (verified in combination with rotation).
- Shortcut lists (tr/en), README and CHANGELOG updated; deb rebuilt as 1.6.0.
This commit is contained in:
Alhan committed 2026-10-14 02:28:24 +03:00
1 parent 24cab6f908
commit bad48167c8
14 files changed
+130 -10

No files matched your search

+22 -1
View File
@@ -26,6 +26,7 @@ class ImageCanvasState extends State<ImageCanvas> {
double _contrast = 1.0;
double _saturation = 1.0;
double _brightness = 0;
bool _flipH = false;
// ── Gesture tracking ──
String _interactionMode = 'none'; // 'contrast' | 'rotate' | 'saturation' | 'brightness'
@@ -165,6 +166,13 @@ class ImageCanvasState extends State<ImageCanvas> {
bool _onHardwareKey(KeyEvent event) {
final key = event.logicalKey;
if (event is KeyDownEvent) {
if (key == LogicalKeyboardKey.keyR &&
!HardwareKeyboard.instance.isControlPressed &&
!HardwareKeyboard.instance.isShiftPressed &&
!HardwareKeyboard.instance.isAltPressed) {
_toggleFlipH();
return true;
}
if (key == LogicalKeyboardKey.controlLeft ||
key == LogicalKeyboardKey.controlRight) {
_ctrlPressed = true;
@@ -202,6 +210,7 @@ class ImageCanvasState extends State<ImageCanvas> {
void _resetView() {
_tx = 0; _ty = 0; _sc = 1.0; _isFilled = WindowPersistence.filled;
_angle = 0; _contrast = 1.0; _saturation = 1.0; _brightness = 0;
_flipH = false;
_usingFullRes = false;
_imageSize = Size.zero;
_markRenderDirty();
@@ -210,10 +219,19 @@ class ImageCanvasState extends State<ImageCanvas> {
void _toggleFillFit() {
_isFilled = !_isFilled; _tx = 0; _ty = 0; _sc = 1.0;
_angle = 0; _contrast = 1.0; _saturation = 1.0; _brightness = 0;
_flipH = false;
WindowPersistence.saveFilled(_isFilled);
_markRenderDirty();
}
/// R: sağ çift tık gibi efektleri sıfırlar ve yatay aynalar; tekrar basınca geri alır.
void _toggleFlipH() {
_flipH = !_flipH;
_angle = 0; _contrast = 1.0; _saturation = 1.0; _brightness = 0;
_interactionMode = 'none';
_markRenderDirty();
}
void _handleDoubleTap() => _toggleFillFit();
void _handleScroll(PointerScrollEvent e) {
@@ -261,6 +279,7 @@ class ImageCanvasState extends State<ImageCanvas> {
_contrast = 1.0;
_saturation = 1.0;
_brightness = 0;
_flipH = false;
_interactionMode = 'none';
_markRenderDirty();
_lastRightTapTime = null;
@@ -416,6 +435,7 @@ class ImageCanvasState extends State<ImageCanvas> {
ty: _ty,
sc: _sc,
angleDeg: _angle,
flipH: _flipH,
cx: _vpSize.width / 2,
cy: _vpSize.height / 2,
k: k,
@@ -518,12 +538,13 @@ class ImageCanvasState extends State<ImageCanvas> {
},
);
if (_angle != 0) {
if (_angle != 0 || _flipH) {
imageContent = Transform(
alignment: Alignment.topLeft,
transform: Matrix4.identity()
..translate(vpCenterX, vpCenterY)
..rotateZ(angleRad)
..scale(_flipH ? -1.0 : 1.0, 1.0)
..translate(-vpCenterX, -vpCenterY),
child: imageContent,
);