pan/scale draft

This commit is contained in:
open-trade 2020-11-23 23:18:42 +08:00
parent 479b8303d7
commit d116251742
3 changed files with 131 additions and 17 deletions

View File

@ -16,13 +16,15 @@ class App extends StatelessWidget {
value: FFI.imageModel,
child: ChangeNotifierProvider.value(
value: FFI.cursorModel,
child: MaterialApp(
title: 'RustDesk',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(title: 'RustDesk'),
))));
child: ChangeNotifierProvider.value(
value: FFI.canvasModel,
child: MaterialApp(
title: 'RustDesk',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(title: 'RustDesk'),
)))));
}
}

View File

@ -6,6 +6,7 @@ import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
import 'dart:async';
import 'common.dart';
@ -47,6 +48,8 @@ class FfiModel with ChangeNotifier {
print('$_permissions');
}
bool keyboard() => _permissions['keyboard'] == true;
void clear() {
_pi = PeerInfo();
_display = Display();
@ -151,9 +154,50 @@ class ImageModel with ChangeNotifier {
}
}
class CanvasModel with ChangeNotifier {
double _x;
double _y;
double _scale;
double _xPan;
double _yPan;
CanvasModel() {
clear();
}
double get x => _x;
double get y => _y;
double get scale => _scale;
void startPan() {
_xPan = 0;
_yPan = 0;
}
void updateOffset(double dx, double dy) {
_x += dx;
_y += dy;
notifyListeners();
}
void updateScale(double v) {
_scale *= v;
if (_scale > 1) _scale = 1;
notifyListeners();
}
void clear() {
_x = 0;
_y = 0;
_scale = 1.0;
_xPan = 0;
_yPan = 0;
}
}
class CursorModel with ChangeNotifier {
ui.Image _image;
final _images = Map<int, ui.Image>();
final _images = Map<int, Tuple3<ui.Image, double, double>>();
double _x = -10000;
double _y = -10000;
double _hotx = 0;
@ -162,8 +206,10 @@ class CursorModel with ChangeNotifier {
double _displayOriginY = 0;
ui.Image get image => _image;
double get x => _x - _displayOriginX - _hotx;
double get y => _y - _displayOriginY - _hoty;
double get x => _x - _displayOriginX;
double get y => _y - _displayOriginY;
double get hotx => _hotx;
double get hoty => _hoty;
void updateCursorData(Map<String, dynamic> evt) {
var id = int.parse(evt['id']);
@ -176,7 +222,7 @@ class CursorModel with ChangeNotifier {
ui.decodeImageFromPixels(rgba, width, height, ui.PixelFormat.rgba8888,
(image) {
_image = image;
_images[id] = image;
_images[id] = Tuple3(image, _hotx, _hoty);
try {
// my throw exception, because the listener maybe already dispose
notifyListeners();
@ -187,7 +233,9 @@ class CursorModel with ChangeNotifier {
void updateCursorId(Map<String, dynamic> evt) {
final tmp = _images[int.parse(evt['id'])];
if (tmp != null) {
_image = tmp;
_image = tmp.item1;
_hotx = tmp.item2;
_hoty = tmp.item3;
notifyListeners();
}
}
@ -222,6 +270,7 @@ class FFI {
static final imageModel = ImageModel();
static final ffiModel = FfiModel();
static final cursorModel = CursorModel();
static final canvasModel = CanvasModel();
static String getId() {
return getByName('remote_id');
@ -283,6 +332,7 @@ class FFI {
FFI.imageModel.update(null);
FFI.cursorModel.clear();
FFI.ffiModel.clear();
FFI.canvasModel.clear();
}
static void setByName(String name, [String value = '']) {

View File

@ -27,6 +27,9 @@ class _RemotePageState extends State<RemotePage> {
bool _showBar = true;
double _bottom = 0;
var _scaleMode = false;
double _xOffset = 0;
double _yOffset = 0;
double _scale = 1;
final FocusNode _focusNode = FocusNode();
@override
@ -153,8 +156,55 @@ class _RemotePageState extends State<RemotePage> {
),
)
: null,
body: RawGestureDetector(
gestures: buildGuestures(),
body: GestureDetector(
onLongPressStart: (details) {
var x = details.globalPosition.dx;
var y = details.globalPosition.dy;
print('long press');
() async {
var value = await showMenu(
context: context,
position:
RelativeRect.fromLTRB(x + 20, y + 20, x + 20, y + 20),
items: [
PopupMenuItem<String>(
child: Text(_scaleMode ? 'Pan Mode' : 'Scale Mode'),
value: 'mode'),
],
elevation: 8.0,
);
if (value == 'mode') {
setState(() => _scaleMode = !_scaleMode);
}
}();
},
onDoubleTap: () {
print('double tap');
},
onTap: () {
print('tap');
},
onScaleStart: (details) {
_scale = 1;
_xOffset = details.focalPoint.dx;
_yOffset = details.focalPoint.dy;
FFI.canvasModel.startPan();
},
onScaleUpdate: (details) {
var scale = details.scale;
if (scale == 1) {
var x = details.focalPoint.dx;
var y = details.focalPoint.dy;
var dx = x - _xOffset;
var dy = y - _yOffset;
FFI.canvasModel.updateOffset(dx, dy);
_xOffset = x;
_yOffset = y;
} else {
FFI.canvasModel.updateScale(scale / _scale);
_scale = scale;
}
},
child: FlutterEasyLoading(
child: Container(
color: MyTheme.canvasColor,
@ -288,8 +338,11 @@ class ImagePaint extends StatelessWidget {
@override
Widget build(BuildContext context) {
final m = Provider.of<ImageModel>(context);
final c = Provider.of<CanvasModel>(context);
var s = c.scale;
return CustomPaint(
painter: new ImagePainter(image: m.image, x: 0, y: 0),
painter:
new ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s),
);
}
}
@ -298,8 +351,14 @@ class CursorPaint extends StatelessWidget {
@override
Widget build(BuildContext context) {
final m = Provider.of<CursorModel>(context);
final c = Provider.of<CanvasModel>(context);
var s = c.scale;
return CustomPaint(
painter: new ImagePainter(image: m.image, x: m.x, y: m.y),
painter: new ImagePainter(
image: m.image,
x: m.x * s - m.hotx + c.x,
y: m.y * s - m.hoty + c.y,
scale: 1),
);
}
}
@ -309,15 +368,18 @@ class ImagePainter extends CustomPainter {
this.image,
this.x,
this.y,
this.scale,
});
ui.Image image;
double x;
double y;
double scale;
@override
void paint(Canvas canvas, Size size) {
if (image == null) return;
canvas.scale(scale, scale);
canvas.drawImage(image, new Offset(x, y), new Paint());
}