module menu.browser.single; import std.algorithm; import std.format; import std.conv; import std.range; import optional; import basics.globals; import file.option; import file.language; import file.filename; import file.trophy; import game.harvest; import file.replay; import gui; import gui.picker; import hardware.sound; import level.level; import menu.browser.withlast; import menu.lastgame; final class BrowserSingle : BrowserWithLastAndDelete { private: bool _gotoEditorLoadFileRecent; bool _gotoEditorNewLevel; bool _gotoRepForLev; Level _levelRecent; // maybe null DTODONULL TextButton _edit; TextButton _newLevel; TextButton _repForLev; TextButton _exportImage; LabelTwo _by, _save, _trophySaved, _trophySkills; Label _exportImageDone; public: this() { super(Lang.browserSingleTitle.transl, basics.globals.dirLevels, super.pickerConfig()); commonConstructor(); // Final class calls: super.highlight(file.option.singleLastLevel); } this(Harvest ha, Optional!(const Replay) lastLoaded) { super(Lang.browserSingleTitle.transl, basics.globals.dirLevels, super.pickerConfig()); commonConstructor(); // Final class calls in correct order: super.addStatsThenHighlight( new StatsAfterReplay(super.newStatsGeom(), ha, lastLoaded), file.option.singleLastLevel); } override @property inout(Level) levelRecent() inout { return _levelRecent; } @property bool gotoEditorNewLevel() const { return _gotoEditorNewLevel; } @property bool gotoEditorLoadFileRecent() const { assert (! _gotoEditorLoadFileRecent || fileRecent); return _gotoEditorLoadFileRecent; } @property bool gotoRepForLev() const { assert (! _gotoRepForLev || fileRecent); return _gotoRepForLev; } protected: final override void onOnHighlightNone() { only(_edit, _exportImage, _repForLev, _by, _save, _trophySaved, _trophySkills, _exportImageDone).each!(e => e.hide()); _levelRecent = null; previewNone(); } final override void onHighlightWithLastGame(Filename fn, bool solved) in { assert (fn, "call onHighlightNone() instead"); } body { onHighlightWithoutLastGame(fn); _trophySkills.shown = false; } final override void onHighlightWithoutLastGame(Filename fn) in { assert (fn, "call onHighlightNone() instead"); } body { only(_edit, _exportImage, _repForLev, _by, _save).each!(e => e.show()); _exportImageDone.hide(); _levelRecent = new Level(fileRecent); previewLevel(_levelRecent); _by.value = _levelRecent.author; _save.value = "%d/%d".format(_levelRecent.required, _levelRecent.initial); TrophyKey key; key.fileNoExt = fn.fileNoExtNoPre; key.title = _levelRecent.name; key.author = _levelRecent.author; getTrophy(key).match!( (Trophy tro) { _trophySaved.shown = true; _trophySkills.shown = true; _trophySaved.value = tro.lixSaved; _trophySkills.value = tro.skillsUsed; }, () { _trophySaved.shown = false; _trophySkills.shown = false; }); } override void onPlay(Filename fn) { assert (fileRecent !is null); assert (_levelRecent !is null); // the super class guarantees that on_file_select is only called after // onFileHighlight has been called with the same fn immediately before if (_levelRecent.playable) { file.option.singleLastLevel = fileRecent; gotoGame = true; } } override Geom newDeleteButtonGeom() const { return new Geom(infoX, 20, infoXl/2, 20, From.BOTTOM_LEFT); } override MsgBox newMsgBoxDelete() { auto m = new MsgBox(Lang.saveBoxTitleDelete.transl); m.addMsg(Lang.saveBoxQuestionDeleteLevel.transl); m.addMsg(Lang.saveBoxLevelName.transl ~ " " ~ (_levelRecent !is null ? _levelRecent.name : fileRecent.fileNoExtNoPre)); m.addMsg(Lang.saveBoxFileName.transl ~ " " ~ fileRecent.rootless); return m; } private: void commonConstructor() { buttonPlayYFromBottom = 100f; _edit = new TextButton(new Geom(infoX + infoXl/2, 100, infoXl/2, 40, From.BOTTOM_LEFT), Lang.browserEdit.transl); _edit.hotkey = file.option.keyMenuEdit; _edit.onExecute = () { assert (fileRecent !is null); file.option.singleLastLevel = fileRecent; _gotoEditorLoadFileRecent = true; }; _newLevel = new TextButton(new Geom(infoX + infoXl/2, 60, infoXl/2, 40, From.BOTTOM_LEFT), Lang.browserNewLevel.transl); _newLevel.hotkey = file.option.keyMenuNewLevel; _newLevel.onExecute = () { file.option.singleLastLevel = currentDir.guaranteedDirOnly; _gotoEditorNewLevel = true; }; _repForLev = new TextButton(new Geom(infoX, 20 + 40, infoXl/2, 40, From.BOTTOM_LEFT), Lang.browserOpenRepForLev.transl); _repForLev.hotkey = file.option.keyMenuRepForLev; _repForLev.onExecute = () { assert (fileRecent !is null); assert (levelRecent !is null); file.option.singleLastLevel = fileRecent; _gotoRepForLev = true; }; _exportImageDone = new Label(new Geom(infoX - this.xlg/2 + infoXl/4, 40, infoXl/2, 20, From.BOTTOM), Lang.browserExportImage.transl); _exportImage = new TextButton(new Geom(infoX, 20 + 20, infoXl/2, 20, From.BOTTOM_LEFT), Lang.browserExportImage.transl); _exportImage.hotkey = file.option.keyMenuExport; _exportImage.onExecute = () { assert (fileRecent !is null); assert (levelRecent !is null); Filename imgFn = Level.exportImageFilename(fileRecent); levelRecent.exportImageTo(imgFn); _exportImage.hide(); _exportImageDone.show(); _exportImageDone.text = imgFn.stringForWriting; hardware.sound.playQuiet(Sound.DISKSAVE); }; _by = new LabelTwo(new Geom(infoX, infoY + 20, infoXl, 20), Lang.browserInfoAuthor.transl); _save = new LabelTwo(new Geom(infoX, infoY + 40, infoXl, 20), Lang.browserInfoInitgoal.transl); immutable savedXl = min(110f, infoXl/2f); _trophySaved = new LabelTwo(new Geom(infoX, infoY + 60, savedXl, 20), Lang.browserInfoBestSaved.transl); _trophySkills = new LabelTwo(new Geom(infoX + savedXl, infoY + 60, infoXl - savedXl, 20), Lang.browserInfoBestSkills.transl); addChildren(_edit, _repForLev, _exportImage, _by, _save, _trophySaved, _trophySkills, _exportImageDone, _newLevel); } }