Skip to content

Commit

Permalink
Merge pull request #374 from Ariemeth/edit_cg_names
Browse files Browse the repository at this point in the history
Added ability to rename cgs
  • Loading branch information
Ariemeth authored Mar 9, 2024
2 parents ebc887b + 8d0f36f commit b3bf2c5
Show file tree
Hide file tree
Showing 9 changed files with 327 additions and 68 deletions.
38 changes: 31 additions & 7 deletions lib/models/combatGroups/combat_group.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,41 @@ import 'package:gearforce/models/validation/validations.dart';
class CombatGroup extends ChangeNotifier {
Group _primary = Group(GroupType.Primary);
Group _secondary = Group(GroupType.Secondary);
final String name;
String _name;
bool _isVeteran = false;
UnitRoster? roster;
List<CombatGroupOption> _options = [];

CombatGroup(String name, {Group? primary, Group? secondary, this.roster})
: _name = name {
this.primary = primary == null ? Group(GroupType.Primary) : primary;
this.secondary = secondary == null ? Group(GroupType.Secondary) : secondary;
_resetOptions();
}

String get name => _name;
set name(String newValue) {
if (_name == newValue) {
return;
}

if (roster != null) {
if (roster!.getCGs().any((value) => value.name == newValue)) {
int count = 1;
String newName = newValue;
while (roster!.getCGs().any((value) => value.name == newName)) {
print('Duplicate name found, changing rename to $newName');
newName = '${newValue} ($count)';
count++;
}
newValue = newName;
}
}

_name = newValue;
notifyListeners();
}

/// Retrieve the options associated with this [CombatGroup].
List<CombatGroupOption> get options => _options.toList();
bool hasOption(String id) => _options.any((o) => o.id == id);
Expand Down Expand Up @@ -92,12 +122,6 @@ class CombatGroup extends ChangeNotifier {
notifyListeners();
}

CombatGroup(this.name, {Group? primary, Group? secondary, this.roster}) {
this.primary = primary == null ? Group(GroupType.Primary) : primary;
this.secondary = secondary == null ? Group(GroupType.Secondary) : secondary;
_resetOptions();
}

Map<String, dynamic> toJson() => {
'primary': _primary.toJson(),
'secondary': _secondary.toJson(),
Expand Down
106 changes: 67 additions & 39 deletions lib/models/roster/roster.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class UnitRoster extends ChangeNotifier {
String? name;
late final ValueNotifier<Faction> factionNotifier;
late final ValueNotifier<RuleSet> rulesetNotifer;
final Map<String, CombatGroup> _combatGroups = new Map<String, CombatGroup>();
final List<CombatGroup> _combatGroups = new List.empty(growable: true);

int _totalCreated = 0;
String _activeCG = '';
Expand Down Expand Up @@ -51,8 +51,8 @@ class UnitRoster extends ChangeNotifier {
ValueNotifier<RuleSet>(factionNotifier.value.defaultSubFaction);

final rulesetListener = () {
_combatGroups.forEach((key, value) {
value.validate(tryFix: tryFix);
_combatGroups.forEach((cg) {
cg.validate(tryFix: tryFix);
});
notifyListeners();
};
Expand All @@ -68,12 +68,12 @@ class UnitRoster extends ChangeNotifier {

rulesetNotifer.addListener(() {
// Ensure each combat group is clear
_combatGroups.forEach((key, value) {
value.validate(tryFix: tryFix);
_combatGroups.forEach((cg) {
cg.validate(tryFix: tryFix);
});

if (_combatGroups.length > 1) {
_combatGroups.removeWhere((key, value) => value.units.length == 0);
_combatGroups.removeWhere((cg) => cg.units.length == 0);
if (_combatGroups.length == 0) {
createCG();
}
Expand All @@ -96,7 +96,7 @@ class UnitRoster extends ChangeNotifier {

_isEliteForce = newValue;

_combatGroups.forEach((id, cg) {
_combatGroups.forEach((cg) {
cg.isEliteForce = newValue;
});

Expand Down Expand Up @@ -135,8 +135,8 @@ class UnitRoster extends ChangeNotifier {

List<Unit> getAllUnits() {
final List<Unit> allUnits = [];
_combatGroups.entries.forEach((me) {
allUnits.addAll(me.value.units);
_combatGroups.forEach((cg) {
allUnits.addAll(cg.units);
});
return allUnits;
}
Expand All @@ -146,7 +146,7 @@ class UnitRoster extends ChangeNotifier {
final result = '\nRoster:\n' +
'\tPlayer: $player \tForce Name: $name\n' +
'\tFaction: ${factionNotifier.value.name} \\ ${rulesetNotifer.value.name}\n' +
'${_combatGroups.values.join('\n')}\n\n';
'${_combatGroups.join('\n')}\n\n';

return result;
}
Expand Down Expand Up @@ -177,7 +177,7 @@ class UnitRoster extends ChangeNotifier {
.indexOf(selectedForceLeader!),
},
'totalCreated': _totalCreated,
'cgs': _combatGroups.entries.map((e) => e.value.toJson()).toList(),
'cgs': _combatGroups.map((e) => e.toJson()).toList(),
'version': _currentRosterVersion,
'rulesVersion': rulesVersion,
'isEliteForce': isEliteForce,
Expand Down Expand Up @@ -227,18 +227,19 @@ class UnitRoster extends ChangeNotifier {
json['isEliteForce'] != null ? json['isEliteForce'] as bool : false;

var decodedCG = json['cgs'];
decodedCG
final cgList = decodedCG
.map((e) => CombatGroup.fromJson(
e,
data,
ur.factionNotifier.value,
ur.rulesetNotifer.value,
ur,
))
.toList()
..forEach((element) {
ur.addCG(element);
});
.toList();

cgList.forEach((cg) {
ur.addCG(cg);
});

try {
final leaderJson = json['forceLeader'];
Expand Down Expand Up @@ -271,23 +272,41 @@ class UnitRoster extends ChangeNotifier {
this.factionNotifier.value = ur.factionNotifier.value;
this.rulesetNotifer.value = ur.rulesetNotifer.value;
this._activeCG = ur._activeCG;
ur._combatGroups.forEach((key, cg) {
this._combatGroups.clear();
ur._combatGroups.forEach((cg) {
this.addCG(cg);
});
this._totalCreated = ur._totalCreated;
this._isEliteForce = ur._isEliteForce;
this.selectedForceLeader = ur.selectedForceLeader;
}

CombatGroup? getCG(String name) => _combatGroups[name];
CombatGroup? getCG(String name) {
if (_combatGroups.any((cg) => cg.name == name)) {
return _combatGroups.firstWhere((cg) => cg.name == name);
}
return null;
}

void addCG(CombatGroup cg) {
cg.roster = this;
if (_combatGroups.any((value) => value.name == cg.name)) {
int count = 1;
String newName = cg.name;
while (_combatGroups.any((value) => value.name == newName)) {
print('Duplicate name found: $newName');
newName = '${cg.name} ($count)';
count++;
}
cg.name = newName;
}

cg.addListener(() {
validate();
notifyListeners();
});
cg.roster = this;
_combatGroups[cg.name] = cg;

_combatGroups.add(cg);
if (_activeCG == '') {
_activeCG = cg.name;
}
Expand All @@ -297,18 +316,20 @@ class UnitRoster extends ChangeNotifier {

void removeCG(String name) {
// if the cg isn't part of the roster no need to do any more checks
if (!_combatGroups.keys.any((key) => key == name)) {
if (!_combatGroups.any((cg) => cg.name == name)) {
return;
}

_combatGroups[name]?.roster = null;
_combatGroups.where((cg) => cg.name == name).forEach((cg) {
cg.roster = null;
});

_combatGroups.remove(name);
_combatGroups.removeWhere((cg) => cg.name == name);
if (_activeCG == name) {
_activeCG = '';
}
if (_combatGroups.isNotEmpty) {
_activeCG = _combatGroups.keys.first;
_activeCG = _combatGroups.first.name;
} else {
createCG();
}
Expand All @@ -326,29 +347,37 @@ class UnitRoster extends ChangeNotifier {

int totalTV() {
var result = 0;
_combatGroups.forEach((key, value) {
result += value.totalTV();
_combatGroups.forEach((cg) {
result += cg.totalTV();
});

return result;
}

CombatGroup? activeCG() => _combatGroups[_activeCG];
CombatGroup? activeCG() {
if (_activeCG == '') {
return null;
}
if (!_combatGroups.any((cg) => cg.name == _activeCG)) {
return null;
}
return _combatGroups.firstWhere((cg) => cg.name == _activeCG);
}

void setActiveCG(String name) {
if (name == _activeCG) {
return;
}
if (_combatGroups.containsKey(name)) {
if (_combatGroups.any((cg) => cg.name == name)) {
_activeCG = name;
notifyListeners();
}
}

List<CombatGroup> getCGs() =>
_combatGroups.entries.map((e) => e.value).toList();
List<CombatGroup> getCGs() => new List<CombatGroup>.from(_combatGroups);

Unit? getFirstUnitWithCommand(CommandLevel cl) {
for (var cg in _combatGroups.values) {
for (var cg in _combatGroups) {
final u = cg.getUnitWithCommand(cl);
if (u != null) {
return u;
Expand All @@ -359,7 +388,7 @@ class UnitRoster extends ChangeNotifier {

List<Unit> getLeaders(CommandLevel? cl) {
final List<Unit> leaders = [];
_combatGroups.forEach((_, cg) {
_combatGroups.forEach((cg) {
leaders.addAll(cg.getLeaders(cl));
});
return leaders;
Expand All @@ -369,7 +398,7 @@ class UnitRoster extends ChangeNotifier {
// specific mod.
List<CombatGroup?> combatGroupsWithMod(String id) {
List<CombatGroup?> results = [];
_combatGroups.forEach((_, cg) {
_combatGroups.forEach((cg) {
if (cg.modCount(id) > 0) {
results.add(cg);
}
Expand All @@ -380,15 +409,14 @@ class UnitRoster extends ChangeNotifier {
// Retrieve a list of units that have the specified mod attached.
List<Unit> unitsWithMod(String id) {
List<Unit> listOfUnits = [];
_combatGroups
.forEach((name, cg) => listOfUnits.addAll(cg.unitsWithMod(id)));
_combatGroups.forEach((cg) => listOfUnits.addAll(cg.unitsWithMod(id)));
return listOfUnits;
}

List<Unit> unitsWithTrait(Trait trait) {
final List<Unit> results = [];

_combatGroups.entries.map((e) => e.value).forEach((cg) {
_combatGroups.forEach((cg) {
results.addAll(cg.unitsWithTrait(trait));
});

Expand All @@ -415,15 +443,15 @@ class UnitRoster extends ChangeNotifier {

List<Unit> get duelists {
final List<Unit> results = [];
_combatGroups.forEach((_, cg) {
_combatGroups.forEach((cg) {
results.addAll(cg.duelists);
});
return results;
}

int totalAirstrikeCounters() {
var total = 0;
_combatGroups.forEach((key, cg) {
_combatGroups.forEach((cg) {
total +=
cg.units.where((u) => u.type == ModelType.AirstrikeCounter).length;
});
Expand Down Expand Up @@ -464,7 +492,7 @@ class UnitRoster extends ChangeNotifier {
selectedForceLeader = forceLeaders.firstOrNull;
}

_combatGroups.forEach((key, cg) {
_combatGroups.forEach((cg) {
final ve = cg.validate(tryFix: tryFix);

validationErrors.addAll(ve.validations);
Expand Down
29 changes: 29 additions & 0 deletions lib/screens/roster/combatGroup/combat_group_options_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:gearforce/models/rules/options/combat_group_options.dart';
import 'package:gearforce/models/rules/rule_set.dart';
import 'package:gearforce/screens/roster/combatGroup/delete_combat_group_dialog.dart';
import 'package:gearforce/screens/roster/combatGroup/option_line.dart';
import 'package:gearforce/screens/roster/combatGroup/rename_combat_group_dialog.dart';
import 'package:gearforce/widgets/options_section_title.dart';

const double _optionSectionWidth = 400;
Expand Down Expand Up @@ -48,6 +49,34 @@ class _CombatGroupOptionsDialogState extends State<CombatGroupOptionsDialog> {
maxLines: 1,
),
Text(''),
ElevatedButton(
onPressed: () {
Future<RenameCGOptionResult?> futureResult =
showDialog<RenameCGOptionResult>(
context: context,
builder: (BuildContext context) {
return RenameCombatGroupDialog(
currentName: widget.cg.name,
);
});

futureResult.then((value) {
switch (value?.resultType) {
case RenameCGOptionResultType.Rename:
final newName = value?.newName;
if (newName != null) {
setState(() {
widget.cg.name = newName;
});
}
break;
default:
}
});
},
child: Text('Rename'),
),
Text(''),
options.isNotEmpty
? combatGroupOptions(options, widget.cg, onLineUpdate)
: Container(),
Expand Down
Loading

0 comments on commit b3bf2c5

Please sign in to comment.