Gesture editor logic done. #4
@@ -8,6 +8,109 @@ import 'package:uuid/uuid.dart';
|
||||
|
||||
typedef OnEditEnd(GestureProp prop);
|
||||
|
||||
class _TreeNode<T> {
|
||||
late List<T> nodes;
|
||||
|
||||
bool get fullFiled => nodes.every((element) => (element as _TreeNode).fullFiled);
|
||||
|
||||
T get availableNode => nodes.firstWhere((element) => !(element as _TreeNode).fullFiled);
|
||||
}
|
||||
|
||||
class GestureDirectionNode extends _TreeNode {
|
||||
GestureDirection direction;
|
||||
bool available = true;
|
||||
|
||||
GestureDirectionNode({required this.direction});
|
||||
|
||||
@override
|
||||
get fullFiled => !available;
|
||||
|
||||
get availableNode => null;
|
||||
}
|
||||
|
||||
class SchemeGestureNode extends _TreeNode<GestureDirectionNode> {
|
||||
Gesture type;
|
||||
|
||||
SchemeGestureNode({required this.type}) {
|
||||
switch (type) {
|
||||
case Gesture.tap:
|
||||
nodes = [GestureDirectionNode(direction: GestureDirection.none)];
|
||||
break;
|
||||
case Gesture.swipe:
|
||||
nodes = [
|
||||
GestureDirectionNode(direction: GestureDirection.up),
|
||||
GestureDirectionNode(direction: GestureDirection.down),
|
||||
GestureDirectionNode(direction: GestureDirection.left),
|
||||
GestureDirectionNode(direction: GestureDirection.right),
|
||||
];
|
||||
break;
|
||||
case Gesture.pinch:
|
||||
nodes = [
|
||||
GestureDirectionNode(direction: GestureDirection.pinch_in),
|
||||
GestureDirectionNode(direction: GestureDirection.pinch_out),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SchemeTreeNode extends _TreeNode<SchemeGestureNode> {
|
||||
int fingers;
|
||||
|
||||
SchemeTreeNode({required this.fingers});
|
||||
|
||||
@override
|
||||
List<SchemeGestureNode> nodes = [
|
||||
SchemeGestureNode(type: Gesture.tap),
|
||||
SchemeGestureNode(type: Gesture.swipe),
|
||||
SchemeGestureNode(type: Gesture.pinch),
|
||||
];
|
||||
}
|
||||
|
||||
class SchemeTree extends _TreeNode<SchemeTreeNode> {
|
||||
@override
|
||||
List<SchemeTreeNode> nodes = [
|
||||
SchemeTreeNode(fingers: 3),
|
||||
SchemeTreeNode(fingers: 4),
|
||||
SchemeTreeNode(fingers: 5),
|
||||
];
|
||||
|
||||
@override
|
||||
String toString() => '''
|
||||
3:
|
||||
tap: ${nodes[0].nodes[0].nodes[0].available}
|
||||
swipe:
|
||||
↑: ${nodes[0].nodes[1].nodes[0].available}
|
||||
↓: ${nodes[0].nodes[1].nodes[1].available}
|
||||
←: ${nodes[0].nodes[1].nodes[2].available}
|
||||
→: ${nodes[0].nodes[1].nodes[3].available}
|
||||
pinch:
|
||||
in: ${nodes[0].nodes[2].nodes[0].available}
|
||||
out:${nodes[0].nodes[2].nodes[1].available}
|
||||
|
||||
4:
|
||||
tap: ${nodes[1].nodes[0].nodes[0].available}
|
||||
swipe:
|
||||
↑: ${nodes[1].nodes[1].nodes[0].available}
|
||||
↓: ${nodes[1].nodes[1].nodes[1].available}
|
||||
←: ${nodes[1].nodes[1].nodes[2].available}
|
||||
→: ${nodes[1].nodes[1].nodes[3].available}
|
||||
pinch:
|
||||
in: ${nodes[1].nodes[2].nodes[0].available}
|
||||
out:${nodes[1].nodes[2].nodes[1].available}
|
||||
|
||||
5:
|
||||
tap: ${nodes[2].nodes[0].nodes[0].available}
|
||||
swipe:
|
||||
↑: ${nodes[2].nodes[1].nodes[0].available}
|
||||
↓: ${nodes[2].nodes[1].nodes[1].available}
|
||||
←: ${nodes[2].nodes[1].nodes[2].available}
|
||||
→: ${nodes[2].nodes[1].nodes[3].available}
|
||||
pinch:
|
||||
in: ${nodes[2].nodes[2].nodes[0].available}
|
||||
out:${nodes[2].nodes[2].nodes[1].available}
|
||||
''';
|
||||
}
|
||||
|
||||
@ProviderModel(copyable: true)
|
||||
class Scheme {
|
||||
@ProviderModelProp()
|
||||
@@ -41,6 +144,16 @@ class Scheme {
|
||||
Scheme.create({this.name, this.description, this.gestures}) {
|
||||
this.id = Uuid().v1();
|
||||
}
|
||||
|
||||
SchemeTree buildSchemeTree() {
|
||||
var schemeTree = SchemeTree();
|
||||
this.gestures!.forEach((gesture) {
|
||||
var schemeTreeNode = schemeTree.nodes.firstWhere((ele) => ele.fingers == gesture.fingers);
|
||||
var schemeGestureNode = schemeTreeNode.nodes.firstWhere((element) => element.type == gesture.gesture);
|
||||
schemeGestureNode.nodes.firstWhere((element) => element.direction == gesture.direction).available = false;
|
||||
});
|
||||
return schemeTree;
|
||||
}
|
||||
}
|
||||
|
||||
enum Gesture {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.provider.dart';
|
||||
import 'package:dde_gesture_manager/pages/gesture_editor.dart';
|
||||
import 'package:dde_gesture_manager/pages/local_manager.dart';
|
||||
import 'package:dde_gesture_manager/pages/market.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Content extends StatefulWidget {
|
||||
const Content({Key? key}) : super(key: key);
|
||||
@@ -13,6 +14,10 @@ class Content extends StatefulWidget {
|
||||
_ContentState createState() => _ContentState();
|
||||
}
|
||||
|
||||
class CopiedGesturePropProvider extends GesturePropProvider {
|
||||
CopiedGesturePropProvider.empty() : super.empty();
|
||||
}
|
||||
|
||||
class _ContentState extends State<Content> {
|
||||
double? preWindowWidth;
|
||||
|
||||
@@ -21,10 +26,17 @@ class _ContentState extends State<Content> {
|
||||
var windowWidth = MediaQuery.of(context).size.width;
|
||||
var preferredPanelsStatus = H.getPreferredPanelsStatus(windowWidth);
|
||||
var widthChanged = preWindowWidth != null && preWindowWidth != windowWidth;
|
||||
var widget = ChangeNotifierProvider(
|
||||
create: (context) => ContentLayoutProvider()
|
||||
..localManagerOpened = preferredPanelsStatus.localManagerPanelOpened
|
||||
..marketOpened = preferredPanelsStatus.marketPanelOpened,
|
||||
var widget = MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => ContentLayoutProvider()
|
||||
..localManagerOpened = preferredPanelsStatus.localManagerPanelOpened
|
||||
..marketOpened = preferredPanelsStatus.marketPanelOpened,
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => CopiedGesturePropProvider.empty(),
|
||||
),
|
||||
],
|
||||
builder: (context, child) {
|
||||
if (widthChanged && mounted) {
|
||||
Future.microtask(
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/settings.provider.dart';
|
||||
import 'package:dde_gesture_manager/pages/content.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
import 'package:dde_gesture_manager/utils/keyboard_mapper.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_button.dart';
|
||||
@@ -152,7 +153,42 @@ class GestureEditor extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(height: 10),
|
||||
Builder(builder: (context) {
|
||||
var gesturePropProvider = context.watch<GesturePropProvider>();
|
||||
var copiedGesturePropProvider = context.watch<CopiedGesturePropProvider>();
|
||||
var schemeTree = schemeProvider.buildSchemeTree();
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
DButton.add(
|
||||
enabled: !gesturePropProvider.editMode! && !schemeTree.fullFiled,
|
||||
onTap: () {
|
||||
var schemeProvider = context.read<SchemeProvider>();
|
||||
schemeProvider.gestures.sout();
|
||||
context.read<SchemeProvider>().setProps(gestures: [
|
||||
...?schemeProvider.gestures,
|
||||
H.getNextAvailableGestureProp(schemeProvider.buildSchemeTree())!,
|
||||
]);
|
||||
},
|
||||
),
|
||||
DButton.delete(
|
||||
enabled: gesturePropProvider != GestureProp.empty() && !gesturePropProvider.editMode!,
|
||||
),
|
||||
DButton.duplicate(
|
||||
enabled: gesturePropProvider != GestureProp.empty() && !gesturePropProvider.editMode!,
|
||||
),
|
||||
DButton.paste(
|
||||
enabled: copiedGesturePropProvider != CopiedGesturePropProvider.empty() &&
|
||||
!gesturePropProvider.editMode!,
|
||||
),
|
||||
]
|
||||
.map((e) => Padding(
|
||||
padding: const EdgeInsets.only(top: 3.0, right: 10.0, bottom: 8.0),
|
||||
child: e,
|
||||
))
|
||||
.toList(),
|
||||
);
|
||||
}),
|
||||
Container(
|
||||
height: 300,
|
||||
decoration: BoxDecoration(
|
||||
@@ -414,9 +450,13 @@ List<DDataCell> _buildRowCellsNormal(BuildContext context, bool selected, Gestur
|
||||
},
|
||||
).toList(),
|
||||
)
|
||||
: Text(
|
||||
gesture.command ?? '',
|
||||
),
|
||||
: (gesture.type == GestureType.built_in
|
||||
? Text(
|
||||
('${LocaleKeys.built_in_commands}.${(builtInCommands.contains(gesture.command) ? gesture.command : builtInCommands.first)!}')
|
||||
.tr())
|
||||
: Text(
|
||||
gesture.command ?? '',
|
||||
)),
|
||||
Text(
|
||||
gesture.remark ?? '',
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/local_schemes_provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/settings.provider.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_button.dart';
|
||||
@@ -111,6 +112,7 @@ class _LocalManagerState extends State<LocalManager> {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
context.read<GesturePropProvider>().copyFrom(GestureProp.empty());
|
||||
},
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class H {
|
||||
H._();
|
||||
@@ -85,10 +86,10 @@ class H {
|
||||
GestureDirection.none;
|
||||
|
||||
static String? getGestureTypeName(GestureType? type) => const {
|
||||
GestureType.built_in: 'built_in',
|
||||
GestureType.shortcut: 'shortcut',
|
||||
GestureType.commandline: 'commandline',
|
||||
}[type];
|
||||
GestureType.built_in: 'built_in',
|
||||
GestureType.shortcut: 'shortcut',
|
||||
GestureType.commandline: 'commandline',
|
||||
}[type];
|
||||
|
||||
static GestureType getGestureTypeByName(String typeName) =>
|
||||
const {
|
||||
@@ -105,6 +106,19 @@ class H {
|
||||
var rgba = list.map<int>((e) => int.parse(e) ~/ 257).toList();
|
||||
return Color.fromARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
|
||||
}
|
||||
|
||||
static GestureProp? getNextAvailableGestureProp(SchemeTree tree) {
|
||||
tree.sout();
|
||||
var gestureProp = GestureProp.empty()
|
||||
..id = Uuid().v1()
|
||||
..type = GestureType.built_in
|
||||
..command = builtInCommands.first;
|
||||
if (tree.fullFiled) return null;
|
||||
gestureProp.fingers = tree.availableNode.fingers;
|
||||
gestureProp.gesture = tree.availableNode.availableNode.type;
|
||||
gestureProp.direction = tree.availableNode.availableNode.availableNode.direction;
|
||||
return gestureProp;
|
||||
}
|
||||
}
|
||||
|
||||
class PreferredPanelsStatus {
|
||||
|
||||
@@ -33,7 +33,7 @@ class DButton extends StatefulWidget {
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
onTap: enabled ? onTap : null,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.add, size: 18)),
|
||||
message: LocaleKeys.operation_add.tr(),
|
||||
@@ -50,7 +50,7 @@ class DButton extends StatefulWidget {
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
onTap: enabled ? onTap : null,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.remove, size: 18)),
|
||||
message: LocaleKeys.operation_delete.tr(),
|
||||
@@ -67,7 +67,7 @@ class DButton extends StatefulWidget {
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
onTap: enabled ? onTap : null,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.check, size: 18)),
|
||||
message: LocaleKeys.operation_apply.tr(),
|
||||
@@ -84,12 +84,29 @@ class DButton extends StatefulWidget {
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
onTap: enabled ? onTap : null,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.copy_rounded, size: 18)),
|
||||
message: LocaleKeys.operation_duplicate.tr(),
|
||||
));
|
||||
|
||||
factory DButton.paste({
|
||||
Key? key,
|
||||
required enabled,
|
||||
GestureTapCallback? onTap,
|
||||
height = defaultButtonHeight * .7,
|
||||
width = defaultButtonHeight * .7,
|
||||
}) =>
|
||||
DButton(
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: enabled ? onTap : null,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.paste_rounded, size: 18)),
|
||||
message: LocaleKeys.operation_paste.tr(),
|
||||
));
|
||||
|
||||
factory DButton.dropdown({
|
||||
Key? key,
|
||||
width = 60.0,
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
"add": "Add",
|
||||
"delete": "delete",
|
||||
"duplicate": "duplicate",
|
||||
"apply": "apply"
|
||||
"apply": "apply",
|
||||
"paste": "paste"
|
||||
},
|
||||
"str": {
|
||||
"null": "Null"
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
"add": "新增",
|
||||
"delete": "删除",
|
||||
"duplicate": "复制",
|
||||
"apply": "应用"
|
||||
"apply": "应用",
|
||||
"paste": "粘贴"
|
||||
},
|
||||
"str": {
|
||||
"null": "无"
|
||||
|
||||
Reference in New Issue
Block a user