Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Theming options #3

Merged
merged 10 commits into from Mar 25, 2022
85 changes: 85 additions & 0 deletions example/lib/main.dart
Expand Up @@ -2,6 +2,7 @@ import 'dart:convert';

import 'package:data_explorer/data_explorer.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';

Expand Down Expand Up @@ -189,6 +190,90 @@ class _DataExplorerPageState extends State<DataExplorerPage> {
child: JsonDataExplorer(
nodes: state.displayNodes,
itemScrollController: state.itemScrollController,

/// Builds a widget after each root node displaying the
/// number of children nodes that it has. Displays `{x}`
/// if it is a class or `[x]` in case of arrays.
rootInformationBuilder: (context, node) => DecoratedBox(
victorbotamedi marked this conversation as resolved.
Show resolved Hide resolved
decoration: const BoxDecoration(
color: Color(0x80E1E1E1),
borderRadius: BorderRadius.all(Radius.circular(2)),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4,
vertical: 2,
),
child: Text(
node.isClass
? '{${(node.childrenCount)}}'
: '[${node.childrenCount}]',
style: GoogleFonts.inconsolata(
fontSize: 12,
color: const Color(0xFF6F6F6F),
),
),
),
),

/// Build an animated collapse/expand indicator. Implicitly
/// animates the indicator when
/// [NodeViewModelState.isCollapsed] changes.
collapsableToggleBuilder: (context, node) =>
AnimatedRotation(
turns: node.isCollapsed ? -0.25 : 0,
duration: const Duration(milliseconds: 300),
child: const Icon(Icons.arrow_drop_down),
),

/// Creates a custom format for classes and array names.
rootNameFormatter: (name) => '$name',

/// Theme definitions of the json data explorer
theme: DataExplorerTheme(
rootKeyTextStyle: GoogleFonts.inconsolata(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 16,
),
propertyKeyTextStyle: GoogleFonts.inconsolata(
color: Colors.black.withOpacity(0.7),
fontWeight: FontWeight.bold,
fontSize: 16,
),
keySearchHighlightTextStyle: GoogleFonts.inconsolata(
color: Colors.black,
backgroundColor: const Color(0xFFFFEDAD),
fontWeight: FontWeight.bold,
fontSize: 16,
),
focusedKeySearchHighlightTextStyle:
GoogleFonts.inconsolata(
color: Colors.black,
backgroundColor: const Color(0xFFF29D0B),
fontWeight: FontWeight.bold,
fontSize: 16,
),
valueTextStyle: GoogleFonts.inconsolata(
color: const Color(0xFFCA442C),
fontSize: 16,
),
valueSearchHighlightTextStyle: GoogleFonts.inconsolata(
color: const Color(0xFFCA442C),
backgroundColor: const Color(0xFFFFEDAD),
fontWeight: FontWeight.bold,
fontSize: 16,
),
focusedValueSearchHighlightTextStyle:
GoogleFonts.inconsolata(
color: Colors.black,
backgroundColor: const Color(0xFFF29D0B),
fontWeight: FontWeight.bold,
fontSize: 16,
),
indentationLineColor: const Color(0xFFE1E1E1),
highlightColor: const Color(0xFFF1F1F1),
),
),
),
],
Expand Down
2 changes: 2 additions & 0 deletions example/pubspec.yaml
Expand Up @@ -11,7 +11,9 @@ dependencies:
sdk: flutter
data_explorer:
path: ../

http: ^0.13.4
google_fonts: ^2.3.1

dev_dependencies:
flutter_test:
Expand Down
1 change: 1 addition & 0 deletions lib/data_explorer.dart
@@ -1,4 +1,5 @@
library data_explorer;

export 'src/data_explorer_store.dart';
export 'src/data_explorer_theme.dart';
export 'src/json_data_explorer.dart';
208 changes: 208 additions & 0 deletions lib/src/data_explorer_theme.dart
@@ -0,0 +1,208 @@
import 'package:flutter/material.dart';

/// Theme used to display the [JsonDataExplorer].
@immutable
class DataExplorerTheme {
/// Text style used to display json class/arrays key attributes.
///
/// Defaults to [propertyKeyTextStyle] if not set.
final TextStyle rootKeyTextStyle;

/// Text style used to display json property key attributes.
final TextStyle propertyKeyTextStyle;

/// Text style to display the values of of json attributes.
final TextStyle valueTextStyle;

/// Text style use to highlight search result matches on json attribute keys.
final TextStyle keySearchHighlightTextStyle;

/// Text style use to highlight search result matches on json attribute
/// values.
final TextStyle valueSearchHighlightTextStyle;

/// Text style used to highlight the current focused search result node key.
///
/// If not set falls back to [keySearchHighlightTextStyle].
final TextStyle focusedKeySearchNodeHighlightTextStyle;

/// Text style used to highlight the current focused search result node value.
///
/// If not set falls back to [valueSearchHighlightTextStyle].
final TextStyle focusedValueSearchHighlightTextStyle;

/// Indentation lines color.
final Color indentationLineColor;

/// Padding used to indent nodes.
final double indentationPadding;

/// An extra factor applied on [indentationPadding] used when rendering
/// properties.
final double propertyIndentationPaddingFactor;

/// Cursor hover highlight color.
///
/// null to disable the highlight.
final Color? highlightColor;

DataExplorerTheme({
TextStyle? rootKeyTextStyle,
TextStyle? propertyKeyTextStyle,
TextStyle? keySearchHighlightTextStyle,
TextStyle? valueTextStyle,
TextStyle? valueSearchHighlightTextStyle,
TextStyle? focusedKeySearchHighlightTextStyle,
TextStyle? focusedValueSearchHighlightTextStyle,
this.indentationLineColor = Colors.grey,
this.highlightColor,
this.indentationPadding = 8.0,
this.propertyIndentationPaddingFactor = 4,
}) : rootKeyTextStyle = rootKeyTextStyle ??
(propertyKeyTextStyle ??
DataExplorerTheme.defaultTheme.rootKeyTextStyle),
propertyKeyTextStyle = propertyKeyTextStyle ??
DataExplorerTheme.defaultTheme.rootKeyTextStyle,
keySearchHighlightTextStyle = keySearchHighlightTextStyle ??
DataExplorerTheme.defaultTheme.keySearchHighlightTextStyle,
valueTextStyle =
valueTextStyle ?? DataExplorerTheme.defaultTheme.valueTextStyle,
valueSearchHighlightTextStyle = valueSearchHighlightTextStyle ??
DataExplorerTheme.defaultTheme.valueSearchHighlightTextStyle,
focusedKeySearchNodeHighlightTextStyle =
focusedKeySearchHighlightTextStyle ??
(keySearchHighlightTextStyle ??
DataExplorerTheme
.defaultTheme.focusedKeySearchNodeHighlightTextStyle),
focusedValueSearchHighlightTextStyle =
focusedValueSearchHighlightTextStyle ??
(valueSearchHighlightTextStyle ??
DataExplorerTheme
.defaultTheme.focusedValueSearchHighlightTextStyle);

const DataExplorerTheme._({
required this.rootKeyTextStyle,
required this.propertyKeyTextStyle,
required this.keySearchHighlightTextStyle,
required this.valueTextStyle,
required this.valueSearchHighlightTextStyle,
required this.focusedKeySearchNodeHighlightTextStyle,
required this.focusedValueSearchHighlightTextStyle,
this.indentationLineColor = Colors.grey,
this.highlightColor,
this.indentationPadding = 8.0,
this.propertyIndentationPaddingFactor = 4,
});

/// Default theme used if no theme is set.
static const defaultTheme = DataExplorerTheme._(
rootKeyTextStyle: TextStyle(
fontSize: 14,
color: Colors.black,
fontWeight: FontWeight.bold,
),
propertyKeyTextStyle: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
valueTextStyle: TextStyle(
fontSize: 14,
color: Colors.redAccent,
),
keySearchHighlightTextStyle: TextStyle(
fontSize: 14,
color: Colors.black,
fontWeight: FontWeight.bold,
backgroundColor: Colors.amberAccent,
),
valueSearchHighlightTextStyle: TextStyle(
fontSize: 14,
color: Colors.redAccent,
fontWeight: FontWeight.bold,
backgroundColor: Colors.amberAccent,
),
focusedKeySearchNodeHighlightTextStyle: TextStyle(
fontSize: 14,
color: Colors.black,
fontWeight: FontWeight.bold,
backgroundColor: Colors.lightGreen,
),
focusedValueSearchHighlightTextStyle: TextStyle(
fontSize: 14,
color: Colors.redAccent,
fontWeight: FontWeight.bold,
backgroundColor: Colors.lightGreen,
),
);

DataExplorerTheme copyWith({
TextStyle? rootKeyTextStyle,
TextStyle? propertyKeyTextStyle,
TextStyle? keySearchHighlightTextStyle,
TextStyle? valueTextStyle,
TextStyle? valueSearchHighlightTextStyle,
TextStyle? focusedKeySearchNodeHighlightTextStyle,
TextStyle? focusedValueSearchHighlightTextStyle,
Color? indentationLineColor,
Color? highlightColor,
double? indentationPadding,
double? propertyIndentationPaddingFactor,
}) =>
DataExplorerTheme(
rootKeyTextStyle: rootKeyTextStyle ?? this.rootKeyTextStyle,
propertyKeyTextStyle: propertyKeyTextStyle ?? this.propertyKeyTextStyle,
keySearchHighlightTextStyle:
keySearchHighlightTextStyle ?? this.keySearchHighlightTextStyle,
valueTextStyle: valueTextStyle ?? this.valueTextStyle,
valueSearchHighlightTextStyle:
valueSearchHighlightTextStyle ?? this.valueSearchHighlightTextStyle,
indentationLineColor: indentationLineColor ?? this.indentationLineColor,
highlightColor: highlightColor ?? this.highlightColor,
indentationPadding: indentationPadding ?? this.indentationPadding,
propertyIndentationPaddingFactor: propertyIndentationPaddingFactor ??
this.propertyIndentationPaddingFactor,
focusedKeySearchHighlightTextStyle:
focusedKeySearchNodeHighlightTextStyle ??
this.focusedKeySearchNodeHighlightTextStyle,
focusedValueSearchHighlightTextStyle:
focusedValueSearchHighlightTextStyle ??
this.focusedValueSearchHighlightTextStyle,
);

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other.runtimeType != runtimeType) return false;
return other is DataExplorerTheme &&
rootKeyTextStyle == other.rootKeyTextStyle &&
propertyKeyTextStyle == other.propertyKeyTextStyle &&
valueTextStyle == other.valueTextStyle &&
indentationLineColor == other.indentationLineColor &&
highlightColor == other.highlightColor &&
indentationPadding == other.indentationPadding &&
propertyIndentationPaddingFactor ==
other.propertyIndentationPaddingFactor &&
keySearchHighlightTextStyle == other.keySearchHighlightTextStyle &&
valueSearchHighlightTextStyle == other.valueSearchHighlightTextStyle &&
focusedKeySearchNodeHighlightTextStyle ==
other.focusedKeySearchNodeHighlightTextStyle &&
focusedValueSearchHighlightTextStyle ==
other.focusedValueSearchHighlightTextStyle;
}

@override
int get hashCode => Object.hash(
rootKeyTextStyle,
propertyKeyTextStyle,
valueTextStyle,
indentationLineColor,
highlightColor,
indentationPadding,
propertyIndentationPaddingFactor,
keySearchHighlightTextStyle,
valueSearchHighlightTextStyle,
focusedKeySearchNodeHighlightTextStyle,
focusedValueSearchHighlightTextStyle,
);
}