Editor almost done. #3
@@ -22,7 +22,9 @@ class ProviderGenerator extends GeneratorForAnnotation<ProviderModel> {
|
||||
List<AnnotationField> fields = [];
|
||||
element.fields.forEach((field) {
|
||||
var annotation = field.metadata.firstWhereOrNull(
|
||||
(m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp');
|
||||
(m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp') ??
|
||||
field.getter?.metadata.firstWhereOrNull(
|
||||
(m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp');
|
||||
if (annotation != null)
|
||||
fields.add(
|
||||
AnnotationField(
|
||||
@@ -77,7 +79,7 @@ String? _genCopyFunc(String displayName, List<AnnotationField> fields, bool copy
|
||||
return '''
|
||||
void copyFrom(${displayName} other) {
|
||||
bool changed = false;
|
||||
${fields.map((f) => 'if (other.${f.name}.diff(this.${f.name})) {this.${f.name} = other.${f.name}; changed = true; }').join('\n')}
|
||||
${fields.map((f) => 'if (other.${f.name} != this.${f.name}) {this.${f.name} = other.${f.name}; changed = true; }').join('\n')}
|
||||
if (changed) notifyListeners();
|
||||
}
|
||||
''';
|
||||
|
||||
@@ -20,6 +20,23 @@ const double defaultBorderRadius = 8;
|
||||
|
||||
const double defaultButtonHeight = 36;
|
||||
|
||||
const List<String> builtInCommands = [
|
||||
'ShowWorkspace',
|
||||
'Handle4Or5FingersSwipeUp',
|
||||
'Handle4Or5FingersSwipeDown',
|
||||
'ToggleMaximize',
|
||||
'Minimize',
|
||||
'ShowWindow',
|
||||
'ShowAllWindow',
|
||||
'SwitchApplication',
|
||||
'ReverseSwitchApplication',
|
||||
'SwitchWorkspace',
|
||||
'ReverseSwitchWorkspace',
|
||||
'SplitWindowLeft',
|
||||
'SplitWindowRight',
|
||||
'MoveWindow',
|
||||
];
|
||||
|
||||
enum PanelType {
|
||||
local_manager,
|
||||
market,
|
||||
|
||||
@@ -18,5 +18,7 @@ const supportedLocaleNames = {
|
||||
SupportedLocale.en: 'English',
|
||||
};
|
||||
|
||||
Locale getSupportedLocale(SupportedLocale supportedLocale) => supportedLocales[supportedLocale.index];
|
||||
Locale transformSupportedLocale(SupportedLocale supportedLocale) => supportedLocales[supportedLocale.index];
|
||||
|
||||
SupportedLocale? getSupportedLocale(Locale? locale) =>
|
||||
supportedLocales.contains(locale) ? SupportedLocale.values[supportedLocales.indexOf(locale!)] : null;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
|
||||
export 'local_schemes_web.dart' if (dart.library.io) 'local_schemes_linux.dart';
|
||||
|
||||
abstract class LocalSchemeEntry {
|
||||
Scheme scheme;
|
||||
DateTime lastModifyTime;
|
||||
String path;
|
||||
|
||||
LocalSchemeEntry({
|
||||
required this.path,
|
||||
required this.scheme,
|
||||
required this.lastModifyTime,
|
||||
});
|
||||
|
||||
LocalSchemeEntry.systemDefault()
|
||||
: this.path = '',
|
||||
this.scheme = Scheme.systemDefault(),
|
||||
|
||||
/// max value of DateTime 
|
||||
this.lastModifyTime = DateTime.fromMillisecondsSinceEpoch(8640000000000000);
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
abstract class LocalSchemesInterface<T extends LocalSchemeEntry> {
|
||||
Future<List<T>> get schemeEntries;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
import 'package:path/path.dart' show join;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'local_schemes.dart';
|
||||
|
||||
export 'local_schemes.dart';
|
||||
|
||||
@ProviderModel()
|
||||
class LocalSchemes implements LocalSchemesInterface<LocalSchemeEntryLinux> {
|
||||
LocalSchemes() {
|
||||
schemeEntries.then((value) => schemes = [LocalSchemeEntryLinux.systemDefault(), ...value]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LocalSchemeEntryLinux>> get schemeEntries async {
|
||||
var _supportDirectory = await getApplicationSupportDirectory();
|
||||
var directory = Directory(join(_supportDirectory.path, 'schemes'));
|
||||
if (!directory.existsSync()) directory.createSync();
|
||||
return directory
|
||||
.list()
|
||||
.map<LocalSchemeEntryLinux?>((f) {
|
||||
LocalSchemeEntryLinux? entry;
|
||||
try {
|
||||
var content = File(f.path).readAsStringSync();
|
||||
entry = LocalSchemeEntryLinux(
|
||||
path: f.path, scheme: Scheme.parse(content), lastModifyTime: f.statSync().modified);
|
||||
} catch (e) {
|
||||
e.sout();
|
||||
}
|
||||
return entry;
|
||||
})
|
||||
.where((e) => e != null)
|
||||
.cast<LocalSchemeEntryLinux>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
@ProviderModelProp()
|
||||
List<LocalSchemeEntry>? schemes;
|
||||
}
|
||||
|
||||
class LocalSchemeEntryLinux implements LocalSchemeEntry {
|
||||
@override
|
||||
String path;
|
||||
|
||||
@override
|
||||
Scheme scheme;
|
||||
|
||||
@override
|
||||
DateTime lastModifyTime;
|
||||
|
||||
LocalSchemeEntryLinux({
|
||||
required this.path,
|
||||
required this.scheme,
|
||||
required this.lastModifyTime,
|
||||
});
|
||||
|
||||
LocalSchemeEntryLinux.systemDefault()
|
||||
: this.path = '',
|
||||
this.scheme = Scheme.systemDefault(),
|
||||
|
||||
/// max value of DateTime 
|
||||
this.lastModifyTime = DateTime.fromMillisecondsSinceEpoch(8640000000000000);
|
||||
|
||||
@override
|
||||
save() {
|
||||
// TODO: implement save
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export 'local_schemes_web.provider.dart' if (dart.library.io) 'local_schemes_linux.provider.dart';
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:html';
|
||||
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
|
||||
import 'local_schemes.dart';
|
||||
|
||||
export 'local_schemes.dart';
|
||||
|
||||
@ProviderModel()
|
||||
class LocalSchemes implements LocalSchemesInterface<LocalSchemeEntryWeb> {
|
||||
LocalSchemes() {
|
||||
schemeEntries.then((value) => schemes = [LocalSchemeEntryWeb.systemDefault(), ...value]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LocalSchemeEntryWeb>> get schemeEntries async {
|
||||
return window.localStorage.keys
|
||||
.map<LocalSchemeEntryWeb?>((key) {
|
||||
if (key.startsWith('schemes.')) {
|
||||
LocalSchemeEntryWeb? entry;
|
||||
try {
|
||||
var content = window.localStorage[key] ?? '';
|
||||
var schemeJson = json.decode(content);
|
||||
entry = LocalSchemeEntryWeb(
|
||||
path: key,
|
||||
scheme: Scheme.parse(schemeJson),
|
||||
lastModifyTime: DateTime.parse(schemeJson['modified_at']),
|
||||
);
|
||||
} catch (e) {
|
||||
e.sout();
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
})
|
||||
.where((e) => e != null)
|
||||
.cast<LocalSchemeEntryWeb>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
@ProviderModelProp()
|
||||
List<LocalSchemeEntry>? schemes;
|
||||
}
|
||||
|
||||
class LocalSchemeEntryWeb implements LocalSchemeEntry {
|
||||
@override
|
||||
String path;
|
||||
|
||||
@override
|
||||
Scheme scheme;
|
||||
|
||||
@override
|
||||
DateTime lastModifyTime;
|
||||
|
||||
LocalSchemeEntryWeb({
|
||||
required this.path,
|
||||
required this.scheme,
|
||||
required this.lastModifyTime,
|
||||
});
|
||||
|
||||
LocalSchemeEntryWeb.systemDefault()
|
||||
: this.path = '',
|
||||
this.scheme = Scheme.systemDefault(),
|
||||
|
||||
/// max value of DateTime 
|
||||
this.lastModifyTime = DateTime.fromMillisecondsSinceEpoch(8640000000000000);
|
||||
|
||||
@override
|
||||
save() {
|
||||
// TODO: implement save
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
export 'local_solutions_web.dart' if (dart.library.io) 'local_solutions_linux.dart';
|
||||
|
||||
import 'package:dde_gesture_manager/models/solution.dart';
|
||||
|
||||
abstract class LocalSolutionEntry {
|
||||
Solution solution;
|
||||
DateTime lastModifyTime;
|
||||
String path;
|
||||
|
||||
LocalSolutionEntry({
|
||||
required this.path,
|
||||
required this.solution,
|
||||
required this.lastModifyTime,
|
||||
});
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
abstract class LocalSolutionsInterface<T extends LocalSolutionEntry> {
|
||||
Future<List<T>> get solutionEntries;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/solution.dart';
|
||||
import 'package:path/path.dart' show join;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'local_solutions.dart';
|
||||
|
||||
export 'local_solutions.dart';
|
||||
|
||||
@ProviderModel()
|
||||
class LocalSolutions implements LocalSolutionsInterface<LocalSolutionEntryLinux> {
|
||||
LocalSolutions() {
|
||||
solutionEntries.then((value) => solutions = value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LocalSolutionEntryLinux>> get solutionEntries async {
|
||||
var _supportDirectory = await getApplicationSupportDirectory();
|
||||
var directory = Directory(join(_supportDirectory.path, 'solutions'));
|
||||
if (!directory.existsSync()) directory.createSync();
|
||||
directory.path.sout();
|
||||
return directory
|
||||
.list()
|
||||
.map<LocalSolutionEntryLinux?>((f) {
|
||||
LocalSolutionEntryLinux? entry;
|
||||
try {
|
||||
var content = File(f.path).readAsStringSync();
|
||||
entry = LocalSolutionEntryLinux(
|
||||
path: f.path, solution: Solution.parse(content), lastModifyTime: f.statSync().modified);
|
||||
} catch (e) {
|
||||
e.sout();
|
||||
}
|
||||
return entry;
|
||||
})
|
||||
.where((e) => e != null)
|
||||
.cast<LocalSolutionEntryLinux>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
@ProviderModelProp()
|
||||
List<LocalSolutionEntry>? solutions;
|
||||
}
|
||||
|
||||
class LocalSolutionEntryLinux implements LocalSolutionEntry {
|
||||
@override
|
||||
String path;
|
||||
|
||||
@override
|
||||
Solution solution;
|
||||
|
||||
@override
|
||||
DateTime lastModifyTime;
|
||||
|
||||
LocalSolutionEntryLinux({
|
||||
required this.path,
|
||||
required this.solution,
|
||||
required this.lastModifyTime,
|
||||
});
|
||||
|
||||
@override
|
||||
save() {
|
||||
// TODO: implement save
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export 'local_solutions_web.provider.dart' if (dart.library.io) 'local_solutions_linux.provider.dart';
|
||||
@@ -1,67 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/models/solution.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'dart:html';
|
||||
|
||||
import 'local_solutions.dart';
|
||||
export 'local_solutions.dart';
|
||||
|
||||
@ProviderModel()
|
||||
class LocalSolutions implements LocalSolutionsInterface<LocalSolutionEntryWeb> {
|
||||
LocalSolutions() {
|
||||
solutionEntries.then((value) => solutions = value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LocalSolutionEntryWeb>> get solutionEntries async {
|
||||
return window.localStorage.keys
|
||||
.map<LocalSolutionEntryWeb?>((key) {
|
||||
if (key.startsWith('solutions.')) {
|
||||
LocalSolutionEntryWeb? entry;
|
||||
try {
|
||||
var content = window.localStorage[key] ?? '';
|
||||
var solutionJson = json.decode(content);
|
||||
entry = LocalSolutionEntryWeb(
|
||||
path: key,
|
||||
solution: Solution.parse(solutionJson),
|
||||
lastModifyTime: DateTime.parse(solutionJson['modified_at']),
|
||||
);
|
||||
} catch (e) {
|
||||
e.sout();
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
})
|
||||
.where((e) => e != null)
|
||||
.cast<LocalSolutionEntryWeb>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
@ProviderModelProp()
|
||||
List<LocalSolutionEntry>? solutions;
|
||||
}
|
||||
|
||||
class LocalSolutionEntryWeb implements LocalSolutionEntry {
|
||||
@override
|
||||
String path;
|
||||
|
||||
@override
|
||||
Solution solution;
|
||||
|
||||
@override
|
||||
DateTime lastModifyTime;
|
||||
|
||||
LocalSolutionEntryWeb({
|
||||
required this.path,
|
||||
required this.solution,
|
||||
required this.lastModifyTime,
|
||||
});
|
||||
|
||||
@override
|
||||
save() {
|
||||
// TODO: implement save
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/extensions/compare_extension.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
typedef OnEditEnd(GestureProp prop);
|
||||
|
||||
@ProviderModel(copyable: true)
|
||||
class Scheme {
|
||||
@ProviderModelProp()
|
||||
String? id;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? name;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? description;
|
||||
|
||||
@ProviderModelProp()
|
||||
List<GestureProp>? gestures;
|
||||
|
||||
Scheme.parse(scheme) {
|
||||
if (scheme is String) scheme = json.decode(scheme);
|
||||
assert(scheme is Map);
|
||||
id = scheme['id'];
|
||||
name = scheme['name'];
|
||||
description = scheme['desc'];
|
||||
gestures = (scheme['gestures'] as List? ?? []).map<GestureProp>((ele) => GestureProp.parse(ele)).toList()..sort();
|
||||
}
|
||||
|
||||
Scheme.systemDefault() {
|
||||
this.id = Uuid.NAMESPACE_NIL;
|
||||
this.name = LocaleKeys.local_manager_default_scheme_label.tr();
|
||||
this.description = LocaleKeys.local_manager_default_scheme_description.tr();
|
||||
this.gestures = [];
|
||||
}
|
||||
|
||||
Scheme.create({this.name, this.description, this.gestures}) {
|
||||
this.id = Uuid().v1();
|
||||
}
|
||||
}
|
||||
|
||||
enum Gesture {
|
||||
tap,
|
||||
swipe,
|
||||
pinch,
|
||||
}
|
||||
|
||||
enum GestureDirection {
|
||||
up,
|
||||
down,
|
||||
left,
|
||||
right,
|
||||
pinch_in,
|
||||
pinch_out,
|
||||
none,
|
||||
}
|
||||
|
||||
enum GestureType {
|
||||
built_in,
|
||||
commandline,
|
||||
shortcut,
|
||||
}
|
||||
|
||||
@ProviderModel(copyable: true)
|
||||
class GestureProp implements Comparable {
|
||||
@ProviderModelProp()
|
||||
String? id;
|
||||
|
||||
@ProviderModelProp()
|
||||
Gesture? gesture;
|
||||
|
||||
@ProviderModelProp()
|
||||
GestureDirection? direction;
|
||||
|
||||
@ProviderModelProp()
|
||||
int? fingers;
|
||||
|
||||
@ProviderModelProp()
|
||||
GestureType? type;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? command;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? remark;
|
||||
|
||||
@ProviderModelProp()
|
||||
bool? get editMode => _editMode;
|
||||
|
||||
set editMode(bool? val) {
|
||||
_editMode = val ?? false;
|
||||
if (val == false) onEditEnd?.call(this);
|
||||
}
|
||||
|
||||
OnEditEnd? onEditEnd;
|
||||
|
||||
bool _editMode = false;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is GestureProp && other.id == this.id;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GestureProp{gesture: $gesture, direction: $direction, fingers: $fingers, type: $type, command: $command, remark: $remark}';
|
||||
}
|
||||
|
||||
GestureProp.empty() : this.id = Uuid.NAMESPACE_NIL;
|
||||
|
||||
GestureProp.parse(props) {
|
||||
if (props is String) props = json.decode(props);
|
||||
assert(props is Map);
|
||||
id = Uuid().v1();
|
||||
gesture = H.getGestureByName(props['gesture']);
|
||||
direction = H.getGestureDirectionByName(props['direction']);
|
||||
fingers = props['fingers'];
|
||||
type = H.getGestureTypeByName(props['type']);
|
||||
command = props['command'];
|
||||
remark = props['remark'];
|
||||
}
|
||||
|
||||
copyFrom(GestureProp prop) {
|
||||
this.id = prop.id;
|
||||
this.gesture = prop.gesture;
|
||||
this.direction = prop.direction;
|
||||
this.fingers = prop.fingers;
|
||||
this.type = prop.type;
|
||||
this.command = prop.command;
|
||||
this.remark = prop.remark;
|
||||
}
|
||||
|
||||
@override
|
||||
int compareTo(other) {
|
||||
assert(other is GestureProp);
|
||||
if (fingers.diff(other.fingers) && other.fingers != null) return fingers! - other.fingers as int;
|
||||
if (gesture.diff(other.gesture) && other.gesture != null) return gesture!.index - other.gesture!.index as int;
|
||||
if (direction.diff(other.direction) && other.direction != null)
|
||||
return direction!.index - other.direction!.index as int;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,15 @@
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
export 'package:flutter/material.dart' show Color;
|
||||
|
||||
@ProviderModel()
|
||||
class Settings {
|
||||
@ProviderModelProp()
|
||||
bool? isDarkMode;
|
||||
|
||||
@ProviderModelProp()
|
||||
Color? activeColor;
|
||||
|
||||
Color get currentActiveColor => activeColor ?? const Color(0xff0069cc);
|
||||
}
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
|
||||
@ProviderModel(copyable: true)
|
||||
class Solution {
|
||||
@ProviderModelProp()
|
||||
String? name;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? description;
|
||||
|
||||
@ProviderModelProp()
|
||||
List<GestureProp>? gestures;
|
||||
|
||||
Solution.parse(solution) {
|
||||
if (solution is String) solution = json.decode(solution);
|
||||
assert(solution is Map);
|
||||
name = solution['name'];
|
||||
description = solution['desc'];
|
||||
gestures = (solution['gestures'] as List? ?? []).map<GestureProp>((ele) => GestureProp.parse(ele)).toList();
|
||||
}
|
||||
}
|
||||
|
||||
enum Gesture {
|
||||
swipe,
|
||||
tap,
|
||||
pinch,
|
||||
}
|
||||
|
||||
enum GestureDirection {
|
||||
up,
|
||||
down,
|
||||
left,
|
||||
right,
|
||||
pinch_in,
|
||||
pinch_out,
|
||||
none,
|
||||
}
|
||||
|
||||
enum GestureType {
|
||||
built_in,
|
||||
commandline,
|
||||
shortcut,
|
||||
}
|
||||
|
||||
@ProviderModel(copyable: true)
|
||||
class GestureProp {
|
||||
@ProviderModelProp()
|
||||
Gesture? gesture;
|
||||
|
||||
@ProviderModelProp()
|
||||
GestureDirection? direction;
|
||||
|
||||
@ProviderModelProp()
|
||||
int? fingers;
|
||||
|
||||
@ProviderModelProp()
|
||||
GestureType? type;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? command;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? remark;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
other is GestureProp &&
|
||||
other.gesture == this.gesture &&
|
||||
other.direction == this.direction &&
|
||||
other.fingers == this.fingers;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GestureProp{gesture: $gesture, direction: $direction, fingers: $fingers, type: $type, command: $command, remark: $remark}';
|
||||
}
|
||||
|
||||
GestureProp.empty();
|
||||
|
||||
GestureProp.parse(props) {
|
||||
if (props is String) props = json.decode(props);
|
||||
assert(props is Map);
|
||||
gesture = H.getGestureByName(props['gesture']);
|
||||
direction = H.getGestureDirectionByName(props['direction']);
|
||||
fingers = props['fingers'];
|
||||
type = H.getGestureTypeByName(props['type']);
|
||||
command = props['command'];
|
||||
remark = props['remark'];
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,32 @@
|
||||
import 'package:adaptive_scrollbar/adaptive_scrollbar.dart';
|
||||
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/solution.dart';
|
||||
import 'package:dde_gesture_manager/models/solution.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/utils/helper.dart';
|
||||
import 'package:dde_gesture_manager/utils/keyboard_mapper.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_button.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_data_table.dart';
|
||||
import 'package:dde_gesture_manager/widgets/table_cell_shortcut_listener.dart';
|
||||
import 'package:dde_gesture_manager/widgets/table_cell_text_field.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
const double _headingRowHeight = 56;
|
||||
const double _scrollBarWidth = 14;
|
||||
|
||||
class GestureEditor extends StatelessWidget {
|
||||
const GestureEditor({Key? key}) : super(key: key);
|
||||
|
||||
List<DDataRow> _buildDataRow(List<GestureProp>? gestures, BuildContext context) => (gestures ?? [])
|
||||
.map((gesture) => DDataRow(
|
||||
onSelectChanged: (selected) {
|
||||
if (selected == true)
|
||||
context.read<GesturePropProvider>().setProps(
|
||||
gesture: gesture.gesture,
|
||||
direction: gesture.direction,
|
||||
fingers: gesture.fingers,
|
||||
type: gesture.type,
|
||||
command: gesture.command,
|
||||
remark: gesture.remark,
|
||||
);
|
||||
},
|
||||
selected: context.watch<GesturePropProvider>() == gesture,
|
||||
cells: [
|
||||
Center(
|
||||
child: Text('${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}').tr(),
|
||||
),
|
||||
Center(
|
||||
child: Text('${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}')
|
||||
.tr()),
|
||||
Center(
|
||||
child: Text('${gesture.fingers}'),
|
||||
),
|
||||
Center(child: Text('${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}').tr()),
|
||||
Text(gesture.command ?? ''),
|
||||
Text(gesture.remark ?? ''),
|
||||
]
|
||||
.map(
|
||||
(ele) => DDataCell(ele),
|
||||
)
|
||||
.toList(),
|
||||
))
|
||||
.toList();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var layoutProvider = context.watch<ContentLayoutProvider>();
|
||||
var solutionProvider = context.watch<SolutionProvider>();
|
||||
var schemeProvider = context.watch<SchemeProvider>();
|
||||
final horizontalCtrl = ScrollController();
|
||||
final verticalCtrl = ScrollController();
|
||||
|
||||
return Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
@@ -99,53 +75,81 @@ class GestureEditor extends StatelessWidget {
|
||||
),
|
||||
Container(height: 10),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
border: Border.all(
|
||||
width: .2,
|
||||
color: context.t.dividerColor,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<GesturePropProvider>().setProps(editMode: false);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
border: Border.all(
|
||||
width: .2,
|
||||
color: context.t.dividerColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: double.infinity,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Scrollbar(
|
||||
isAlwaysShown: true,
|
||||
child: SingleChildScrollView(
|
||||
primary: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
||||
child: DDataTable(
|
||||
showCheckboxColumn: true,
|
||||
headerBackgroundColor: context.t.dialogBackgroundColor,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
border: Border.all(
|
||||
width: .2,
|
||||
color: context.t.dividerColor,
|
||||
width: double.infinity,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return AdaptiveScrollbar(
|
||||
controller: verticalCtrl,
|
||||
underColor: Colors.transparent,
|
||||
sliderDecoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(_scrollBarWidth / 2),
|
||||
color: Colors.grey.withOpacity(.4),
|
||||
),
|
||||
sliderActiveDecoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(_scrollBarWidth / 2),
|
||||
color: Colors.grey.withOpacity(.6),
|
||||
),
|
||||
position: ScrollbarPosition.right,
|
||||
underSpacing: EdgeInsets.only(top: _headingRowHeight),
|
||||
width: _scrollBarWidth,
|
||||
child: AdaptiveScrollbar(
|
||||
width: _scrollBarWidth,
|
||||
underColor: Colors.transparent,
|
||||
sliderDecoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(_scrollBarWidth / 2),
|
||||
color: Colors.grey.withOpacity(.4),
|
||||
),
|
||||
sliderActiveDecoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(_scrollBarWidth / 2),
|
||||
color: Colors.grey.withOpacity(.6),
|
||||
),
|
||||
controller: horizontalCtrl,
|
||||
position: ScrollbarPosition.bottom,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: horizontalCtrl,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
||||
child: DDataTable(
|
||||
showBottomBorder: true,
|
||||
headingRowHeight: _headingRowHeight,
|
||||
showCheckboxColumn: true,
|
||||
headerBackgroundColor: context.t.dialogBackgroundColor,
|
||||
verticalScrollController: verticalCtrl,
|
||||
dataRowColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor;
|
||||
if (states.contains(MaterialState.selected))
|
||||
return context.read<SettingsProvider>().currentActiveColor;
|
||||
return null;
|
||||
}),
|
||||
columns: [
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())),
|
||||
],
|
||||
rows: _buildDataRows(schemeProvider.gestures, context),
|
||||
),
|
||||
),
|
||||
dataRowColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor;
|
||||
if (states.contains(MaterialState.selected)) return Colors.blueAccent;
|
||||
return null;
|
||||
}),
|
||||
columns: [
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())),
|
||||
DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())),
|
||||
],
|
||||
rows: _buildDataRow(solutionProvider.gestures, context),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(height: 10),
|
||||
@@ -167,3 +171,261 @@ class GestureEditor extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<DDataRow> _buildDataRows(List<GestureProp>? gestures, BuildContext context) => (gestures ?? []).map((gesture) {
|
||||
var gesturePropProvider = context.watch<GesturePropProvider>();
|
||||
bool editing = gesturePropProvider == gesture && gesturePropProvider.editMode == true;
|
||||
bool selected = gesturePropProvider == gesture && !editing;
|
||||
return DDataRow(
|
||||
onSelectChanged: (selected) {
|
||||
var provider = context.read<GesturePropProvider>();
|
||||
if (selected == true) {
|
||||
provider.setProps(
|
||||
editMode: false,
|
||||
);
|
||||
Future.microtask(() => provider.setProps(
|
||||
id: gesture.id,
|
||||
));
|
||||
} else if (selected == false) {
|
||||
provider.onEditEnd = (prop) {
|
||||
var schemeProvider = context.read<SchemeProvider>();
|
||||
var newGestures = List<GestureProp>.of(schemeProvider.gestures!);
|
||||
var index = newGestures.indexWhere((element) => element == prop);
|
||||
newGestures[index].copyFrom(prop);
|
||||
context.read<SchemeProvider>().setProps(
|
||||
gestures: newGestures..sort(),
|
||||
);
|
||||
};
|
||||
provider.copyFrom(
|
||||
gesture..editMode = true,
|
||||
);
|
||||
}
|
||||
},
|
||||
selected: selected,
|
||||
cells: editing ? _buildRowCellsEditing(context, gesture) : _buildRowCellsNormal(context, selected, gesture),
|
||||
);
|
||||
}).toList();
|
||||
|
||||
List<DDataCell> _buildRowCellsEditing(BuildContext context, GestureProp gesture) => [
|
||||
DButton.dropdown(
|
||||
enabled: true,
|
||||
child: DropdownButton<int>(
|
||||
icon: Icon(Icons.keyboard_arrow_down_rounded),
|
||||
items: [3, 4, 5]
|
||||
.map(
|
||||
(e) => DropdownMenuItem<int>(
|
||||
child: Text('$e'),
|
||||
value: e,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value: context.watch<GesturePropProvider>().fingers,
|
||||
onChanged: (value) => context.read<GesturePropProvider>().setProps(
|
||||
fingers: value,
|
||||
editMode: true,
|
||||
),
|
||||
isExpanded: true,
|
||||
),
|
||||
),
|
||||
DButton.dropdown(
|
||||
enabled: true,
|
||||
width: 60.0,
|
||||
child: DropdownButton<Gesture>(
|
||||
icon: Icon(Icons.keyboard_arrow_down_rounded),
|
||||
items: Gesture.values
|
||||
.map(
|
||||
(e) => DropdownMenuItem<Gesture>(
|
||||
child: Text(
|
||||
'${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(e)}',
|
||||
textScaleFactor: .8,
|
||||
).tr(),
|
||||
value: e,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value: context.watch<GesturePropProvider>().gesture,
|
||||
onChanged: (value) => context.read<GesturePropProvider>().setProps(
|
||||
gesture: value,
|
||||
editMode: true,
|
||||
),
|
||||
isExpanded: true,
|
||||
),
|
||||
),
|
||||
DButton.dropdown(
|
||||
enabled: true,
|
||||
width: 100.0,
|
||||
child: DropdownButton<GestureDirection>(
|
||||
icon: Icon(Icons.keyboard_arrow_down_rounded),
|
||||
items: GestureDirection.values
|
||||
.map(
|
||||
(e) => DropdownMenuItem<GestureDirection>(
|
||||
child: Text(
|
||||
'${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(e)}',
|
||||
textScaleFactor: .8,
|
||||
).tr(),
|
||||
value: e,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value: context.watch<GesturePropProvider>().direction,
|
||||
onChanged: (value) => context.read<GesturePropProvider>().setProps(
|
||||
direction: value,
|
||||
editMode: true,
|
||||
),
|
||||
isExpanded: true,
|
||||
),
|
||||
),
|
||||
DButton.dropdown(
|
||||
enabled: true,
|
||||
width: 100.0,
|
||||
child: DropdownButton<GestureType>(
|
||||
icon: Icon(Icons.keyboard_arrow_down_rounded),
|
||||
items: GestureType.values
|
||||
.map(
|
||||
(e) => DropdownMenuItem<GestureType>(
|
||||
child: Text(
|
||||
'${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(e)}',
|
||||
textScaleFactor: .8,
|
||||
).tr(),
|
||||
value: e,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value: context.watch<GesturePropProvider>().type,
|
||||
onChanged: (value) => context.read<GesturePropProvider>().setProps(
|
||||
type: value,
|
||||
command: '',
|
||||
editMode: true,
|
||||
),
|
||||
isExpanded: true,
|
||||
),
|
||||
),
|
||||
_buildCommandCellsEditing(context),
|
||||
TableCellTextField(
|
||||
initText: gesture.remark,
|
||||
hint: 'pls input cmd',
|
||||
onComplete: (value) => context.read<GesturePropProvider>().setProps(
|
||||
remark: value,
|
||||
editMode: true,
|
||||
),
|
||||
),
|
||||
].map((e) => DDataCell(e)).toList();
|
||||
|
||||
Widget _buildCommandCellsEditing(BuildContext context) {
|
||||
var gesture = context.read<GesturePropProvider>();
|
||||
switch (gesture.type) {
|
||||
case GestureType.commandline:
|
||||
return TableCellTextField(
|
||||
initText: gesture.command,
|
||||
hint: 'pls input cmd',
|
||||
onComplete: (value) => context.read<GesturePropProvider>().setProps(
|
||||
command: value,
|
||||
editMode: true,
|
||||
),
|
||||
);
|
||||
case GestureType.built_in:
|
||||
return DButton.dropdown(
|
||||
enabled: true,
|
||||
width: 250.0,
|
||||
child: DropdownButton<String>(
|
||||
icon: Icon(Icons.keyboard_arrow_down_rounded),
|
||||
items: builtInCommands
|
||||
.map(
|
||||
(e) => DropdownMenuItem<String>(
|
||||
child: Text(
|
||||
('${LocaleKeys.built_in_commands}.$e').tr(),
|
||||
textScaleFactor: .8,
|
||||
),
|
||||
value: ('${LocaleKeys.built_in_commands}.$e').tr(),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value:
|
||||
('${LocaleKeys.built_in_commands}.${(builtInCommands.contains(gesture.command) ? gesture.command : builtInCommands.first)!}')
|
||||
.tr(),
|
||||
onChanged: (value) => context.read<GesturePropProvider>().setProps(
|
||||
command: value,
|
||||
editMode: true,
|
||||
),
|
||||
isExpanded: true,
|
||||
),
|
||||
);
|
||||
case GestureType.shortcut:
|
||||
return TableCellShortcutListener(
|
||||
width: 250.0,
|
||||
initShortcut: gesture.command ?? '',
|
||||
onComplete: (value) => context.read<GesturePropProvider>().setProps(
|
||||
command: value,
|
||||
editMode: true,
|
||||
),
|
||||
);
|
||||
default:
|
||||
throw Exception('Unknown gesture command type.');
|
||||
}
|
||||
}
|
||||
|
||||
List<DDataCell> _buildRowCellsNormal(BuildContext context, bool selected, GestureProp gesture) => [
|
||||
Center(
|
||||
child: Text(
|
||||
'${gesture.fingers}',
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Text(
|
||||
'${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}',
|
||||
).tr(),
|
||||
),
|
||||
Center(
|
||||
child: Text(
|
||||
'${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}',
|
||||
).tr()),
|
||||
Center(
|
||||
child: Text(
|
||||
'${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}',
|
||||
).tr()),
|
||||
gesture.type == GestureType.shortcut
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: (gesture.command ?? '').split('+').map(
|
||||
(e) {
|
||||
var keyNames = getPhysicalKeyNamesByRealName(e);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius / 2),
|
||||
color: context.t.dialogBackgroundColor,
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: Color(0xff565656),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||
child: Text(
|
||||
keyNames != null ? keyNames.displayName : LocaleKeys.str_null.tr(),
|
||||
style: TextStyle(
|
||||
color: context.watch<SettingsProvider>().currentActiveColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
)
|
||||
: Text(
|
||||
gesture.command ?? '',
|
||||
),
|
||||
Text(
|
||||
gesture.remark ?? '',
|
||||
),
|
||||
]
|
||||
.map(
|
||||
(ele) => DDataCell(DefaultTextStyle(
|
||||
style: context.t.textTheme.bodyText2!.copyWith(
|
||||
color: selected ? Colors.white : null,
|
||||
),
|
||||
child: ele)),
|
||||
)
|
||||
.toList();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/local_solutions_provider.dart';
|
||||
import 'package:dde_gesture_manager/models/solution.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/local_schemes_provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.provider.dart';
|
||||
import 'package:dde_gesture_manager/pages/content.dart';
|
||||
import 'package:dde_gesture_manager/pages/footer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -18,7 +18,7 @@ class _HomePageState extends State<HomePage> {
|
||||
return Scaffold(
|
||||
body: MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (context) => SolutionProvider.parse('''
|
||||
ChangeNotifierProvider(create: (context) => SchemeProvider.parse('''
|
||||
{
|
||||
"name": "test",
|
||||
"desc": "some desc",
|
||||
@@ -66,7 +66,7 @@ class _HomePageState extends State<HomePage> {
|
||||
}
|
||||
''')),
|
||||
ChangeNotifierProvider(create: (context) => GesturePropProvider.empty()),
|
||||
ChangeNotifierProvider(create: (context) => LocalSolutionsProvider(),lazy: false),
|
||||
ChangeNotifierProvider(create: (context) => LocalSchemesProvider(),lazy: false),
|
||||
],
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
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_solutions_provider.dart';
|
||||
import 'package:dde_gesture_manager/models/solution.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/local_schemes_provider.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';
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@@ -21,25 +22,28 @@ class LocalManager extends StatefulWidget {
|
||||
class _LocalManagerState extends State<LocalManager> {
|
||||
late ScrollController _scrollController;
|
||||
int? _hoveringIndex;
|
||||
int? _selectedIndex;
|
||||
late int _selectedIndex;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
/// todo: load from sp
|
||||
_selectedIndex = 0;
|
||||
_scrollController = ScrollController();
|
||||
}
|
||||
|
||||
Color _getItemBackgroundColor(int index) {
|
||||
Color _color = index % 2 == 0 ? context.t.scaffoldBackgroundColor : context.t.backgroundColor;
|
||||
if (index == _hoveringIndex) _color = context.t.scaffoldBackgroundColor;
|
||||
if (index == _selectedIndex) _color = Colors.blueAccent;
|
||||
if (index == _selectedIndex) _color = context.read<SettingsProvider>().currentActiveColor;
|
||||
return _color;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var isOpen = context.watch<ContentLayoutProvider>().localManagerOpened == true;
|
||||
var localSolutions = context.watch<LocalSolutionsProvider>().solutions ?? [];
|
||||
var localSchemes = context.watch<LocalSchemesProvider>().schemes ?? [];
|
||||
return AnimatedContainer(
|
||||
duration: mediumDuration,
|
||||
curve: Curves.easeInOut,
|
||||
@@ -83,54 +87,82 @@ class _LocalManagerState extends State<LocalManager> {
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemBuilder: (context, index) => GestureDetector(
|
||||
onDoubleTap: () {
|
||||
context.read<SolutionProvider>().copyFrom(localSolutions[index].solution);
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
},
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
},
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (_) {
|
||||
setState(() {
|
||||
_hoveringIndex = index;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: _getItemBackgroundColor(index),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 12.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(localSolutions[index].solution.name ?? ''),
|
||||
Text('456'),
|
||||
],
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: .3,
|
||||
color: context.t.dividerColor,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 1, vertical: 2),
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemBuilder: (context, index) => GestureDetector(
|
||||
onTap: () {
|
||||
context.read<SchemeProvider>().copyFrom(localSchemes[index].scheme);
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
},
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (_) {
|
||||
setState(() {
|
||||
_hoveringIndex = index;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: _getItemBackgroundColor(index),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 6, right: 12.0),
|
||||
child: DefaultTextStyle(
|
||||
style: context.t.textTheme.bodyText2!.copyWith(
|
||||
color: _selectedIndex == index ? Colors.white : null,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(localSchemes[index].scheme.name ?? ''),
|
||||
Text('456'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
itemCount: localSchemes.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
itemCount: localSolutions.length,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 150,
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
Container(height: 5),
|
||||
Container(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
DButton.add(enabled: true),
|
||||
DButton.delete(enabled: _selectedIndex > 0),
|
||||
DButton.duplicate(enabled: _selectedIndex > 0),
|
||||
DButton.apply(enabled: _selectedIndex > 0),
|
||||
]
|
||||
.map((e) => Padding(
|
||||
padding: const EdgeInsets.only(right: 4),
|
||||
child: e,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -18,9 +18,20 @@ var darkTheme = ThemeData.dark().copyWith(
|
||||
),
|
||||
),
|
||||
popupMenuTheme: ThemeData.dark().popupMenuTheme.copyWith(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
),
|
||||
),
|
||||
dialogBackgroundColor: Color(0xff202020),
|
||||
tooltipTheme: ThemeData.dark().tooltipTheme.copyWith(
|
||||
textStyle: TextStyle(
|
||||
color: Colors.grey,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 3, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Color(0xff282828).withOpacity(.9),
|
||||
border: Border.all(color: Colors.black38),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -23,4 +23,15 @@ var lightTheme = ThemeData.light().copyWith(
|
||||
),
|
||||
),
|
||||
dialogBackgroundColor: Color(0xfffefefe),
|
||||
tooltipTheme: ThemeData.dark().tooltipTheme.copyWith(
|
||||
textStyle: TextStyle(
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 3, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Color(0xfff8f8f8).withOpacity(.9),
|
||||
border: Border.all(color: Colors.grey.shade400),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/solution.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';
|
||||
@@ -96,7 +96,15 @@ class H {
|
||||
'shortcut': GestureType.shortcut,
|
||||
'commandline': GestureType.commandline,
|
||||
}[typeName] ??
|
||||
GestureType.built_in;
|
||||
GestureType.built_in;
|
||||
|
||||
static Color? parseQtActiveColor(String? inp) {
|
||||
if (inp == null) return null;
|
||||
var list = inp.split(',');
|
||||
if (list.length != 4) return null;
|
||||
var rgba = list.map<int>((e) => int.parse(e) ~/ 257).toList();
|
||||
return Color.fromARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
|
||||
}
|
||||
}
|
||||
|
||||
class PreferredPanelsStatus {
|
||||
|
||||
@@ -18,8 +18,11 @@ Future<void> initEvents(BuildContext context) async {
|
||||
} else {
|
||||
var xsettings = GSettings('com.deepin.xsettings');
|
||||
String? themeName;
|
||||
Color? activeColor;
|
||||
try {
|
||||
themeName = (await xsettings.get('theme-name')).toString();
|
||||
var _activeColor = (await xsettings.get('qt-active-color'));
|
||||
activeColor = H.parseQtActiveColor(_activeColor.toNative());
|
||||
} catch (e) {
|
||||
print(e);
|
||||
context.read<SettingsProvider>().setProps(isDarkMode: false);
|
||||
@@ -27,10 +30,14 @@ Future<void> initEvents(BuildContext context) async {
|
||||
|
||||
if (themeName != null) {
|
||||
context.read<SettingsProvider>().setProps(isDarkMode: themeName.contains('dark'));
|
||||
context.read<SettingsProvider>().setProps(activeColor: activeColor);
|
||||
xsettings.keysChanged.listen((event) {
|
||||
xsettings.get('theme-name').then((value) {
|
||||
context.read<SettingsProvider>().setProps(isDarkMode: value.toString().contains('dark'));
|
||||
});
|
||||
xsettings.get('qt-active-color').then((value) {
|
||||
context.read<SettingsProvider>().setProps(activeColor: H.parseQtActiveColor(value.toNative()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
const KeysOrder = [
|
||||
'Ctrl',
|
||||
'Super',
|
||||
'Alt',
|
||||
'Shift',
|
||||
'Return',
|
||||
'Escape',
|
||||
'BackSpace',
|
||||
'Tab',
|
||||
'space',
|
||||
'→',
|
||||
'←',
|
||||
'↓',
|
||||
'↑',
|
||||
'Print',
|
||||
'ScrollLock',
|
||||
'Pause',
|
||||
'Insert',
|
||||
'Home',
|
||||
'Page_Up',
|
||||
'Delete',
|
||||
'End',
|
||||
'Page_Down',
|
||||
'F1',
|
||||
'F2',
|
||||
'F3',
|
||||
'F4',
|
||||
'F5',
|
||||
'F6',
|
||||
'F7',
|
||||
'F8',
|
||||
'F9',
|
||||
'F10',
|
||||
'F11',
|
||||
'F12',
|
||||
'-',
|
||||
'=',
|
||||
'(',
|
||||
')',
|
||||
r'\',
|
||||
';',
|
||||
"'",
|
||||
'`',
|
||||
',',
|
||||
'.',
|
||||
'/',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'0',
|
||||
];
|
||||
|
||||
class KeyNames implements Comparable {
|
||||
final String displayName;
|
||||
final String realName;
|
||||
|
||||
const KeyNames({required this.displayName, required this.realName});
|
||||
|
||||
@override
|
||||
int compareTo(other) => KeysOrder.indexOf(this.displayName) - KeysOrder.indexOf(other.displayName);
|
||||
|
||||
@override
|
||||
String toString() => realName;
|
||||
}
|
||||
|
||||
KeyNames? getPhysicalKeyNames(int keyId) => _knownPhysicalKeyNames[keyId];
|
||||
|
||||
KeyNames? getPhysicalKeyNamesByRealName(String name) =>
|
||||
_knownPhysicalKeyNames.values.firstWhereOrNull((element) => element.realName == name);
|
||||
|
||||
/// https://www.w3.org/TR/uievents-code/
|
||||
const Map<int, KeyNames> _knownPhysicalKeyNames = <int, KeyNames>{
|
||||
/// https://www.w3.org/TR/uievents-code/#key-legacy
|
||||
/*0x00000010: hyper,
|
||||
0x00000011: superKey,
|
||||
0x00000016: turbo,
|
||||
0x0007009b: abort,
|
||||
0x00000015: resume,
|
||||
0x00000014: suspend,
|
||||
0x00070079: again,
|
||||
0x0007007c: copy,
|
||||
0x0007007b: cut,
|
||||
0x0007007e: find,
|
||||
0x00070074: open,
|
||||
0x0007007d: paste,
|
||||
0x000700a3: props,
|
||||
0x00070077: select,
|
||||
0x0007007a: undo,*/
|
||||
|
||||
/// Often handled in hardware so that events aren't generated for this key.
|
||||
/*0x00000012: fn,
|
||||
0x00000013: fnLock,*/
|
||||
|
||||
/// W.T.F
|
||||
/*0x00000017: privacyScreenToggle,
|
||||
0x00010082: sleep,
|
||||
0x00010083: wakeUp,
|
||||
0x000100b5: displayToggleIntExt,
|
||||
0x0005ff01: gameButton1,
|
||||
0x0005ff02: gameButton2,
|
||||
0x0005ff03: gameButton3,
|
||||
0x0005ff04: gameButton4,
|
||||
0x0005ff05: gameButton5,
|
||||
0x0005ff06: gameButton6,
|
||||
0x0005ff07: gameButton7,
|
||||
0x0005ff08: gameButton8,
|
||||
0x0005ff09: gameButton9,
|
||||
0x0005ff0a: gameButton10,
|
||||
0x0005ff0b: gameButton11,
|
||||
0x0005ff0c: gameButton12,
|
||||
0x0005ff0d: gameButton13,
|
||||
0x0005ff0e: gameButton14,
|
||||
0x0005ff0f: gameButton15,
|
||||
0x0005ff10: gameButton16,
|
||||
0x0005ff11: gameButtonA,
|
||||
0x0005ff12: gameButtonB,
|
||||
0x0005ff13: gameButtonC,
|
||||
0x0005ff14: gameButtonLeft1,
|
||||
0x0005ff15: gameButtonLeft2,
|
||||
0x0005ff16: gameButtonMode,
|
||||
0x0005ff17: gameButtonRight1,
|
||||
0x0005ff18: gameButtonRight2,
|
||||
0x0005ff19: gameButtonSelect,
|
||||
0x0005ff1a: gameButtonStart,
|
||||
0x0005ff1b: gameButtonThumbLeft,
|
||||
0x0005ff1c: gameButtonThumbRight,
|
||||
0x0005ff1d: gameButtonX,
|
||||
0x0005ff1e: gameButtonY,
|
||||
0x0005ff1f: gameButtonZ,
|
||||
0x00070000: usbReserved,
|
||||
0x00070001: usbErrorRollOver,
|
||||
0x00070002: usbPostFail,
|
||||
0x00070003: usbErrorUndefined,*/
|
||||
|
||||
0x00070004: const KeyNames(displayName: 'A', realName: 'a'),
|
||||
0x00070005: const KeyNames(displayName: 'B', realName: 'b'),
|
||||
0x00070006: const KeyNames(displayName: 'C', realName: 'c'),
|
||||
0x00070007: const KeyNames(displayName: 'D', realName: 'd'),
|
||||
0x00070008: const KeyNames(displayName: 'E', realName: 'e'),
|
||||
0x00070009: const KeyNames(displayName: 'F', realName: 'f'),
|
||||
0x0007000a: const KeyNames(displayName: 'G', realName: 'g'),
|
||||
0x0007000b: const KeyNames(displayName: 'H', realName: 'h'),
|
||||
0x0007000c: const KeyNames(displayName: 'I', realName: 'i'),
|
||||
0x0007000d: const KeyNames(displayName: 'J', realName: 'j'),
|
||||
0x0007000e: const KeyNames(displayName: 'K', realName: 'k'),
|
||||
0x0007000f: const KeyNames(displayName: 'L', realName: 'l'),
|
||||
0x00070010: const KeyNames(displayName: 'M', realName: 'm'),
|
||||
0x00070011: const KeyNames(displayName: 'N', realName: 'n'),
|
||||
0x00070012: const KeyNames(displayName: 'O', realName: 'o'),
|
||||
0x00070013: const KeyNames(displayName: 'P', realName: 'p'),
|
||||
0x00070014: const KeyNames(displayName: 'Q', realName: 'q'),
|
||||
0x00070015: const KeyNames(displayName: 'R', realName: 'r'),
|
||||
0x00070016: const KeyNames(displayName: 'S', realName: 's'),
|
||||
0x00070017: const KeyNames(displayName: 'T', realName: 't'),
|
||||
0x00070018: const KeyNames(displayName: 'U', realName: 'u'),
|
||||
0x00070019: const KeyNames(displayName: 'V', realName: 'v'),
|
||||
0x0007001a: const KeyNames(displayName: 'W', realName: 'w'),
|
||||
0x0007001b: const KeyNames(displayName: 'X', realName: 'x'),
|
||||
0x0007001c: const KeyNames(displayName: 'Y', realName: 'y'),
|
||||
0x0007001d: const KeyNames(displayName: 'Z', realName: 'z'),
|
||||
0x0007001e: const KeyNames(displayName: '1', realName: '1'),
|
||||
0x0007001f: const KeyNames(displayName: '2', realName: '2'),
|
||||
0x00070020: const KeyNames(displayName: '3', realName: '3'),
|
||||
0x00070021: const KeyNames(displayName: '4', realName: '4'),
|
||||
0x00070022: const KeyNames(displayName: '5', realName: '5'),
|
||||
0x00070023: const KeyNames(displayName: '6', realName: '6'),
|
||||
0x00070024: const KeyNames(displayName: '7', realName: '7'),
|
||||
0x00070025: const KeyNames(displayName: '8', realName: '8'),
|
||||
0x00070026: const KeyNames(displayName: '9', realName: '9'),
|
||||
0x00070027: const KeyNames(displayName: '0', realName: '0'),
|
||||
0x00070028: const KeyNames(displayName: 'Return', realName: 'Return'),
|
||||
0x00070029: const KeyNames(displayName: 'Escape', realName: 'Escape'),
|
||||
0x0007002a: const KeyNames(displayName: 'BackSpace', realName: 'BackSpace'),
|
||||
0x0007002b: const KeyNames(displayName: 'Tab', realName: 'Tab'),
|
||||
0x0007002c: const KeyNames(displayName: 'space', realName: 'space'),
|
||||
0x0007002d: const KeyNames(displayName: '-', realName: 'minus'),
|
||||
0x0007002e: const KeyNames(displayName: '=', realName: 'equal'),
|
||||
0x0007002f: const KeyNames(displayName: '(', realName: 'parenleft'),
|
||||
0x00070030: const KeyNames(displayName: ')', realName: 'parenright'),
|
||||
0x00070031: const KeyNames(displayName: r'\', realName: 'backslash'),
|
||||
0x00070033: const KeyNames(displayName: ';', realName: 'semicolon'),
|
||||
0x00070034: const KeyNames(displayName: "'", realName: 'apostrophe'),
|
||||
0x00070035: const KeyNames(displayName: '`', realName: 'grave'),
|
||||
0x00070036: const KeyNames(displayName: ',', realName: 'comma'),
|
||||
0x00070037: const KeyNames(displayName: '.', realName: 'period'),
|
||||
0x00070038: const KeyNames(displayName: '/', realName: 'slash'),
|
||||
0x00070039: const KeyNames(displayName: 'CapsLock', realName: 'Caps_Lock'),
|
||||
0x0007003a: const KeyNames(displayName: 'F1', realName: 'F1'),
|
||||
0x0007003b: const KeyNames(displayName: 'F2', realName: 'F2'),
|
||||
0x0007003c: const KeyNames(displayName: 'F3', realName: 'F3'),
|
||||
0x0007003d: const KeyNames(displayName: 'F4', realName: 'F4'),
|
||||
0x0007003e: const KeyNames(displayName: 'F5', realName: 'F5'),
|
||||
0x0007003f: const KeyNames(displayName: 'F6', realName: 'F6'),
|
||||
0x00070040: const KeyNames(displayName: 'F7', realName: 'F7'),
|
||||
0x00070041: const KeyNames(displayName: 'F8', realName: 'F8'),
|
||||
0x00070042: const KeyNames(displayName: 'F9', realName: 'F9'),
|
||||
0x00070043: const KeyNames(displayName: 'F10', realName: 'F10'),
|
||||
0x00070044: const KeyNames(displayName: 'F11', realName: 'F11'),
|
||||
0x00070045: const KeyNames(displayName: 'F12', realName: 'F12'),
|
||||
0x00070046: const KeyNames(displayName: 'Print', realName: 'Print'),
|
||||
0x00070047: const KeyNames(displayName: 'ScrollLock', realName: 'Scroll_Lock'),
|
||||
0x00070048: const KeyNames(displayName: 'Pause', realName: 'Pause'),
|
||||
0x00070049: const KeyNames(displayName: 'Insert', realName: 'Insert'),
|
||||
0x0007004a: const KeyNames(displayName: 'Home', realName: 'Home'),
|
||||
0x0007004b: const KeyNames(displayName: 'Page_Up', realName: 'Page_Up'),
|
||||
0x0007004c: const KeyNames(displayName: 'Delete', realName: 'Delete'),
|
||||
0x0007004d: const KeyNames(displayName: 'End', realName: 'End'),
|
||||
0x0007004e: const KeyNames(displayName: 'Page_Down', realName: 'Page_Down'),
|
||||
0x0007004f: const KeyNames(displayName: '→', realName: 'Right'),
|
||||
0x00070050: const KeyNames(displayName: '←', realName: 'Left'),
|
||||
0x00070051: const KeyNames(displayName: '↓', realName: 'Down'),
|
||||
0x00070052: const KeyNames(displayName: '↑', realName: 'Up'),
|
||||
0x00070053: const KeyNames(displayName: 'NumLock', realName: 'Num_Lock'),
|
||||
0x00070054: const KeyNames(displayName: 'KP_Divide', realName: 'KP_Divide'),
|
||||
0x00070055: const KeyNames(displayName: 'KP_Multiply', realName: 'KP_Multiply'),
|
||||
0x00070056: const KeyNames(displayName: 'KP_Subtract', realName: 'KP_Subtract'),
|
||||
0x00070057: const KeyNames(displayName: 'KP_Add', realName: 'KP_Add'),
|
||||
0x00070058: const KeyNames(displayName: 'KP_Enter', realName: 'KP_Enter'),
|
||||
0x00070059: const KeyNames(displayName: 'KP_1', realName: 'KP_1'),
|
||||
0x0007005a: const KeyNames(displayName: 'KP_2', realName: 'KP_2'),
|
||||
0x0007005b: const KeyNames(displayName: 'KP_3', realName: 'KP_3'),
|
||||
0x0007005c: const KeyNames(displayName: 'KP_4', realName: 'KP_4'),
|
||||
0x0007005d: const KeyNames(displayName: 'KP_5', realName: 'KP_5'),
|
||||
0x0007005e: const KeyNames(displayName: 'KP_6', realName: 'KP_6'),
|
||||
0x0007005f: const KeyNames(displayName: 'KP_7', realName: 'KP_7'),
|
||||
0x00070060: const KeyNames(displayName: 'KP_8', realName: 'KP_8'),
|
||||
0x00070061: const KeyNames(displayName: 'KP_9', realName: 'KP_9'),
|
||||
0x00070062: const KeyNames(displayName: 'KP_0', realName: 'KP_0'),
|
||||
0x00070063: const KeyNames(displayName: '.', realName: 'KP_Decimal'),
|
||||
|
||||
/// IntlBackslash ???
|
||||
0x00070064: const KeyNames(displayName: r'\', realName: 'backslash'),
|
||||
0x00070065: const KeyNames(displayName: 'Menu', realName: 'Menu'),
|
||||
|
||||
/// Mac only
|
||||
// 0x00070066: power,
|
||||
0x00070067: const KeyNames(displayName: 'KP_Equal', realName: 'KP_Equal'),
|
||||
0x00070068: const KeyNames(displayName: 'F13', realName: 'F13'),
|
||||
0x00070069: const KeyNames(displayName: 'F14', realName: 'F14'),
|
||||
0x0007006a: const KeyNames(displayName: 'F15', realName: 'F15'),
|
||||
0x0007006b: const KeyNames(displayName: 'F16', realName: 'F16'),
|
||||
0x0007006c: const KeyNames(displayName: 'F17', realName: 'F17'),
|
||||
0x0007006d: const KeyNames(displayName: 'F18', realName: 'F18'),
|
||||
0x0007006e: const KeyNames(displayName: 'F19', realName: 'F19'),
|
||||
0x0007006f: const KeyNames(displayName: 'F20', realName: 'F20'),
|
||||
0x00070070: const KeyNames(displayName: 'F21', realName: 'F21'),
|
||||
0x00070071: const KeyNames(displayName: 'F22', realName: 'F22'),
|
||||
0x00070072: const KeyNames(displayName: 'F23', realName: 'F23'),
|
||||
0x00070073: const KeyNames(displayName: 'F24', realName: 'F24'),
|
||||
|
||||
/// Not present on standard PC keyboards.
|
||||
// 0x00070075: help,
|
||||
0x0007007f: const KeyNames(displayName: 'XF86AudioMute', realName: 'XF86AudioMute'),
|
||||
0x00070080: const KeyNames(displayName: 'XF86AudioRaiseVolume', realName: 'XF86AudioRaiseVolume'),
|
||||
0x00070081: const KeyNames(displayName: 'XF86AudioLowerVolume', realName: 'XF86AudioLowerVolume'),
|
||||
0x00070085: const KeyNames(displayName: 'KP_Separator', realName: 'KP_Separator'),
|
||||
0x00070087: const KeyNames(displayName: 'KanaRo', realName: 'kana_RO'),
|
||||
0x00070088: const KeyNames(displayName: 'Hiragana_Katakana', realName: 'Hiragana_Katakana'),
|
||||
0x00070089: const KeyNames(displayName: 'yen', realName: 'yen'),
|
||||
0x0007008a: const KeyNames(displayName: 'Henkan_Mode', realName: 'Henkan_Mode'),
|
||||
0x0007008b: const KeyNames(displayName: 'Muhenkan', realName: 'Muhenkan'),
|
||||
0x00070090: const KeyNames(displayName: 'Hangul', realName: 'Hangul'),
|
||||
0x00070091: const KeyNames(displayName: 'Hangul_Hanja', realName: 'Hangul_Hanja'),
|
||||
0x00070092: const KeyNames(displayName: 'Katakana', realName: 'Katakana'),
|
||||
0x00070093: const KeyNames(displayName: 'Hiragana', realName: 'Hiragana'),
|
||||
0x00070094: const KeyNames(displayName: 'Zenkaku', realName: 'Zenkaku'),
|
||||
0x000700b6: const KeyNames(displayName: 'KP_Left', realName: 'KP_Left'),
|
||||
0x000700b7: const KeyNames(displayName: 'KP_Right', realName: 'KP_Right'),
|
||||
|
||||
/// Found on the Microsoft Natural Keyboard.
|
||||
// 0x000700bb: numpadBackspace,
|
||||
|
||||
/// W.T.F ???
|
||||
/*0x000700d0: numpadMemoryStore,
|
||||
0x000700d1: numpadMemoryRecall,
|
||||
0x000700d2: numpadMemoryClear,
|
||||
0x000700d3: numpadMemoryAdd,
|
||||
0x000700d4: numpadMemorySubtract,
|
||||
0x000700d7: numpadSignChange,
|
||||
0x000700d9: numpadClearEntry,*/
|
||||
0x000700d8: const KeyNames(displayName: 'NumLock', realName: 'Num_Lock'),
|
||||
0x000700e0: const KeyNames(displayName: 'Ctrl', realName: 'Control_L'),
|
||||
0x000700e1: const KeyNames(displayName: 'Shift', realName: 'Shift_L'),
|
||||
0x000700e2: const KeyNames(displayName: 'Alt', realName: 'Alt_L'),
|
||||
0x000700e3: const KeyNames(displayName: 'Super', realName: 'Super_L'),
|
||||
0x000700e4: const KeyNames(displayName: 'Ctrl', realName: 'Control_R'),
|
||||
0x000700e5: const KeyNames(displayName: 'Shift', realName: 'Shift_R'),
|
||||
0x000700e6: const KeyNames(displayName: 'Alt', realName: 'Alt_R'),
|
||||
0x000700e7: const KeyNames(displayName: 'Super', realName: 'Super_R'),
|
||||
|
||||
/// Toggles the display of information about the currently selected content, program, or media.
|
||||
// 0x000c0060: info,
|
||||
|
||||
/// Toggles closed captioning on and off.
|
||||
// 0x000c0061: closedCaptionToggle,
|
||||
|
||||
/// Too dangerous ...
|
||||
/*0x000c006f: brightnessUp,
|
||||
0x000c0070: brightnessDown,
|
||||
0x000c0072: brightnessToggle,
|
||||
0x000c0073: brightnessMinimum,
|
||||
0x000c0074: brightnessMaximum,
|
||||
0x000c0075: brightnessAuto,*/
|
||||
|
||||
/// seems only works on mobile.
|
||||
/*0x000c0079: kbdIllumUp,
|
||||
0x000c007a: kbdIllumDown,
|
||||
0x000c0083: mediaLast,
|
||||
0x000c008c: launchPhone,
|
||||
0x000c008d: programGuide,
|
||||
0x000c0094: exit,
|
||||
0x000c009c: channelUp,
|
||||
0x000c009d: channelDown,
|
||||
0x000c00b0: mediaPlay,
|
||||
0x000c00b1: mediaPause,
|
||||
0x000c00b2: mediaRecord,
|
||||
0x000c00b3: mediaFastForward,
|
||||
0x000c00b4: mediaRewind,
|
||||
0x000c00b5: mediaTrackNext,
|
||||
0x000c00b6: mediaTrackPrevious,
|
||||
0x000c00b7: mediaStop,
|
||||
|
||||
/// Mac only
|
||||
// 0x000c00b8: eject,
|
||||
0x000c00cd: mediaPlayPause,
|
||||
0x000c00cf: speechInputToggle,
|
||||
0x000c00e5: bassBoost,
|
||||
0x000c0183: mediaSelect,*/
|
||||
0x000c0184: const KeyNames(displayName: 'XF86Word', realName: 'XF86Word'),
|
||||
0x000c0186: const KeyNames(displayName: 'XF86Excel', realName: 'XF86Excel'),
|
||||
0x000c018a: const KeyNames(displayName: 'XF86Mail', realName: 'XF86Mail'),
|
||||
|
||||
/// not implements on linux.
|
||||
// 0x000c018d: launchContacts,
|
||||
0x000c018e: const KeyNames(displayName: 'XF86Calendar', realName: 'XF86Calendar'),
|
||||
0x000c0192: const KeyNames(displayName: 'XF86Launch2', realName: 'XF86Launch2'),
|
||||
0x000c0194: const KeyNames(displayName: 'XF86Launch1', realName: 'XF86Launch1'),
|
||||
|
||||
/// I don't think need implement those keys
|
||||
/*0x000c0196: launchInternetBrowser,
|
||||
0x000c019c: logOff,
|
||||
0x000c019e: lockScreen,
|
||||
0x000c019f: launchControlPanel,
|
||||
0x000c01a2: selectTask,
|
||||
0x000c01a7: launchDocuments,
|
||||
0x000c01ab: spellCheck,
|
||||
0x000c01ae: launchKeyboardLayout,
|
||||
0x000c01b1: launchScreenSaver,
|
||||
0x000c01b7: launchAudioBrowser,
|
||||
0x000c01cb: launchAssistant,
|
||||
0x000c0201: newKey,
|
||||
0x000c0203: close,
|
||||
0x000c0207: save,
|
||||
0x000c0208: print,
|
||||
0x000c0221: browserSearch,
|
||||
0x000c0223: browserHome,
|
||||
0x000c0224: browserBack,
|
||||
0x000c0225: browserForward,
|
||||
0x000c0226: browserStop,
|
||||
0x000c0227: browserRefresh,
|
||||
0x000c022a: browserFavorites,
|
||||
0x000c022d: zoomIn,
|
||||
0x000c022e: zoomOut,
|
||||
0x000c0232: zoomToggle,
|
||||
0x000c0279: redo,
|
||||
0x000c0289: mailReply,
|
||||
0x000c028b: mailForward,
|
||||
0x000c028c: mailSend,
|
||||
0x000c029d: keyboardLayoutSelect,
|
||||
0x000c029f: showAllWindows,*/
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/settings.provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:glass_kit/glass_kit.dart';
|
||||
|
||||
@@ -7,6 +9,8 @@ class DButton extends StatefulWidget {
|
||||
final double height;
|
||||
final Widget child;
|
||||
final GestureTapCallback? onTap;
|
||||
final EdgeInsets? padding;
|
||||
final Color? activeBorderColor;
|
||||
|
||||
const DButton({
|
||||
Key? key,
|
||||
@@ -14,8 +18,94 @@ class DButton extends StatefulWidget {
|
||||
this.height = defaultButtonHeight,
|
||||
required this.child,
|
||||
this.onTap,
|
||||
this.padding,
|
||||
this.activeBorderColor,
|
||||
}) : super(key: key);
|
||||
|
||||
factory DButton.add({
|
||||
Key? key,
|
||||
required enabled,
|
||||
GestureTapCallback? onTap,
|
||||
height = defaultButtonHeight * .7,
|
||||
width = defaultButtonHeight * .7,
|
||||
}) =>
|
||||
DButton(
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.add, size: 18)),
|
||||
message: LocaleKeys.operation_add.tr(),
|
||||
));
|
||||
|
||||
factory DButton.delete({
|
||||
Key? key,
|
||||
required enabled,
|
||||
GestureTapCallback? onTap,
|
||||
height = defaultButtonHeight * .7,
|
||||
width = defaultButtonHeight * .7,
|
||||
}) =>
|
||||
DButton(
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.remove, size: 18)),
|
||||
message: LocaleKeys.operation_delete.tr(),
|
||||
));
|
||||
|
||||
factory DButton.apply({
|
||||
Key? key,
|
||||
required enabled,
|
||||
GestureTapCallback? onTap,
|
||||
height = defaultButtonHeight * .7,
|
||||
width = defaultButtonHeight * .7,
|
||||
}) =>
|
||||
DButton(
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.check, size: 18)),
|
||||
message: LocaleKeys.operation_apply.tr(),
|
||||
));
|
||||
|
||||
factory DButton.duplicate({
|
||||
Key? key,
|
||||
required enabled,
|
||||
GestureTapCallback? onTap,
|
||||
height = defaultButtonHeight * .7,
|
||||
width = defaultButtonHeight * .7,
|
||||
}) =>
|
||||
DButton(
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
onTap: onTap,
|
||||
child: Tooltip(
|
||||
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.copy_rounded, size: 18)),
|
||||
message: LocaleKeys.operation_duplicate.tr(),
|
||||
));
|
||||
|
||||
factory DButton.dropdown({
|
||||
Key? key,
|
||||
width = 60.0,
|
||||
height = kMinInteractiveDimension * .86,
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
required enabled,
|
||||
required DropdownButton child,
|
||||
}) =>
|
||||
DButton(
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
padding: padding,
|
||||
child: child,
|
||||
);
|
||||
|
||||
@override
|
||||
State<DButton> createState() => _DButtonState();
|
||||
}
|
||||
@@ -26,8 +116,9 @@ class _DButtonState extends State<DButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: widget.onTap,
|
||||
onTap: widget.child is DropdownButton ? (widget.child as DropdownButton).onTap : widget.onTap,
|
||||
child: GlassContainer(
|
||||
padding: widget.padding,
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
gradient: LinearGradient(
|
||||
@@ -35,8 +126,10 @@ class _DButtonState extends State<DButton> {
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
),
|
||||
borderColor: Color(0xff565656),
|
||||
borderWidth: 1,
|
||||
borderColor: _hovering
|
||||
? (widget.activeBorderColor ?? context.watch<SettingsProvider>().currentActiveColor)
|
||||
: Color(0xff565656),
|
||||
borderWidth: 2,
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
child: MouseRegion(
|
||||
onEnter: (event) => setState(() {
|
||||
|
||||
@@ -420,6 +420,7 @@ class DDataCell {
|
||||
/// * <https://material.io/design/components/data-tables.html>
|
||||
class DDataTable extends StatefulWidget {
|
||||
final Color headerBackgroundColor;
|
||||
final ScrollController verticalScrollController;
|
||||
|
||||
/// Creates a widget describing a data table.
|
||||
///
|
||||
@@ -466,6 +467,7 @@ class DDataTable extends StatefulWidget {
|
||||
required this.rows,
|
||||
this.checkboxHorizontalMargin,
|
||||
required this.headerBackgroundColor,
|
||||
required this.verticalScrollController,
|
||||
}) : assert(columns != null),
|
||||
assert(columns.isNotEmpty),
|
||||
assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length)),
|
||||
@@ -755,7 +757,7 @@ class _DDataTableState extends State<DDataTable> {
|
||||
textDirection: numeric ? TextDirection.rtl : null,
|
||||
mainAxisAlignment: center ? MainAxisAlignment.spaceAround : MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
label,
|
||||
Flexible(child: label),
|
||||
if (onSort != null) ...<Widget>[
|
||||
_SortArrow(
|
||||
visible: sorted,
|
||||
@@ -1033,6 +1035,7 @@ class _DDataTableState extends State<DDataTable> {
|
||||
padding: EdgeInsets.only(top: _headersRect?.last.height ?? 0),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
controller: widget.verticalScrollController,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, -(_headersRect?.last.height ?? 0)),
|
||||
child: Table(
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:dde_gesture_manager/constants/sp_keys.dart';
|
||||
import 'package:dde_gesture_manager/constants/supported_locales.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/generated/codegen_loader.g.dart';
|
||||
import 'package:dde_gesture_manager/generated/locale_keys.g.dart';
|
||||
import 'package:dde_gesture_manager/models/local_schemes_provider.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:easy_localization/src/translations.dart';
|
||||
|
||||
class LanguageSwitcher extends StatelessWidget {
|
||||
const LanguageSwitcher({Key? key}) : super(key: key);
|
||||
@@ -15,10 +16,10 @@ class LanguageSwitcher extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _locale = EasyLocalization.of(context)?.currentLocale;
|
||||
var _supportedLocale = supportedLocales.firstWhereOrNull((element) => element == _locale);
|
||||
var _supportedLocale = getSupportedLocale(_locale) ?? SupportedLocale.zh_CN;
|
||||
|
||||
return PopupMenuButton<SupportedLocale>(
|
||||
tooltip: LocaleKeys.language_tip.tr(),
|
||||
tooltip: LocaleKeys.language_tip.tr(),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.language_outlined, size: 20),
|
||||
@@ -28,23 +29,29 @@ class LanguageSwitcher extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
itemBuilder: (BuildContext context) => supportedLocales
|
||||
initialValue: _supportedLocale,
|
||||
onSelected: (value) {
|
||||
EasyLocalization.of(context)?.setLocale(transformSupportedLocale(value)).then((_) {
|
||||
var localeMap = Translations(CodegenLoader.mapLocales[context.locale.toString()]!);
|
||||
if (!kIsWeb) WindowManager.instance.setTitle(localeMap.get(LocaleKeys.app_name)!);
|
||||
var localSchemesProvider = context.read<LocalSchemesProvider>();
|
||||
var schemes = localSchemesProvider.schemes!;
|
||||
var newSchemes = [
|
||||
schemes.first
|
||||
..scheme.name = localeMap.get(LocaleKeys.local_manager_default_scheme_label)
|
||||
..scheme.description = localeMap.get(LocaleKeys.local_manager_default_scheme_description),
|
||||
...schemes.skip(1),
|
||||
];
|
||||
localSchemesProvider.setProps(schemes: newSchemes);
|
||||
});
|
||||
H().sp.setInt(SPKeys.userLanguage, value.index);
|
||||
},
|
||||
itemBuilder: (BuildContext context) => SupportedLocale.values
|
||||
.map(
|
||||
(locale) => PopupMenuItem(
|
||||
value: SupportedLocale.zh_CN,
|
||||
child: ListTile(
|
||||
leading: Visibility(
|
||||
child: Icon(CupertinoIcons.check_mark),
|
||||
visible: _supportedLocale == locale,
|
||||
),
|
||||
title: Text(supportedLocaleNames[SupportedLocale.values[supportedLocales.indexOf(locale)]] ?? ''),
|
||||
),
|
||||
onTap: () {
|
||||
EasyLocalization.of(context)?.setLocale(locale).then((_) {
|
||||
if (!kIsWeb) WindowManager.instance.setTitle(LocaleKeys.app_name.tr());
|
||||
});
|
||||
H().sp.setInt(SPKeys.userLanguage, supportedLocales.indexOf(locale));
|
||||
},
|
||||
(supportedLocale) => CheckedPopupMenuItem(
|
||||
value: supportedLocale,
|
||||
checked: EasyLocalization.of(context)?.locale == transformSupportedLocale(supportedLocale),
|
||||
child: Text(supportedLocaleNames[supportedLocale] ?? ''),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/settings.provider.dart';
|
||||
import 'package:dde_gesture_manager/utils/keyboard_mapper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class TableCellShortcutListener extends StatefulWidget {
|
||||
final double width;
|
||||
final String initShortcut;
|
||||
final Function(String shortcut) onComplete;
|
||||
|
||||
const TableCellShortcutListener({
|
||||
Key? key,
|
||||
this.width = 150.0,
|
||||
required this.initShortcut,
|
||||
required this.onComplete,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_TableCellShortcutListenerState createState() => _TableCellShortcutListenerState();
|
||||
}
|
||||
|
||||
class _TableCellShortcutListenerState extends State<TableCellShortcutListener> {
|
||||
List<KeyNames> _shortcut = [];
|
||||
bool inputMode = false;
|
||||
FocusNode _focusNode = FocusNode();
|
||||
|
||||
_handleFocusChange() {
|
||||
if (!_focusNode.hasFocus) {
|
||||
widget.onComplete(_shortcut.join('+'));
|
||||
}
|
||||
}
|
||||
|
||||
_tryToAddKey(PhysicalKeyboardKey key) {
|
||||
var names = getPhysicalKeyNames(key.usbHidUsage);
|
||||
if (names != null && !_shortcut.contains(names))
|
||||
setState(() {
|
||||
_shortcut.add(names);
|
||||
_shortcut.sort();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
var __shortcut = widget.initShortcut.split('+');
|
||||
__shortcut.forEach((name) {
|
||||
var keyNames = getPhysicalKeyNamesByRealName(name);
|
||||
if (keyNames != null) _shortcut.add(keyNames);
|
||||
});
|
||||
_shortcut.sort();
|
||||
_focusNode.addListener(_handleFocusChange);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.removeListener(_handleFocusChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RawKeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
onKey: (evt) {
|
||||
_tryToAddKey(evt.physicalKey);
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_shortcut = [];
|
||||
inputMode = true;
|
||||
});
|
||||
},
|
||||
child: Focus(
|
||||
autofocus: true,
|
||||
onKeyEvent: (_, __) => KeyEventResult.skipRemainingHandlers,
|
||||
child: Container(
|
||||
height: kMinInteractiveDimension * .86,
|
||||
width: widget.width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
color: Colors.grey.withOpacity(.3),
|
||||
border: Border.all(
|
||||
width: 2,
|
||||
color: Focus.of(context).hasFocus
|
||||
? context.watch<SettingsProvider>().activeColor ?? Color(0xff565656)
|
||||
: Color(0xff565656)),
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 5),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: _shortcut
|
||||
.map(
|
||||
(e) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius / 2),
|
||||
color: context.t.dialogBackgroundColor,
|
||||
border: Border.all(width: 1, color: Color(0xff565656)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||
child: Text(
|
||||
e.displayName.notNull ? e.displayName : LocaleKeys.str_null.tr(),
|
||||
style: TextStyle(
|
||||
color: context.watch<SettingsProvider>().activeColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/models/settings.provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class TableCellTextField extends StatefulWidget {
|
||||
final String? initText;
|
||||
final String? hint;
|
||||
final Function(String value) onComplete;
|
||||
|
||||
const TableCellTextField({
|
||||
Key? key,
|
||||
this.initText,
|
||||
this.hint,
|
||||
required this.onComplete,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_TableCellTextFieldState createState() => _TableCellTextFieldState();
|
||||
}
|
||||
|
||||
class _TableCellTextFieldState extends State<TableCellTextField> {
|
||||
final FocusNode _focusNode = FocusNode(
|
||||
onKeyEvent: (_, __) => KeyEventResult.skipRemainingHandlers,
|
||||
);
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_focusNode.addListener(_handleFocusChange);
|
||||
_controller.text = widget.initText ?? '';
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.removeListener(_handleFocusChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_handleFocusChange() {
|
||||
if (!_focusNode.hasFocus) {
|
||||
widget.onComplete(_controller.text);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: kMinInteractiveDimension * .86,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(defaultBorderRadius),
|
||||
color: Colors.grey.withOpacity(.3),
|
||||
border: Border.all(
|
||||
width: 2,
|
||||
color: Focus.of(context).hasFocus
|
||||
? context.watch<SettingsProvider>().activeColor ??
|
||||
Color(0xff565656)
|
||||
: Color(0xff565656)),
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 15),
|
||||
child: TextField(
|
||||
focusNode: _focusNode,
|
||||
cursorColor: context.watch<SettingsProvider>().activeColor,
|
||||
decoration: InputDecoration.collapsed(hintText: widget.hint),
|
||||
controller: _controller,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class ThemeSwitcher extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _brightnessMode = context.watch<ConfigsProvider>().brightnessMode;
|
||||
return PopupMenuButton(
|
||||
return PopupMenuButton<BrightnessMode>(
|
||||
initialValue: _brightnessMode,
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -23,35 +23,23 @@ class ThemeSwitcher extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
onSelected: (value) => context.read<ConfigsProvider>().setProps(brightnessMode: value),
|
||||
tooltip: LocaleKeys.theme_tip.tr(),
|
||||
itemBuilder: (BuildContext context) => [
|
||||
PopupMenuItem<BrightnessMode>(
|
||||
child: ListTile(
|
||||
leading: Visibility(
|
||||
child: Icon(CupertinoIcons.check_mark),
|
||||
visible: _brightnessMode == BrightnessMode.system,
|
||||
),
|
||||
title: Text(LocaleKeys.theme_system).tr(),
|
||||
),
|
||||
onTap: () => context.read<ConfigsProvider>().setProps(brightnessMode: BrightnessMode.system),
|
||||
CheckedPopupMenuItem<BrightnessMode>(
|
||||
child: Text(LocaleKeys.theme_system).tr(),
|
||||
checked: _brightnessMode == BrightnessMode.system,
|
||||
value: BrightnessMode.system,
|
||||
),
|
||||
PopupMenuItem<BrightnessMode>(
|
||||
child: ListTile(
|
||||
leading: Visibility(
|
||||
child: Icon(CupertinoIcons.check_mark),
|
||||
visible: _brightnessMode == BrightnessMode.light,
|
||||
),
|
||||
title: Text(LocaleKeys.theme_light).tr()),
|
||||
onTap: () => context.read<ConfigsProvider>().setProps(brightnessMode: BrightnessMode.light),
|
||||
CheckedPopupMenuItem<BrightnessMode>(
|
||||
child: Text(LocaleKeys.theme_light).tr(),
|
||||
checked: _brightnessMode == BrightnessMode.light,
|
||||
value: BrightnessMode.light,
|
||||
),
|
||||
PopupMenuItem<BrightnessMode>(
|
||||
child: ListTile(
|
||||
leading: Visibility(
|
||||
child: Icon(CupertinoIcons.check_mark),
|
||||
visible: _brightnessMode == BrightnessMode.dark,
|
||||
),
|
||||
title: Text(LocaleKeys.theme_dark).tr()),
|
||||
onTap: () => context.read<ConfigsProvider>().setProps(brightnessMode: BrightnessMode.dark),
|
||||
CheckedPopupMenuItem<BrightnessMode>(
|
||||
child: Text(LocaleKeys.theme_dark).tr(),
|
||||
checked: _brightnessMode == BrightnessMode.dark,
|
||||
value: BrightnessMode.dark,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -35,6 +35,8 @@ dependencies:
|
||||
glass_kit: ^2.0.1
|
||||
rect_getter: ^1.0.0
|
||||
path_provider: ^2.0.5
|
||||
uuid: ^3.0.5
|
||||
adaptive_scrollbar: ^2.1.0
|
||||
xdg_directories_web:
|
||||
path: 3rd_party/xdg_directories_web
|
||||
|
||||
|
||||
@@ -20,13 +20,17 @@
|
||||
"tip": "Display help documentation"
|
||||
},
|
||||
"market": {
|
||||
"title": "Solution market"
|
||||
"title": "Scheme market"
|
||||
},
|
||||
"local_manager": {
|
||||
"title": "Local solution management"
|
||||
"title": "Local scheme management",
|
||||
"default_scheme": {
|
||||
"label": "System default scheme",
|
||||
"description": "System default gesture scheme, cannot be modified. (Secretly telling you that there is no actual content in this scheme, just when applying the scheme, it is achieved by deleting a custom configuration scheme."
|
||||
}
|
||||
},
|
||||
"gesture_editor": {
|
||||
"label": "Gesture program editing",
|
||||
"label": "Gesture scheme editing",
|
||||
"gesture": "gesture",
|
||||
"direction": "direction",
|
||||
"fingers": "fingers",
|
||||
@@ -58,5 +62,24 @@
|
||||
"delete": "delete",
|
||||
"duplicate": "duplicate",
|
||||
"apply": "apply"
|
||||
},
|
||||
"str": {
|
||||
"null": "Null"
|
||||
},
|
||||
"built_in_commands": {
|
||||
"ShowWorkspace": "ShowWorkspace",
|
||||
"Handle4Or5FingersSwipeUp": "4/5FingersSwipeUp",
|
||||
"Handle4Or5FingersSwipeDown": "4/5FingersSwipeDown",
|
||||
"ToggleMaximize": "ToggleMaximize",
|
||||
"Minimize": "Minimize",
|
||||
"ShowWindow": "ShowWindow",
|
||||
"ShowAllWindow": "ShowAllWindow",
|
||||
"SwitchApplication": "SwitchApplication",
|
||||
"ReverseSwitchApplication": "ReverseSwitchApplication",
|
||||
"SwitchWorkspace": "SwitchWorkspace",
|
||||
"ReverseSwitchWorkspace": "ReverseSwitchWorkspace",
|
||||
"SplitWindowLeft": "SplitWindowLeft",
|
||||
"SplitWindowRight": "SplitWindowRight",
|
||||
"MoveWindow": "MoveWindow"
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,11 @@
|
||||
"title": "方案市场"
|
||||
},
|
||||
"local_manager": {
|
||||
"title": "本地方案管理"
|
||||
"title": "本地方案管理",
|
||||
"default_scheme": {
|
||||
"label": "系统默认方案",
|
||||
"description": "系统默认的手势方案,不可修改。(偷偷告诉你,这个这个方案里没有任何实际内容,应用该方案时不过是通过删除自定义配置方案的方式来实现恢复系统默认方案~)"
|
||||
}
|
||||
},
|
||||
"gesture_editor": {
|
||||
"label": "手势方案编辑",
|
||||
@@ -58,5 +62,24 @@
|
||||
"delete": "删除",
|
||||
"duplicate": "复制",
|
||||
"apply": "应用"
|
||||
},
|
||||
"str": {
|
||||
"null": "无"
|
||||
},
|
||||
"built_in_commands": {
|
||||
"ShowWorkspace": "显示工作区",
|
||||
"Handle4Or5FingersSwipeUp": "4/5指向上划",
|
||||
"Handle4Or5FingersSwipeDown": "4/5指向下划",
|
||||
"ToggleMaximize": "全屏切换",
|
||||
"Minimize": "最小化",
|
||||
"ShowWindow": "显示桌面",
|
||||
"ShowAllWindow": "查看所有窗口",
|
||||
"SwitchApplication": "切换应用窗口",
|
||||
"ReverseSwitchApplication": "反向切换应用窗口",
|
||||
"SwitchWorkspace": "切换工作区",
|
||||
"ReverseSwitchWorkspace": "反向切换工作区",
|
||||
"SplitWindowLeft": "向左分屏",
|
||||
"SplitWindowRight": "向右分屏",
|
||||
"MoveWindow": "移动窗口"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user