Vital
Loading...
Searching...
No Matches
save_section.cpp
Go to the documentation of this file.
1#include "save_section.h"
2
3#include "skin.h"
4#include "fonts.h"
5#include "load_save.h"
7#include "synth_strings.h"
8
9class FileNameInputFilter : public TextEditor::InputFilter {
10 public:
11 FileNameInputFilter() : TextEditor::InputFilter() { }
12
13 String filterNewText(TextEditor& editor, const String& new_input) override {
14 return new_input.removeCharacters("<>?*/|\\[]\":");
15 }
16};
17
18SaveSection::SaveSection(String name) : Overlay(name), overwrite_(false), saving_preset_(true),
19 body_(Shaders::kRoundedRectangleFragment) {
20 addOpenGlComponent(&body_);
21
22#if !defined(NO_TEXT_ENTRY)
23 name_ = std::make_unique<OpenGlTextEditor>("Name");
24 name_->addListener(this);
25 name_->setInputFilter(new FileNameInputFilter(), true);
26 addAndMakeVisible(name_.get());
27 addOpenGlComponent(name_->getImageComponent());
28
29 author_ = std::make_unique<OpenGlTextEditor>("Author");
30 author_->addListener(this);
31 author_->setText(LoadSave::getAuthor());
32 addAndMakeVisible(author_.get());
33 addOpenGlComponent(author_->getImageComponent());
34
35 comments_ = std::make_unique<OpenGlTextEditor>("Comments");
36 comments_->addListener(this);
37 comments_->setReturnKeyStartsNewLine(true);
38 comments_->setInputRestrictions(LoadSave::kMaxCommentLength);
39 addAndMakeVisible(comments_.get());
40 addOpenGlComponent(comments_->getImageComponent());
41 comments_->setMultiLine(true);
42#endif
43
44 save_button_ = std::make_unique<OpenGlToggleButton>(TRANS("Save"));
45 save_button_->setButtonText("Save");
46 save_button_->setUiButton(true);
47 save_button_->addListener(this);
48 addAndMakeVisible(save_button_.get());
49 addOpenGlComponent(save_button_->getGlComponent());
50
51 overwrite_button_ = std::make_unique<OpenGlToggleButton>(TRANS("Overwrite"));
52 overwrite_button_->setButtonText("Overwrite");
53 overwrite_button_->setUiButton(true);
54 overwrite_button_->addListener(this);
55 addAndMakeVisible(overwrite_button_.get());
56 addOpenGlComponent(overwrite_button_->getGlComponent());
57
58 cancel_button_ = std::make_unique<OpenGlToggleButton>(TRANS("Cancel"));
59 cancel_button_->setButtonText("Cancel");
60 cancel_button_->setUiButton(false);
61 cancel_button_->addListener(this);
62 addAndMakeVisible(cancel_button_.get());
63 addOpenGlComponent(cancel_button_->getGlComponent());
64
65 preset_text_ = std::make_unique<PlainTextComponent>("Preset", "NAME");
66 addOpenGlComponent(preset_text_.get());
67 preset_text_->setFontType(PlainTextComponent::kLight);
68 preset_text_->setTextSize(kLabelHeight * size_ratio_);
69 preset_text_->setJustification(Justification::centredRight);
70
71 author_text_ = std::make_unique<PlainTextComponent>("Author", "AUTHOR");
72 addOpenGlComponent(author_text_.get());
73 author_text_->setFontType(PlainTextComponent::kLight);
74 author_text_->setTextSize(kLabelHeight * size_ratio_);
75 author_text_->setJustification(Justification::centredRight);
76
77 style_text_ = std::make_unique<PlainTextComponent>("Style", "STYLE");
78 addOpenGlComponent(style_text_.get());
79 style_text_->setFontType(PlainTextComponent::kLight);
80 style_text_->setTextSize(kLabelHeight * size_ratio_);
81 style_text_->setJustification(Justification::centredRight);
82
83 comments_text_ = std::make_unique<PlainTextComponent>("Comments", "COMMENTS");
84 addOpenGlComponent(comments_text_.get());
85 comments_text_->setFontType(PlainTextComponent::kLight);
86 comments_text_->setTextSize(kLabelHeight);
87 comments_text_->setJustification(Justification::centredRight);
88
89 overwrite_text_ = std::make_unique<PlainTextComponent>("overwrite", "Overwrite existing file?");
90 addOpenGlComponent(overwrite_text_.get());
91 overwrite_text_->setFontType(PlainTextComponent::kLight);
92 overwrite_text_->setTextSize(kLabelHeight);
93 overwrite_text_->setJustification(Justification::centred);
94
95 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i) {
96 style_buttons_[i] = std::make_unique<OpenGlToggleButton>(strings::kPresetStyleNames[i]);
97 style_buttons_[i]->addListener(this);
98 addAndMakeVisible(style_buttons_[i].get());
99 addOpenGlComponent(style_buttons_[i]->getGlComponent());
100 }
101}
102
105 body_.setColor(findColour(Skin::kBody, true));
106
107 Colour text_color = findColour(Skin::kBodyText, true);
108 preset_text_->setColor(text_color);
109 author_text_->setColor(text_color);
110 style_text_->setColor(text_color);
111 comments_text_->setColor(text_color);
112 overwrite_text_->setColor(text_color);
113
115
116 if (overwrite_)
118 else
120
121 if (name_) {
122 name_->redoImage();
123 author_->redoImage();
124 comments_->redoImage();
125 }
126
127 float label_height = kLabelHeight * size_ratio_;
128 preset_text_->setTextSize(label_height);
129 author_text_->setTextSize(label_height);
130 comments_text_->setTextSize(label_height);
131 style_text_->setTextSize(label_height);
132 overwrite_text_->setTextSize(label_height);
133}
134
136 Rectangle<int> save_rect = getSaveRect();
137 body_.setBounds(save_rect);
138 int padding_x = size_ratio_ * kPaddingX;
139 int padding_y = size_ratio_ * kPaddingX;
140 int style_padding_x = size_ratio_ * kStylePaddingX;
141 int style_padding_y = size_ratio_ * kStylePaddingY;
142 int division = size_ratio_ * kDivision;
143 int extra_top_padding = size_ratio_ * kExtraTopPadding;
144 int button_height = size_ratio_ * kButtonHeight;
145 int style_button_height = size_ratio_ * kStyleButtonHeight;
146
147 save_button_->setVisible(true);
148 overwrite_button_->setVisible(false);
149 float button_width = (save_rect.getWidth() - 3 * padding_x) / 2.0f;
150 save_button_->setBounds(save_rect.getX() + button_width + 2 * padding_x,
151 save_rect.getBottom() - padding_y - button_height,
152 button_width, button_height);
153 cancel_button_->setBounds(save_rect.getX() + padding_x,
154 save_rect.getBottom() - padding_y - button_height,
155 button_width, button_height);
156
157 int text_x = save_rect.getX() + padding_x;
158 int text_y = save_rect.getY() + extra_top_padding;
159
160 preset_text_->setVisible(true);
161 author_text_->setVisible(true);
162 style_text_->setVisible(saving_preset_);
163 comments_text_->setVisible(saving_preset_);
164 overwrite_text_->setVisible(false);
165
166 if (name_ == nullptr || author_ == nullptr || comments_ == nullptr)
167 return;
168
169 name_->setVisible(true);
170 author_->setVisible(true);
171 comments_->setVisible(saving_preset_);
172 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i)
173 style_buttons_[i]->setVisible(saving_preset_);
174
175 int editor_height = kTextEditorHeight * size_ratio_;
176 int editor_x = save_rect.getX() + padding_x + division;
177 int editor_width = save_rect.getWidth() - 2 * padding_x - division;
178 name_->setBounds(editor_x, save_rect.getY() + padding_y + extra_top_padding,
179 editor_width, editor_height);
180 author_->setBounds(editor_x, save_rect.getY() + 2 * padding_y + editor_height + extra_top_padding,
181 editor_width, editor_height);
182
183 int style_width = editor_width + style_padding_x;
184 int style_y = save_rect.getY() + 3 * padding_y + 2 * editor_height + extra_top_padding;
185 int num_in_row = LoadSave::kNumPresetStyles / 3;
186 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i) {
187 int column = i % num_in_row;
188 int x = editor_x + (style_width * column) / num_in_row;
189 int next_x = editor_x + (style_width * (column + 1)) / num_in_row;
190 int width = next_x - x - style_padding_x;
191 int y = style_y + (i / num_in_row) * (style_button_height + style_padding_y);
192 style_buttons_[i]->setBounds(x, y, width, style_button_height);
193 }
194
195 int comments_y = style_y + 3 * style_button_height + 2 * style_padding_y + padding_y;
196 int comments_height = save_button_->getY() - comments_y - padding_y;
197 comments_->setBounds(editor_x, comments_y, editor_width, comments_height);
198
199 float text_width = division - 10 * size_ratio_;
200 preset_text_->setBounds(text_x, text_y + padding_y, text_width, name_->getHeight());
201 author_text_->setBounds(text_x, text_y + 2 * padding_y + name_->getHeight(),
202 text_width, name_->getHeight());
203
204 int style_height = 3 * style_button_height + 2 * style_padding_y;
205 style_text_->setBounds(text_x, text_y + 3 * padding_y + 2 * name_->getHeight(),
206 text_width, style_height);
207 comments_text_->setBounds(text_x, text_y + 4 * padding_y + style_height + 2 * name_->getHeight(),
208 text_width, author_->getHeight());
209
210 Font editor_font = Fonts::instance()->proportional_light().withPointHeight(editor_height * 0.6f);
211 setTextColors(name_.get(), file_type_ + " " + TRANS("Name"));
212 setTextColors(author_.get(), TRANS("Author"));
213 setTextColors(comments_.get(), TRANS("Comments"));
214 name_->applyFontToAllText(editor_font, true);
215 author_->applyFontToAllText(editor_font, true);
216 comments_->applyFontToAllText(editor_font, true);
217}
218
220 preset_text_->setVisible(false);
221 author_text_->setVisible(false);
222 style_text_->setVisible(false);
223 comments_text_->setVisible(false);
224 overwrite_text_->setVisible(true);
225 name_->setVisible(false);
226 author_->setVisible(false);
227 comments_->setVisible(false);
228
229 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i)
230 style_buttons_[i]->setVisible(false);
231
232 Rectangle<int> overwrite_rect = getOverwriteRect();
233 body_.setBounds(overwrite_rect);
234
235 save_button_->setVisible(false);
236 overwrite_button_->setVisible(true);
237
238 overwrite_text_->setText(String("Overwrite existing file?"));
239 int padding_x = kPaddingX * size_ratio_;
240 int padding_y = kPaddingY * size_ratio_;
241 int button_height = kButtonHeight * size_ratio_;
242 overwrite_text_->setBounds(overwrite_rect.getX() + padding_x,
243 overwrite_rect.getY() + (kExtraTopPadding + 24) * size_ratio_,
244 overwrite_rect.getWidth() - 2 * padding_x, 24 * size_ratio_);
245 overwrite_text_->redrawImage(true);
246
247 float button_width = (overwrite_rect.getWidth() - 3 * padding_x) / 2.0f;
248 cancel_button_->setBounds(overwrite_rect.getX() + padding_x,
249 overwrite_rect.getBottom() - padding_y - button_height,
250 button_width, button_height);
251 overwrite_button_->setBounds(overwrite_rect.getX() + button_width + 2 * padding_x,
252 overwrite_rect.getBottom() - padding_y - button_height,
253 button_width, button_height);
254}
255
256void SaveSection::setTextColors(OpenGlTextEditor* editor, String empty_string) {
257 editor->setColour(CaretComponent::caretColourId, findColour(Skin::kTextEditorCaret, true));
258 editor->setColour(TextEditor::textColourId, findColour(Skin::kPresetText, true));
259 editor->setColour(TextEditor::highlightedTextColourId, findColour(Skin::kBodyText, true));
260 editor->setColour(TextEditor::highlightColourId, findColour(Skin::kTextEditorSelection, true));
261 Colour empty_color = findColour(Skin::kBodyText, true);
262 empty_color = empty_color.withAlpha(0.5f * empty_color.getFloatAlpha());
263 editor->setTextToShowWhenEmpty(empty_string, empty_color);
264 editor->redoImage();
265}
266
267void SaveSection::setVisible(bool should_be_visible) {
268 overwrite_ = false;
269
270 if (should_be_visible) {
272 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
273 if (parent && name_) {
274 name_->setText(parent->getSynth()->getPresetName());
275 comments_->setText(parent->getSynth()->getComments());
276 String style = parent->getSynth()->getStyle();
277 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i)
278 style_buttons_[i]->setToggleState(style == String(strings::kPresetStyleNames[i]), dontSendNotification);
279 }
280 }
281
282 Image image(Image::ARGB, 1, 1, false);
283 Graphics g(image);
285
286 Overlay::setVisible(should_be_visible);
287
288 if (name_ && name_->isShowing())
289 name_->grabKeyboardFocus();
290}
291
292void SaveSection::mouseUp(const MouseEvent &e) {
293 if (!getSaveRect().contains(e.getPosition()))
294 setVisible(false);
295}
296
298 save();
299}
300
301void SaveSection::buttonClicked(Button* clicked_button) {
302 if (clicked_button == save_button_.get() || clicked_button == overwrite_button_.get())
303 save();
304 else if (clicked_button == cancel_button_.get())
305 setVisible(false);
306 else {
307 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i) {
308 if (style_buttons_[i].get() != clicked_button)
309 style_buttons_[i]->setToggleState(false, dontSendNotification);
310 }
311 }
312}
313
314Rectangle<int> SaveSection::getSaveRect() {
315 int save_width = kSaveWidth * size_ratio_;
316 int save_height = kSavePresetHeight * size_ratio_;
317 if (!saving_preset_)
319
320 int x = (getWidth() - save_width) / 2;
321 int y = (getHeight() - save_height) / 2;
322 return Rectangle<int>(x, y, save_width, save_height);
323}
324
326 int x = (getWidth() - kOverwriteWidth * size_ratio_) / 2;
327 int y = (getHeight() - kOverwriteHeight * size_ratio_) / 2;
328 return Rectangle<int>(x, y, kOverwriteWidth * size_ratio_, kOverwriteHeight * size_ratio_);
329}
330
331void SaveSection::save() {
332 if (name_ == nullptr || name_->getText().trim() == "")
333 return;
334
335 String file_name = name_->getText().trim() + String(".") + file_extension_;
336 File save_file = file_directory_.getChildFile(File::createLegalFileName(file_name));
337 if (!overwrite_ && save_file.exists()) {
338 overwrite_ = true;
340 repaint();
341 return;
342 }
343
344 if (saving_preset_) {
345 LoadSave::saveAuthor(author_->getText().trim().toStdString());
346 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
347 if (parent) {
348 parent->getSynth()->setAuthor(author_->getText().trim().removeCharacters("\""));
349 parent->getSynth()->setComments(comments_->getText().trim().removeCharacters("\""));
350 String style = "";
351 for (int i = 0; i < LoadSave::kNumPresetStyles; ++i) {
352 if (style_buttons_[i]->getToggleState())
353 style = style_buttons_[i]->getName();
354 }
355 parent->getSynth()->setStyle(style.removeCharacters("\""));
356 parent->getSynth()->saveToFile(save_file);
357
358 for (Listener* listener : listeners_)
359 listener->save(save_file);
360 }
361 }
362 else {
363 file_data_["name"] = name_->getText().trim().toStdString();
364 file_data_["author"] = author_->getText().trim().toStdString();
365 save_file.replaceWithText(file_data_.dump());
366 for (Listener* listener : listeners_)
367 listener->save(save_file);
368 }
369 setVisible(false);
370}
Definition save_section.cpp:9
FileNameInputFilter()
Definition save_section.cpp:11
String filterNewText(TextEditor &editor, const String &new_input) override
Definition save_section.cpp:13
Font & proportional_light()
Returns a reference to the proportional light font.
Definition fonts.h:28
static Fonts * instance()
Gets the singleton instance of the Fonts class.
Definition fonts.h:52
static void saveAuthor(std::string author)
Saves the provided author name to the config.
Definition load_save.cpp:1261
@ kNumPresetStyles
Definition load_save.h:66
static std::string getAuthor()
Retrieves the saved author name from the config.
Definition load_save.cpp:1671
static const int kMaxCommentLength
Maximum length of preset comments.
Definition load_save.h:70
virtual void redoImage()
Redraws the image after a state change.
Definition open_gl_image_component.h:196
force_inline void setColor(Colour color)
Sets the base color for the quads.
Definition open_gl_multi_quad.h:102
void setRounding(float rounding)
Sets the rounding radius of the quads.
Definition open_gl_multi_quad.h:347
A text editor that uses an OpenGlImageComponent for rendering and updates the image on text changes.
Definition open_gl_image_component.h:209
A SynthSection that displays an overlay with a background and optional listeners.
Definition overlay.h:180
virtual void resized() override
Called when the overlay is resized. Updates background color and size.
Definition overlay.h:237
void setVisible(bool should_be_visible) override
Sets the visibility of the overlay and notifies listeners.
Definition overlay.h:224
float size_ratio_
A scaling factor for the overlay size.
Definition overlay.h:267
@ kLight
Definition open_gl_image_component.h:309
Rectangle< int > getOverwriteRect()
Gets the rectangle bounds of the overwrite confirmation dialog.
Definition save_section.cpp:325
void mouseUp(const MouseEvent &e) override
Called when the mouse is released. Used to close the overlay if clicked outside.
Definition save_section.cpp:292
static constexpr int kPaddingX
Horizontal padding inside the dialog.
Definition save_section.h:35
static constexpr int kButtonHeight
Height of buttons.
Definition save_section.h:32
static constexpr int kOverwriteWidth
Width of overwrite confirmation dialog.
Definition save_section.h:28
static constexpr int kSaveWidth
Base width of the save dialog.
Definition save_section.h:23
void setTextColors(OpenGlTextEditor *editor, String empty_string)
Configures text editor colors and placeholder text.
Definition save_section.cpp:256
void resized() override
Called when the component is resized. Updates layout and positions of all elements.
Definition save_section.cpp:103
static constexpr int kExtraTopPadding
Extra top padding inside the dialog.
Definition save_section.h:37
void setSaveBounds()
Sets the layout and components for the normal save mode (not overwrite).
Definition save_section.cpp:135
static constexpr int kSavePresetHeight
Base height of the preset save dialog.
Definition save_section.h:24
SaveSection(String name)
Constructs a SaveSection with a given name.
Definition save_section.cpp:18
void buttonClicked(Button *clicked_button) override
Called when a button is clicked.
Definition save_section.cpp:301
static constexpr int kStylePaddingY
Vertical padding for style buttons.
Definition save_section.h:26
void setVisible(bool should_be_visible) override
Sets the visibility of this overlay. Adjusts layout when becoming visible.
Definition save_section.cpp:267
void textEditorReturnKeyPressed(TextEditor &editor) override
Called when the return key is pressed in any text editor.
Definition save_section.cpp:297
static constexpr int kOverwriteHeight
Height of overwrite confirmation dialog.
Definition save_section.h:29
static constexpr int kPaddingY
Vertical padding inside the dialog.
Definition save_section.h:36
static constexpr int kTextEditorHeight
Height of each text editor component.
Definition save_section.h:30
void setOverwriteBounds()
Sets the layout and components for the overwrite confirmation mode.
Definition save_section.cpp:219
static constexpr int kStyleButtonHeight
Height of each style button.
Definition save_section.h:27
Rectangle< int > getSaveRect()
Gets the rectangle bounds of the main save dialog.
Definition save_section.cpp:314
static constexpr int kStylePaddingX
Horizontal padding for style buttons.
Definition save_section.h:25
static constexpr int kLabelHeight
Height of labels.
Definition save_section.h:31
static constexpr int kDivision
Horizontal division for layout.
Definition save_section.h:34
Manages and provides access to vertex and fragment shaders used by the OpenGL rendering pipeline.
Definition shaders.h:19
@ kBodyRounding
Definition skin.h:71
@ kBodyText
Definition skin.h:133
@ kPresetText
Definition skin.h:132
@ kTextEditorSelection
Definition skin.h:203
@ kTextEditorCaret
Definition skin.h:202
@ kBody
Definition skin.h:129
void setAuthor(const String &author)
Sets the author metadata of the current preset.
Definition synth_base.cpp:681
void setComments(const String &comments)
Sets the comments or description metadata of the current preset.
Definition synth_base.cpp:685
bool saveToFile(File preset)
Saves the current preset state to the specified file.
Definition synth_base.cpp:531
void setStyle(const String &style)
Sets the style metadata of the current preset (e.g., bass, lead, etc.).
Definition synth_base.cpp:689
String getComments()
Gets the comments for the current preset.
Definition synth_base.cpp:705
String getPresetName()
Gets the current preset’s name.
Definition synth_base.cpp:713
String getStyle()
Gets the style of the current preset.
Definition synth_base.cpp:709
An interface class linking the Vital synthesizer backend (SynthBase) with a GUI.
Definition synth_gui_interface.h:56
SynthBase * getSynth()
Returns the SynthBase instance this interface is managing.
Definition synth_gui_interface.h:85
void paintOpenGlChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all OpenGL child components.
Definition synth_section.cpp:267
float findValue(Skin::ValueId value_id) const
Finds a value in the skin overrides or from the parent if not found locally.
Definition synth_section.cpp:18
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
const std::string kPresetStyleNames[]
Names for preset categories or styles.
Definition synth_strings.h:81