Remove support for nested work parts

We will add a way to create sections as a much simpler replacement in
the future.
This commit is contained in:
Elias Projahn 2020-04-24 21:18:24 +02:00
parent f7f109179f
commit 18bc8eb982
3 changed files with 30 additions and 143 deletions

View file

@ -16,8 +16,7 @@ CREATE TABLE works (
composer INTEGER REFERENCES persons(id), composer INTEGER REFERENCES persons(id),
title TEXT NOT NULL, title TEXT NOT NULL,
part_of INTEGER REFERENCES works(id) ON DELETE CASCADE, part_of INTEGER REFERENCES works(id) ON DELETE CASCADE,
part_index INTEGER, part_index INTEGER
part_level INTEGER
); );
CREATE TABLE instrumentations ( CREATE TABLE instrumentations (

View file

@ -8,13 +8,11 @@ import '../selectors/person.dart';
class PartData { class PartData {
final titleController = TextEditingController(); final titleController = TextEditingController();
int level;
Person composer; Person composer;
List<Instrument> instruments; List<Instrument> instruments;
PartData({ PartData({
String title, String title,
this.level = 0,
this.composer, this.composer,
this.instruments = const [], this.instruments = const [],
}) { }) {
@ -108,17 +106,13 @@ class WorkProperties extends StatelessWidget {
class PartTile extends StatefulWidget { class PartTile extends StatefulWidget {
final PartData part; final PartData part;
final void Function() onMore; final void Function() onMore;
final void Function() onAdd;
final void Function() onDelete; final void Function() onDelete;
final void Function(int levels) onMove;
PartTile({ PartTile({
Key key, Key key,
@required this.part, @required this.part,
@required this.onMore, @required this.onMore,
@required this.onAdd,
@required this.onDelete, @required this.onDelete,
@required this.onMove,
}) : super(key: key); }) : super(key: key);
@override @override
@ -126,72 +120,34 @@ class PartTile extends StatefulWidget {
} }
class _PartTileState extends State<PartTile> { class _PartTileState extends State<PartTile> {
static const unit = 16.0;
static const iconShrink = 4.0;
double dragStart;
double dragDelta = 0.0;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final padding = widget.part.level * unit + dragDelta; return Row(
final iconSize = 24 - widget.part.level * iconShrink; children: <Widget>[
Padding(
return GestureDetector( padding: const EdgeInsets.only(left: 16.0, right: 8.0),
child: Padding( child: Icon(
padding: EdgeInsets.only(left: padding > 0.0 ? padding : 0.0), Icons.drag_handle,
child: Row( ),
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 16.0, right: 8.0),
child: Icon(
Icons.drag_handle,
size: iconSize,
),
),
Expanded(
child: TextField(
controller: widget.part.titleController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Part title',
),
),
),
IconButton(
icon: const Icon(Icons.more_horiz),
iconSize: iconSize,
onPressed: widget.onMore,
),
IconButton(
icon: const Icon(Icons.add),
iconSize: iconSize,
onPressed: widget.onAdd,
),
IconButton(
icon: const Icon(Icons.delete),
iconSize: iconSize,
onPressed: widget.onDelete,
),
],
), ),
), Expanded(
onHorizontalDragStart: (details) { child: TextField(
dragStart = details.localPosition.dx; controller: widget.part.titleController,
}, decoration: InputDecoration(
onHorizontalDragUpdate: (details) { border: InputBorder.none,
setState(() { hintText: 'Part title',
dragDelta = details.localPosition.dx - dragStart; ),
}); ),
}, ),
onHorizontalDragEnd: (details) { IconButton(
if (dragDelta.abs() >= unit) { icon: const Icon(Icons.more_horiz),
widget.onMove((dragDelta / unit).round()); onPressed: widget.onMore,
} ),
setState(() { IconButton(
dragDelta = 0.0; icon: const Icon(Icons.delete),
}); onPressed: widget.onDelete,
}, ),
],
); );
} }
} }
@ -276,7 +232,6 @@ class _WorkEditorState extends State<WorkEditor> {
parts.add(PartData( parts.add(PartData(
title: dbPart.title, title: dbPart.title,
composer: partComposer, composer: partComposer,
level: dbPart.partLevel,
instruments: partInstruments, instruments: partInstruments,
)); ));
}); });
@ -285,17 +240,6 @@ class _WorkEditorState extends State<WorkEditor> {
} }
} }
void cleanLevels() {
var previousLevel = -1;
for (var i = 0; i < parts.length; i++) {
final part = parts[i];
if (part.level > previousLevel + 1) {
part.level = previousLevel + 1;
}
previousLevel = part.level;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<Widget> partTiles = []; final List<Widget> partTiles = [];
@ -334,30 +278,11 @@ class _WorkEditorState extends State<WorkEditor> {
), ),
); );
}, },
onAdd: () {
setState(() {
parts.insert(i + 1, PartData(level: part.level + 1));
});
},
onDelete: () { onDelete: () {
setState(() { setState(() {
parts.removeAt(i); parts.removeAt(i);
cleanLevels();
}); });
}, },
onMove: (levels) {
if (levels > 0 && i > 0 && parts[i - 1].level >= part.level) {
setState(() {
part.level++;
});
} else if (levels < 0) {
final newLevel = part.level + levels;
setState(() {
part.level = newLevel > 0 ? newLevel : 0;
cleanLevels();
});
}
},
)); ));
} }
@ -389,7 +314,6 @@ class _WorkEditorState extends State<WorkEditor> {
composer: part.composer?.id, composer: part.composer?.id,
partOf: workId, partOf: workId,
partIndex: i, partIndex: i,
partLevel: part.level,
), ),
instrumentIds: part.instruments.map((i) => i.id).toList(), instrumentIds: part.instruments.map((i) => i.id).toList(),
)); ));
@ -425,7 +349,7 @@ class _WorkEditorState extends State<WorkEditor> {
padding: const EdgeInsets.only(left: 16.0, top: 16.0), padding: const EdgeInsets.only(left: 16.0, top: 16.0),
child: Text( child: Text(
'Parts', 'Parts',
style: Theme.of(context).textTheme.subhead, style: Theme.of(context).textTheme.subtitle1,
), ),
), ),
], ],
@ -437,8 +361,6 @@ class _WorkEditorState extends State<WorkEditor> {
final newIndex = i2 > i1 ? i2 - 1 : i2; final newIndex = i2 > i1 ? i2 - 1 : i2;
parts.insert(newIndex, part); parts.insert(newIndex, part);
cleanLevels();
}); });
}, },
), ),
@ -447,7 +369,7 @@ class _WorkEditorState extends State<WorkEditor> {
label: Text('Add part'), label: Text('Add part'),
onPressed: () { onPressed: () {
setState(() { setState(() {
parts.add(PartData(level: 0)); parts.add(PartData());
}); });
}, },
), ),

View file

@ -71,8 +71,8 @@ class ProgramTile extends StatelessWidget {
children: <Widget>[ children: <Widget>[
for (final part in item.workParts) for (final part in item.workParts)
Padding( Padding(
padding: EdgeInsets.only( padding: const EdgeInsets.only(
left: 8.0 + part.partLevel * 8.0, left: 8.0,
), ),
child: Text( child: Text(
part.title, part.title,
@ -162,10 +162,6 @@ class _ProgramScreenState extends State<ProgramScreen> {
// from the database again. // from the database again.
int lastWorkId; int lastWorkId;
// We need to keep track of the last work part to be able to check for the
// parent work parts that were left out between the two last tracks.
int lastPartId;
// This will always contain the parts of the current work. // This will always contain the parts of the current work.
List<Work> workParts = []; List<Work> workParts = [];
@ -193,40 +189,10 @@ class _ProgramScreenState extends State<ProgramScreen> {
} }
lastWorkId = recording.work; lastWorkId = recording.work;
lastPartId = null;
}
/// Search for all parent work parts of [partId] starting from the part
/// with the ID [startId] and add them to the part list.
void addParentParts(int startId, int partId) {
final level = workParts[partId].partLevel;
final List<Work> parents = List.filled(level - 1, null);
for (var i = startId; i < partId; i++) {
final part = workParts[i];
if (part.partLevel < parents.length) {
parents[part.partLevel] = part;
}
}
newWorkParts.addAll(parents);
} }
for (final partId in partIds) { for (final partId in partIds) {
// We will need to include all parent work parts first, if there were
// work parts left out between the last two tracks or if the current
// work part comes before the previous one.
if (lastPartId != null) {
if (partIds.first > lastPartId + 1) {
addParentParts(lastPartId + 1, partId);
}
} else if (partIds.first > 0) {
addParentParts(0, partId);
}
newWorkParts.add(workParts[partId]); newWorkParts.add(workParts[partId]);
lastPartId = partId;
} }
newItems.add(ProgramItem( newItems.add(ProgramItem(