Peoplemon  0.1.0
Peoplemon 3 game source documentation
PlaylistEditorWindow.cpp
Go to the documentation of this file.
2 
3 #include <BLIB/Audio.hpp>
4 #include <Core/Properties.hpp>
5 
6 namespace editor
7 {
8 namespace component
9 {
10 using namespace bl::gui;
11 
13 : onSelect(oscb)
14 , onCancel(occb)
15 , songPicker(core::Properties::MusicPath(), {"ogg", "wav"},
16  std::bind(&PlaylistEditorWindow::onSongPick, this, std::placeholders::_1),
17  std::bind(&PlaylistEditorWindow::closePickers, this))
18 , plistPicker(core::Properties::PlaylistPath(), {"plst"},
19  std::bind(&PlaylistEditorWindow::onPlaylistPick, this, std::placeholders::_1),
20  std::bind(&PlaylistEditorWindow::closePickers, this)) {
21  window = Window::create(LinePacker::create(LinePacker::Vertical, 4.f), "Playlist Editor");
22  window->getSignal(Event::Closed).willAlwaysCall(std::bind(&PlaylistEditorWindow::close, this));
23 
24  Box::Ptr row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
25  Button::Ptr but = Button::create("New");
26  but->getSignal(Event::LeftClicked)
27  .willAlwaysCall(std::bind(&PlaylistEditorWindow::makeNew, this));
28  row->pack(but, false, true);
29  but = Button::create("Open");
30  but->getSignal(Event::LeftClicked).willAlwaysCall([this](const Event&, Element*) {
31  settingFile = false;
32  window->setForceFocus(false);
33  plistPicker.open(FilePicker::PickExisting, "Open Playlist", gui);
34  });
35  row->pack(but, false, true);
36  but = Button::create("Set file");
37  but->getSignal(Event::LeftClicked).willAlwaysCall([this](const Event&, Element*) {
38  settingFile = true;
39  window->setForceFocus(false);
40  plistPicker.open(FilePicker::CreateOrPick, "Set Playlist File", gui);
41  });
42  row->pack(but, false, true);
43  saveBut = Button::create("Save");
44  saveBut->getSignal(Event::LeftClicked)
45  .willAlwaysCall(std::bind(&PlaylistEditorWindow::save, this));
46  row->pack(saveBut, false, true);
47  fileLabel = Label::create("<set a file>");
48  fileLabel->setColor(sf::Color(20, 230, 245), sf::Color::Transparent);
49  row->pack(fileLabel, true, true);
50  window->pack(row);
51 
52  row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
53  songList = SelectBox::create();
54  songList->setRequisition({400.f, 350.f});
55  songList->setMaxSize({400.f, 400.f});
56  row->pack(songList, true, true);
57 
58  Box::Ptr column = Box::create(LinePacker::create(LinePacker::Vertical, 6.f));
59  but = Button::create("Add Song");
60  but->getSignal(Event::LeftClicked).willAlwaysCall([this](const Event&, Element*) {
61  window->setForceFocus(false);
62  songPicker.open(FilePicker::PickExisting, "Add Song", gui);
63  });
64  column->pack(but, true, false);
65 
66  shuffleBut = CheckButton::create("Shuffle");
67  column->pack(shuffleBut);
68  loopShuffleBut = CheckButton::create("Reshuffle on loop");
69  column->pack(loopShuffleBut);
70 
71  but = Button::create("Remove");
72  but->getSignal(Event::LeftClicked)
73  .willAlwaysCall(std::bind(&PlaylistEditorWindow::removeSong, this));
74  but->setColor(sf::Color(170, 0, 0), sf::Color::Black);
75  column->pack(but);
76  row->pack(column, false, true);
77  window->pack(row, true, true);
78 
79  but = Button::create("Use Playlist");
80  but->getSignal(Event::LeftClicked)
81  .willAlwaysCall(std::bind(&PlaylistEditorWindow::select, this));
82  but->setColor(sf::Color(20, 230, 255), sf::Color::Black);
83  window->pack(but);
84 
85  markClean();
86 }
87 
88 void PlaylistEditorWindow::open(GUI* g, const std::string& p) {
89  gui = g;
90  if (!p.empty()) { load(p); }
91  else { makeNew(); }
92  gui->pack(window);
93  window->setForceFocus(true);
94 }
95 
96 void PlaylistEditorWindow::onSongPick(const std::string& song) {
97  songPicker.close();
98  window->setForceFocus(true);
99  songList->addOption(song);
100  markDirty();
101 }
102 
103 void PlaylistEditorWindow::onPlaylistPick(const std::string& p) {
104  const std::string plst = bl::util::FileUtil::getExtension(p) == "plst" ? p : p + ".plst";
105  if (settingFile) {
106  fileLabel->setText(plst);
107  markDirty();
108  }
109  else { load(plst); }
110  closePickers();
111 }
112 
113 void PlaylistEditorWindow::makeNew() {
114  if (!confirmUnsaved()) return;
115 
116  songList->clearOptions();
117  fileLabel->setText("<set a file>");
118  shuffleBut->setValue(true);
119  loopShuffleBut->setValue(false);
120  markClean();
121 }
122 
123 void PlaylistEditorWindow::markDirty() {
124  saveBut->setColor(sf::Color::Red, sf::Color::Black);
125  dirty = true;
126 }
127 
128 void PlaylistEditorWindow::markClean() {
129  saveBut->setColor(sf::Color::Red, sf::Color::Black);
130  dirty = false;
131 }
132 
133 void PlaylistEditorWindow::removeSong() {
134  const auto o = songList->getSelectedOption();
135  if (o.has_value()) { songList->removeOption(o.value()); }
136 }
137 
138 void PlaylistEditorWindow::save() {
139  bl::audio::Playlist plst;
140  plst.setShuffle(shuffleBut->getValue());
141  plst.setShuffleOnLoop(loopShuffleBut->getValue());
142 
143  std::vector<std::string> songs;
144  songList->getAllOptions(songs);
145  for (const auto& song : songs) { plst.addSong(song); }
146 
147  if (plst.saveToFile(
148  bl::util::FileUtil::joinPath(core::Properties::PlaylistPath(), fileLabel->getText()))) {
149  markClean();
150  }
151  else { bl::dialog::tinyfd_messageBox("Error", "Failed to save playlist", "ok", "error", 1); }
152 }
153 
154 void PlaylistEditorWindow::load(const std::string& file) {
155  if (!confirmUnsaved()) return;
156 
157  bl::audio::Playlist plst;
158  if (!plst.loadFromFile(bl::util::FileUtil::joinPath(core::Properties::PlaylistPath(), file))) {
159  bl::dialog::tinyfd_messageBox("Error", "Failed to load playlist", "ok", "error", 1);
160  return;
161  }
162 
163  fileLabel->setText(file);
164  songList->clearOptions();
165  for (const auto& song : plst.getSongList()) { songList->addOption(song); }
166  shuffleBut->setValue(plst.shuffling());
167  loopShuffleBut->setValue(plst.shufflingOnLoop());
168  markClean();
169 }
170 
171 void PlaylistEditorWindow::close() {
172  closePickers();
173  window->setForceFocus(false);
174  window->remove();
175  onCancel();
176 }
177 
178 void PlaylistEditorWindow::select() {
179  if (!confirmUnsaved()) return;
180 
181  if (!bl::util::FileUtil::exists(
182  bl::util::FileUtil::joinPath(core::Properties::PlaylistPath(), fileLabel->getText()))) {
183  bl::dialog::tinyfd_messageBox("Error", "Please select a playlist", "ok", "error", 1);
184  return;
185  }
186 
187  std::vector<std::string> songs;
188  songList->getAllOptions(songs);
189  if (songs.empty()) {
190  bl::dialog::tinyfd_messageBox(
191  "Error", "Please add at least one song mate", "ok", "error", 1);
192  return;
193  }
194 
195  close();
196  onSelect(fileLabel->getText());
197 }
198 
199 void PlaylistEditorWindow::closePickers() {
200  songPicker.close();
201  plistPicker.close();
202  window->setForceFocus(true);
203 }
204 
205 bool PlaylistEditorWindow::confirmUnsaved() {
206  if (dirty) {
207  return 1 == bl::dialog::tinyfd_messageBox(
208  "Warning", "Discard unsaved changes", "yesno", "warning", 0);
209  }
210  return true;
211 }
212 
213 } // namespace component
214 } // namespace editor
Core classes and functionality for both the editor and game.
All classes and functionality used for implementing the game editor.
Definition: Tile.hpp:11
static const std::string & PlaylistPath()
Definition: Properties.cpp:321
PlaylistEditorWindow(const SelectedCb &onSelect, const CancelCb &onCancel)
Creates the playlist editor.
void open(bl::gui::GUI *gui, const std::string &plist)
Opens the window with an optional file to load.
std::function< void(const std::string &)> SelectedCb