aves/lib/widgets/viewer/info/metadata/xmp_structs.dart
2021-01-11 18:46:41 +09:00

141 lines
4.2 KiB
Dart

import 'dart:math';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/basic/multi_cross_fader.dart';
import 'package:aves/widgets/common/identity/highlight_title.dart';
import 'package:aves/widgets/viewer/info/common.dart';
import 'package:flutter/material.dart';
class XmpStructArrayCard extends StatefulWidget {
final String title;
final List<Map<String, String>> structs = [];
final Map<String, InfoLinkHandler> Function(int index) linkifier;
XmpStructArrayCard({
@required this.title,
@required Map<int, Map<String, String>> structByIndex,
this.linkifier,
}) {
structs.length = structByIndex.keys.fold(0, max);
structByIndex.keys.forEach((index) => structs[index - 1] = structByIndex[index]);
}
@override
_XmpStructArrayCardState createState() => _XmpStructArrayCardState();
}
class _XmpStructArrayCardState extends State<XmpStructArrayCard> {
int _index;
List<Map<String, String>> get structs => widget.structs;
@override
void initState() {
super.initState();
_index = structs.length - 1;
}
@override
Widget build(BuildContext context) {
void setIndex(int index) {
index = index.clamp(0, structs.length - 1);
if (_index != index) {
_index = index;
setState(() {});
}
}
return Card(
margin: XmpStructCard.cardMargin,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 8, top: 8, right: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
child: HighlightTitle(
'${widget.title} ${_index + 1}',
color: Colors.transparent,
selectable: true,
),
),
IconButton(
visualDensity: VisualDensity.compact,
icon: Icon(AIcons.previous),
onPressed: _index > 0 ? () => setIndex(_index - 1) : null,
tooltip: 'Previous',
),
IconButton(
visualDensity: VisualDensity.compact,
icon: Icon(AIcons.next),
onPressed: _index < structs.length - 1 ? () => setIndex(_index + 1) : null,
tooltip: 'Next',
),
],
),
),
MultiCrossFader(
duration: Durations.xmpStructArrayCardTransition,
sizeCurve: Curves.easeOutBack,
alignment: AlignmentDirectional.topStart,
child: Padding(
// add padding at this level (instead of the column level)
// so that the crossfader can animate the content size
// without clipping the text
padding: EdgeInsets.only(left: 8, right: 8, bottom: 8),
child: InfoRowGroup(
structs[_index] ?? {},
maxValueLength: Constants.infoGroupMaxValueLength,
linkHandlers: widget.linkifier?.call(_index + 1),
),
),
),
],
),
);
}
}
class XmpStructCard extends StatelessWidget {
final String title;
final Map<String, String> struct;
final Map<String, InfoLinkHandler> Function() linkifier;
static const cardMargin = EdgeInsets.symmetric(vertical: 8, horizontal: 0);
const XmpStructCard({
@required this.title,
@required this.struct,
this.linkifier,
});
@override
Widget build(BuildContext context) {
return Card(
margin: cardMargin,
child: Padding(
padding: EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HighlightTitle(
title,
color: Colors.transparent,
selectable: true,
),
InfoRowGroup(
struct,
maxValueLength: Constants.infoGroupMaxValueLength,
linkHandlers: linkifier?.call(),
),
],
),
),
);
}
}