16  template<
class Comparator>
 
   17  void sortFileArray(Array<File>& file_array) {
 
   18    Comparator comparator;
 
   19    file_array.sort(comparator, 
true);
 
   22  template<
class Comparator>
 
   23  void sortFileArrayWithCache(Array<File>& file_array, 
PresetInfoCache* cache) {
 
   24    Comparator comparator(cache);
 
   25    file_array.sort(comparator, 
true);
 
   28  const std::string kPresetStoreUrl = 
"";
 
   30  class FileNameFilter : 
public TextEditor::InputFilter {
 
   32      FileNameFilter() : TextEditor::InputFilter() { }
 
   34      String filterNewText(TextEditor& editor, 
const String& new_input)
 override {
 
   35        return new_input.removeCharacters(
"<>?*/|\\[]\":");
 
   41    num_view_presets_(0), hover_preset_(-1), click_preset_(-1), cache_position_(0),
 
   42    highlight_(
Shaders::kColorFragment), hover_(
Shaders::kColorFragment),
 
   43    view_position_(0), sort_column_(kName), sort_ascending_(true) {
 
   44  addAndMakeVisible(browse_area_);
 
   45  browse_area_.setInterceptsMouseClicks(
false, 
false);
 
   49  scroll_bar_ = std::make_unique<OpenGlScrollBar>();
 
   50  addAndMakeVisible(scroll_bar_.get());
 
   52  scroll_bar_->addListener(
this);
 
   54#if !defined(NO_TEXT_ENTRY) 
   55  rename_editor_ = std::make_unique<OpenGlTextEditor>(
"Search");
 
   56  rename_editor_->addListener(
this);
 
   57  rename_editor_->setSelectAllWhenFocused(
true);
 
   58  rename_editor_->setMultiLine(
false, 
false);
 
   59  rename_editor_->setJustification(Justification::centredLeft);
 
   60  rename_editor_->setInputFilter(
new FileNameFilter(), 
true);
 
   61  addChildComponent(rename_editor_.get());
 
 
   82  int text_padding = row_height / 2;
 
   86  g.reduceClipRegion(getLocalBounds().removeFromTop(title_width));
 
   87  Rectangle<float> top = getLocalBounds().toFloat().removeFromTop(title_width * 2.0f);
 
   92  scroll_bar_->setColor(lighten);
 
   94  g.fillRect(star_width, 0, 1, title_width);
 
   95  g.fillRect(star_width + name_width, 0, 1, title_width);
 
   96  g.fillRect(star_width + name_width + style_width, 0, 1, title_width);
 
   97  g.fillRect(getWidth() - date_width, 0, 1, title_width);
 
  100  g.setFont(
Fonts::instance()->proportional_regular().withPointHeight(title_width * 0.5f));
 
  103  float star_draw_width = title_width * 0.8f;
 
  104  float star_y = (title_width - star_draw_width) / 2.0f;
 
  105  Rectangle<float> star_bounds((star_width - star_draw_width) / 2.0f, star_y, star_draw_width, star_draw_width);
 
  106  g.fillPath(star, star.getTransformToScaleToFit(star_bounds, 
true));
 
  108  g.drawText(
"Name", text_padding + star_width, 0, name_width, title_width, Justification::centredLeft);
 
  109  int style_x = star_width + name_width + text_padding;
 
  110  g.drawText(
"Style", style_x, 0, style_width, title_width, Justification::centredLeft);
 
  111  int author_x = star_width + name_width + text_padding + style_width;
 
  112  g.drawText(
"Author", author_x, 0, author_width, title_width, Justification::centredLeft);
 
  113  g.drawText(
"Date", getWidth() - date_width, 0, date_width - text_padding, title_width, Justification::centredRight);
 
  116  setWantsKeyboardFocus(
true);
 
  117  setMouseClickGrabsKeyboardFocus(
true);
 
 
  121  static constexpr float kScrollBarWidth = 15.0f;
 
  123  int scroll_bar_width = kScrollBarWidth * 
getSizeRatio();
 
  125  int scroll_bar_height = getHeight() - title_width;
 
  126  scroll_bar_->setBounds(getWidth() - scroll_bar_width, title_width, scroll_bar_width, scroll_bar_height);
 
  129  browse_area_.setBounds(0, title_width, getWidth(), getHeight() - title_width);
 
 
  132void PresetList::sort() {
 
  133  if (sort_column_ == 
kStar && sort_ascending_)
 
  134    sortFileArray<FavoriteAscendingComparator>(presets_);
 
  135  else if (sort_column_ == 
kStar && !sort_ascending_)
 
  136    sortFileArray<FavoriteDescendingComparator>(presets_);
 
  137  else if (sort_column_ == 
kName && sort_ascending_)
 
  138    sortFileArray<FileNameAscendingComparator>(presets_);
 
  139  else if (sort_column_ == 
kName && !sort_ascending_)
 
  140    sortFileArray<FileNameDescendingComparator>(presets_);
 
  141  else if (sort_column_ == 
kAuthor && sort_ascending_)
 
  142    sortFileArrayWithCache<AuthorAscendingComparator>(presets_, &preset_info_cache_);
 
  143  else if (sort_column_ == 
kAuthor && !sort_ascending_)
 
  144    sortFileArrayWithCache<AuthorDescendingComparator>(presets_, &preset_info_cache_);
 
  145  else if (sort_column_ == 
kStyle && sort_ascending_)
 
  146    sortFileArrayWithCache<StyleAscendingComparator>(presets_, &preset_info_cache_);
 
  147  else if (sort_column_ == 
kStyle && !sort_ascending_)
 
  148    sortFileArrayWithCache<StyleDescendingComparator>(presets_, &preset_info_cache_);
 
  149  else if (sort_column_ == 
kDate && sort_ascending_)
 
  150    sortFileArray<FileDateAscendingComparator>(presets_);
 
  151  else if (sort_column_ == 
kDate && !sort_ascending_)
 
  152    sortFileArray<FileDateDescendingComparator>(presets_);
 
  154  filter(filter_string_, filter_styles_);
 
  165  view_position_ = std::max(0.0f, view_position_);
 
  167  float scaled_height = getHeight() - title_width;
 
  169  view_position_ = std::min(view_position_, 1.0f * scrollable_range - scaled_height);
 
  170  viewPositionChanged();
 
 
  178  return floorf((mouse_position + getViewPosition() - title_width) / 
getRowHeight());
 
 
  183  if (hover_preset_ >= filtered_presets_.size())
 
 
  192  if (click_preset_ < 0 || click_preset_ >= filtered_presets_.size())
 
  195  File preset = filtered_presets_[click_preset_];
 
  197    preset.revealToUser();
 
  198  else if (result == 
kRename && rename_editor_) {
 
  199    renaming_preset_ = preset;
 
  203    rename_editor_->setColour(TextEditor::textColourId, findColour(
Skin::kBodyText, 
true));
 
  204    rename_editor_->setColour(TextEditor::highlightedTextColourId, findColour(
Skin::kBodyText, 
true));
 
  206    rename_editor_->setText(renaming_preset_.getFileNameWithoutExtension());
 
  207    rename_editor_->setVisible(
true);
 
  208    rename_editor_->grabKeyboardFocus();
 
  209    rename_editor_->selectAll();
 
  212    for (
Listener* listener : listeners_)
 
  213      listener->deleteRequested(preset);
 
 
  218  float click_y_position = e.position.y;
 
  221  if (row >= 0 && hover_preset_ >= 0) {
 
  222    click_preset_ = hover_preset_;
 
  226    File preset = filtered_presets_[click_preset_];
 
  227    if (preset.exists() && preset.hasWriteAccess()) {
 
  232    showPopupSelector(
this, e.getPosition(), options, [=](
int selection) { respondToMenuCallback(selection); });
 
 
  238  float click_y_position = e.position.y;
 
  239  float click_x_position = e.position.x;
 
  243  if (click_y_position <= title_width) {
 
  249    if (click_x_position < star_right)
 
  250      clicked_column = 
kStar;
 
  251    else if (click_x_position < name_right)
 
  252      clicked_column = 
kName;
 
  253    else if (click_x_position < style_right)
 
  255    else if (click_x_position < author_right)
 
  258      clicked_column = 
kDate;
 
  260    if (clicked_column == sort_column_)
 
  261      sort_ascending_ = !sort_ascending_;
 
  263      sort_ascending_ = 
true;
 
  264    sort_column_ = clicked_column;
 
  268  else if (row < filtered_presets_.size() && row >= 0) {
 
  269    File preset = filtered_presets_[row];
 
  270    if (click_x_position < star_right) {
 
  271      std::string path = preset.getFullPathName().toStdString();
 
  272      if (favorites_.count(path)) {
 
  273        favorites_.erase(path);
 
  277        favorites_.insert(path);
 
  283      selected_preset_ = preset;
 
  285      for (
Listener* listener : listeners_)
 
  286        listener->newPresetSelected(preset);
 
 
  292  if (e.mods.isPopupMenu())
 
 
  299  if (renaming_preset_.exists())
 
 
  304  if (renaming_preset_.exists())
 
 
  309  rename_editor_->setVisible(
false);
 
 
  313  view_position_ = range_start;
 
  314  viewPositionChanged();
 
 
  318  static constexpr float kScrollStepRatio = 0.05f;
 
  321  float scaled_height = getHeight() - title_width;
 
  323  scroll_bar_->setCurrentRange(getViewPosition(), scaled_height, dontSendNotification);
 
  324  scroll_bar_->setSingleStepSize(scroll_bar_->getHeight() * kScrollStepRatio);
 
  325  scroll_bar_->cancelPendingUpdate();
 
 
  329  String text = rename_editor_->getText();
 
  330  rename_editor_->setVisible(
false);
 
  331  if (text.trim().isEmpty() || !renaming_preset_.exists())
 
  334  File parent = renaming_preset_.getParentDirectory();
 
  335  File new_file = parent.getChildFile(text + renaming_preset_.getFileExtension());
 
  336  renaming_preset_.moveFileTo(new_file);
 
  337  renaming_preset_ = File();
 
 
  344  if (current_folder_.exists() && current_folder_.isDirectory())
 
 
  353  int num_presets = 
static_cast<int>(filtered_presets_.size());
 
  354  if (num_presets == 0)
 
  358  selected_preset_ = filtered_presets_[new_index];
 
  359  for (
Listener* listener : listeners_)
 
  360    listener->newPresetSelected(selected_preset_);
 
 
  364  if (getWidth() <= 0 || getHeight() <= 0)
 
  367  int max = 
static_cast<int>(filtered_presets_.size()) - 
kNumCachedRows;
 
  368  int position = std::max(0, std::min<int>(cache_position_, max));
 
 
  373  filter_string_ = filter_string.toLowerCase();
 
  374  filter_styles_ = styles;
 
  376  tokens.addTokens(filter_string_, 
" ", 
"");
 
  377  filtered_presets_.clear();
 
  379  for (
const File& preset : presets_) {
 
  381    std::string path = preset.getFullPathName().toStdString();
 
  382    if (!styles.empty()) {
 
  383      std::string style = preset_info_cache_.
getStyle(preset);
 
  384      if (styles.count(style) == 0)
 
  387    if (match && tokens.size()) {
 
  388      String name = preset.getFileNameWithoutExtension().toLowerCase();
 
  389      String author = String(preset_info_cache_.
getAuthor(preset)).toLowerCase();
 
  391      for (
const String& token : tokens) {
 
  392        if (!name.contains(token) && !author.contains(token))
 
  397      filtered_presets_.push_back(preset);
 
  399  num_view_presets_ = 
static_cast<int>(filtered_presets_.size());
 
 
  405  for (
int i = 0; i < filtered_presets_.size(); ++i) {
 
  406    if (selected_preset_ == filtered_presets_[i])
 
 
  415  int presets_height = row_height * 
static_cast<int>(filtered_presets_.size());
 
  416  return std::max(presets_height, getHeight() - title_width);
 
 
  422    rows_[i].
init(open_gl);
 
  426  highlight_.
init(open_gl);
 
  427  hover_.
init(open_gl);
 
 
  431void PresetList::viewPositionChanged() {
 
  434  int last_cache_position = cache_position_;
 
  435  cache_position_ = getViewPosition() / row_height;
 
  436  int max = 
static_cast<int>(filtered_presets_.size() - 
kNumCachedRows);
 
  437  cache_position_ = std::max(0, std::min<int>(cache_position_, max));
 
  439  if (std::abs(cache_position_ - last_cache_position) >= 
kNumCachedRows)
 
  441  else if (last_cache_position < cache_position_)
 
  443  else if (last_cache_position > cache_position_)
 
  444    loadBrowserCache(cache_position_, last_cache_position);
 
  447void PresetList::loadBrowserCache(
int start_index, 
int end_index) {
 
  450  int image_width = getWidth() * mult;
 
  452  int text_padding = row_height / 2.0f;
 
  453  int star_x = text_padding;
 
  455  int name_x = star_x + star_width;
 
  457  int style_x = name_x + name_width;
 
  459  int author_x = style_x + style_width;
 
  462  int date_x = image_width - date_width + text_padding;
 
  464  end_index = std::min(
static_cast<int>(filtered_presets_.size()), end_index);
 
  468  float star_draw_width = row_height * 0.8f;
 
  469  float star_y = (row_height - star_draw_width) / 2.0f;
 
  470  Rectangle<float> star_bounds((star_width - star_draw_width) / 2.0f, star_y, star_draw_width, star_draw_width);
 
  471  star.applyTransform(star.getTransformToScaleToFit(star_bounds, 
true));
 
  472  PathStrokeType star_stroke(1.0f, PathStrokeType::curved);
 
  475  Colour star_unselected = text_color.withMultipliedAlpha(0.5f);
 
  478  for (
int i = start_index; i < end_index; ++i) {
 
  479    Image row_image(Image::ARGB, image_width, row_height, 
true);
 
  480    Graphics g(row_image);
 
  482    File preset = filtered_presets_[i];
 
  483    String name = preset.getFileNameWithoutExtension();
 
  484    String author = preset_info_cache_.
getAuthor(preset);
 
  485    String style = preset_info_cache_.
getStyle(preset);
 
  486    if (!style.isEmpty())
 
  487      style = style.substring(0, 1).toUpperCase() + style.substring(1);
 
  488    String date = preset.getCreationTime().toString(
true, 
false, 
false);
 
  490    if (favorites_.count(preset.getFullPathName().toStdString())) {
 
  491      g.setColour(star_selected);
 
  495      g.setColour(star_unselected);
 
  497    g.strokePath(star, star_stroke);
 
  499    g.setColour(text_color);
 
  501    g.drawText(name, name_x, 0, name_width   - 2 * text_padding, row_height, Justification::centredLeft, 
true);
 
  502    g.drawText(style, style_x, 0, style_width - 2 * text_padding, row_height, Justification::centredLeft, 
true);
 
  503    g.drawText(author, author_x, 0, author_width - 2 * text_padding, row_height, Justification::centredLeft, 
true);
 
  504    g.drawText(date, date_x, 0, date_width - 2 * text_padding, row_height, Justification::centredRight, 
true);
 
  510void PresetList::moveQuadToRow(
OpenGlQuad& quad, 
int row, 
float y_offset) {
 
  513  float open_gl_row_height = 2.0f * row_height / view_height;
 
  514  float offset = row * open_gl_row_height;
 
  516  float y = 1.0f + y_offset - offset;
 
  517  quad.
setQuad(0, -1.0f, y - open_gl_row_height, 2.0f, open_gl_row_height);
 
  522  float view_height = getHeight() - title_width;
 
  524  int num_presets = num_view_presets_;
 
  526  int view_position = getViewPosition();
 
  527  float y_offset = 2.0f * view_position / view_height;
 
  529  Rectangle<int> view_bounds(0, title_width, getWidth(), getHeight() - title_width);
 
  534  float width_ratio = image_width / getWidth();
 
  535  float height_ratio = image_height / row_height;
 
  537  float open_gl_row_height = height_ratio * 2.0f * row_height / view_height;
 
  538  int cache_position = std::max(0, std::min(cache_position_, num_presets - 
kNumCachedRows));
 
  540    int row = cache_position + i;
 
  542    float offset = (2.0f * row_height * row) / view_height;
 
  543    float y = 1.0f + y_offset - offset;
 
  545    Rectangle<int> row_bounds(0, row_height * row - view_position + title_width, getWidth(), row_height);
 
  549    rows_[cache_index].
setTopRight(-1.0f + 2.0f * width_ratio, y);
 
  550    rows_[cache_index].
setBottomLeft(-1.0f, y - open_gl_row_height);
 
  551    rows_[cache_index].
setBottomRight(-1.0f + 2.0f * width_ratio, y - open_gl_row_height);
 
  556  if (selected_index >= 0) {
 
  557    moveQuadToRow(highlight_, selected_index, y_offset);
 
  562  if (hover_preset_ >= 0) {
 
  563    moveQuadToRow(hover_, hover_preset_, y_offset);
 
 
  573    rows_[i].destroy(open_gl);
 
 
  581  save_section_ = 
nullptr;
 
  582  delete_section_ = 
nullptr;
 
  584  addKeyListener(
this);
 
  586  preset_list_ = std::make_unique<PresetList>();
 
  587  preset_list_->addListener(
this);
 
  590  folder_list_ = std::make_unique<SelectionList>();
 
  591  folder_list_->addFavoritesOption();
 
  592  folder_list_->addListener(
this);
 
  596  Array<File> selections;
 
  597  for (
const File& directory : directories)
 
  598    selections.add(directory);
 
  599  folder_list_->setSelections(selections);
 
  603    style_buttons_[i]->addListener(
this);
 
  605    addAndMakeVisible(style_buttons_[i].get());
 
  609  store_button_ = std::make_unique<OpenGlToggleButton>(
"Store");
 
  611  store_button_->setUiButton(
true);
 
  612  store_button_->setVisible(
false);
 
  614  preset_text_ = std::make_unique<PlainTextComponent>(
"Preset", 
"Preset name");
 
  617  preset_text_->setJustification(Justification::centredLeft);
 
  619  author_text_ = std::make_unique<PlainTextComponent>(
"Author", 
"Author");
 
  622  author_text_->setJustification(Justification::centredLeft);
 
  624#if !defined(NO_TEXT_ENTRY) 
  625  search_box_ = std::make_unique<OpenGlTextEditor>(
"Search");
 
  626  search_box_->addListener(
this);
 
  627  search_box_->setSelectAllWhenFocused(
true);
 
  628  search_box_->setMultiLine(
false, 
false);
 
  629  search_box_->setJustification(Justification::centredLeft);
 
  630  addAndMakeVisible(search_box_.get());
 
  633  comments_ = std::make_unique<OpenGlTextEditor>(
"Comments");
 
  634  comments_->setSelectAllWhenFocused(
false);
 
  635  comments_->setJustification(Justification::topLeft);
 
  636  comments_->setReadOnly(
true);
 
  637  addAndMakeVisible(comments_.get());
 
  639  comments_->setMultiLine(
true, 
true);
 
  644  preset_list_->setPresets(presets);
 
  646  setWantsKeyboardFocus(
true);
 
  647  setMouseClickGrabsKeyboardFocus(
true);
 
 
  665  int text_x = info_rect.getX() + left_padding;
 
  666  int text_width = info_rect.getWidth() - 2 * left_padding;
 
  667  int name_y = info_rect.getY() + top_padding;
 
  669  int author_y = name_y + name_height + middle_padding;
 
  671  int comments_y = author_y + author_height + 2 * middle_padding;
 
  674  g.drawRect(text_x, author_y, text_width, 1);
 
  675  g.drawRect(text_x, comments_y, text_width, 1);
 
  679  Rectangle<float> folder_bounds = folder_list_->getBounds().toFloat().expanded(1);
 
  680  g.fillRoundedRectangle(folder_bounds, rounding);
 
 
  691  static constexpr float kBrowseWidthRatio = 0.68f;
 
  692  static constexpr float kSearchBoxRowHeightRatio = 1.3f;
 
  697  empty_color = empty_color.withAlpha(0.5f * empty_color.getFloatAlpha());
 
  700    search_box_->setTextToShowWhenEmpty(TRANS(
"Search"), empty_color);
 
  702    search_box_->setColour(TextEditor::textColourId, findColour(
Skin::kBodyText, 
true));
 
  703    search_box_->setColour(TextEditor::highlightedTextColourId, findColour(
Skin::kBodyText, 
true));
 
  707    comments_->setColour(TextEditor::textColourId, findColour(
Skin::kBodyText, 
true));
 
  708    comments_->setColour(TextEditor::highlightedTextColourId, findColour(
Skin::kBodyText, 
true));
 
  713  int preset_list_width = getWidth() * kBrowseWidthRatio;
 
  714  preset_list_->setBounds(getWidth() - preset_list_width - padding, 0, preset_list_width, getHeight());
 
  716    preset_list_->redoCache();
 
  724  int name_y = info_rect.getY() + top_padding;
 
  726  int author_y = name_y + name_height + middle_padding;
 
  728  int text_x = info_rect.getX() + left_padding;
 
  729  int text_width = info_rect.getWidth() - 2 * left_padding;
 
  730  preset_text_->setTextSize(name_height);
 
  731  preset_text_->setBounds(text_x, name_y - middle_padding, text_width, name_height + 2 * middle_padding);
 
  732  author_text_->setTextSize(author_height);
 
  733  author_text_->setBounds(text_x, author_y, text_width / 2, author_height + 2 * middle_padding);
 
  735  int style_filter_y = search_rect.getY() + top_padding;
 
  737    int search_box_height = kSearchBoxRowHeightRatio * preset_list_->getRowHeight();
 
  738    int search_box_x = search_rect.getX() + left_padding;
 
  739    search_box_->setBounds(search_box_x, search_rect.getY() + top_padding, text_width, search_box_height);
 
  741    style_filter_y = search_box_->getBottom() + top_padding;
 
  745  int style_button_height = preset_list_->getRowHeight();
 
  746  int style_filter_x = search_rect.getX() + left_padding;
 
  747  int style_filter_width = search_rect.getWidth() - 2 * left_padding + widget_margin;
 
  751    int column = i % num_in_row;
 
  752    int x = style_filter_x + (style_filter_width * column) / num_in_row;
 
  753    int next_x = style_filter_x + (style_filter_width * (column + 1)) / num_in_row;
 
  754    int width = next_x - x - widget_margin;
 
  755    int y = style_filter_y + (i / num_in_row) * (style_button_height + widget_margin);
 
  756    style_buttons_[i]->setBounds(x, y, width, style_button_height);
 
  759  int folder_y = style_filter_y + 3 * style_button_height + 2 * widget_margin + top_padding + 1;
 
  760  folder_list_->setBounds(style_filter_x, folder_y, text_width, search_rect.getBottom() - top_padding - folder_y - 1);
 
 
  765void PresetBrowser::setCommentsBounds() {
 
  770  int width = info_rect.getWidth() - 2 * left_padding;
 
  772  int comments_x = info_rect.getX() + left_padding;
 
  773  int comments_y = info_rect.getY() + top_info_height + top_padding;
 
  774  int comments_height = info_rect.getBottom() - comments_y - top_padding;
 
  775  if (store_button_->isVisible()) {
 
  777    int store_y = info_rect.getBottom() - store_height - top_padding;
 
  778    store_button_->setBounds(comments_x, store_y, width, store_height);
 
  779    comments_height -= store_height + top_padding / 2;
 
  782    comments_->setBounds(comments_x, comments_y, width, comments_height);
 
  786  SynthSection::visibilityChanged();
 
  788    search_box_->setText(
"");
 
  791    preset_list_->redoCache();
 
  792    folder_list_->redoCache();
 
  793    more_author_presets_.clear();
 
  797      json available_packs = available[
"packs"];
 
  798      for (
auto& pack : available_packs) {
 
  799        if (pack.count(
"Presets") == 0)
 
  802        bool purchased = 
false;
 
  803        if (pack.count(
"Purchased"))
 
  804          purchased = pack[
"Purchased"];
 
  808        std::string author_data = pack[
"Author"];
 
  810        authors.addTokens(author_data, 
",", 
"");
 
  811        for (
const String& author : authors)
 
  812          more_author_presets_.insert(author.removeCharacters(
" ._").toLowerCase().toStdString());
 
  815    catch (
const json::exception& e) {
 
 
  825  int y = info_rect.getBottom() + padding;
 
  826  return Rectangle<int>(0, y, info_rect.getWidth(), getHeight() - y);
 
 
  830  static constexpr float kInfoHeightRatio = 0.43f;
 
  832  int height = getHeight() * kInfoHeightRatio;
 
  833  return Rectangle<int>(0, 0, width, height);
 
 
  838    search_box_->setText(
"");
 
  839  preset_list_->reloadPresets();
 
  840  preset_list_->filter(
"", std::set<std::string>());
 
  843  Array<File> selections;
 
  844  for (
const File& directory : directories)
 
  845    selections.add(directory);
 
  846  folder_list_->setSelections(selections);
 
 
  850  std::set<std::string> styles;
 
  852    if (style_buttons_[i]->getToggleState()) {
 
  854      styles.insert(name.toLowerCase().toStdString());
 
  858  preset_list_->filter(search_box_->getText(), styles);
 
  859  preset_list_->redoCache();
 
 
  879  if (clicked_button == store_button_.get()) {
 
  880    String encoded_author = URL::addEscapeChars(author_text_->getText().toStdString(), 
true);
 
  881    encoded_author = encoded_author.replace(
"+", 
"%2B");
 
  883    URL url(String(kPresetStoreUrl) + encoded_author);
 
  884    url.launchInDefaultBrowser();
 
 
  892    return search_box_->hasKeyboardFocus(
true);
 
  894  if (key.getKeyCode() == KeyPress::escapeKey) {
 
  895    for (
Listener* listener : listeners_)
 
  896      listener->hidePresetBrowser();
 
  899  if (key.getKeyCode() == KeyPress::upKey || key.getKeyCode() == KeyPress::leftKey) {
 
  903  if (key.getKeyCode() == KeyPress::downKey || key.getKeyCode() == KeyPress::rightKey) {
 
  907  return search_box_->hasKeyboardFocus(
true);
 
 
  912    return search_box_->hasKeyboardFocus(
true);
 
 
  919  File parent = external_preset_.getParentDirectory();
 
  920  if (parent.exists()) {
 
  923    presets.sort(kFileSorter);
 
  924    int index = presets.indexOf(external_preset_);
 
  925    index = (index + indices + presets.size()) % presets.size();
 
  927    File new_preset = presets[index];
 
  928    loadFromFile(new_preset);
 
  932    preset_list_->shiftSelectedPreset(indices);
 
 
  944  external_preset_ = file;
 
 
  948bool PresetBrowser::loadFromFile(File& preset) {
 
  950  if (parent == 
nullptr)
 
  956    setPresetInfo(preset);
 
  963      comments_->setText(comments);
 
  964      comments_->setFont(
Fonts::instance()->proportional_light().withPointHeight(comments_font_size));
 
  965      comments_->redoImage();
 
  972void PresetBrowser::loadPresetInfo() {
 
  974  if (parent == 
nullptr)
 
  979  lighten = background.overlaidWith(lighten);
 
  983  if (preset.isEmpty()) {
 
  984    preset_text_->setText(
"Preset name");
 
  985    preset_text_->setColor(lighten);
 
  988    preset_text_->setText(preset);
 
  989    preset_text_->setColor(regular_text);
 
  993  if (author.isEmpty()) {
 
  994    author_text_->setText(
"Author");
 
  995    author_text_->setColor(lighten);
 
  998    author_text_->setText(author);
 
  999    author_text_->setColor(regular_text);
 
 1005    comments_->setText(comments);
 
 1006    comments_->setFont(
Fonts::instance()->proportional_light().withPointHeight(comments_font_size));
 
 1007    comments_->redoImage();
 
 1011void PresetBrowser::setPresetInfo(File& preset) {
 
 1012  if (preset.exists()) {
 
 1014      json parsed_json_state = json::parse(preset.loadFileAsString().toStdString(), 
nullptr, 
false);
 
 1018    catch (
const json::exception& e) {
 
 1024  listeners_.push_back(listener);
 
 
 1028  save_section_ = save_section;
 
 
 1033  delete_section_ = delete_section;
 
 
 1038  if (selection.exists() && selection.isDirectory())
 
 1039    preset_list_->setCurrentFolder(selection);
 
 
 1043  Array<File> presets;
 
 1045  preset_list_->setPresets(presets);
 
 
 1049  Array<File> presets;
 
 1052  Array<File> favorites;
 
 1055  for (
const File& file : presets) {
 
 1056    if (favorite_lookup.count(file.getFullPathName().toStdString()))
 
 1057      favorites.add(file);
 
 1059  preset_list_->setPresets(favorites);
 
 
An overlay that asks the user to confirm deletion of a preset file.
Definition delete_section.h:15
 
void addDeleteListener(Listener *listener)
Definition delete_section.h:77
 
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
 
A helper class for sorting files in ascending order based on their names.
Definition load_save.h:34
 
static const std::string kPresetFolderName
Definition load_save.h:74
 
static std::vector< File > getPresetDirectories()
Gets directories that should contain presets.
Definition load_save.cpp:1764
 
@ kNumPresetStyles
Definition load_save.h:66
 
static void addFavorite(const File &new_favorite)
Adds a new favorite preset or item to the favorites file.
Definition load_save.cpp:1219
 
static void getAllPresets(Array< File > &presets)
Retrieves all preset files from preset directories.
Definition load_save.cpp:1835
 
static std::string getLicense(json state)
Extracts the license information from a JSON state, if present.
Definition load_save.cpp:1107
 
static void removeFavorite(const File &old_favorite)
Removes a favorite item from the favorites.
Definition load_save.cpp:1225
 
static json getAvailablePacks()
Parses and returns JSON data about available packs.
Definition load_save.cpp:1441
 
static String getAuthorFromFile(const File &file)
Extracts the author's name from a given preset file.
Definition load_save.cpp:1039
 
static std::set< std::string > getFavorites()
Retrieves all favorites as a set of string paths.
Definition load_save.cpp:1235
 
static bool setViewPort(Component *component, Rectangle< int > bounds, OpenGlWrapper &open_gl)
Sets the OpenGL viewport to match a specified rectangle within a component.
Definition open_gl_component.cpp:42
 
static void setScissorBounds(Component *component, Rectangle< int > bounds, OpenGlWrapper &open_gl)
Sets the OpenGL scissor region to a specified rectangle within a component.
Definition open_gl_component.cpp:82
 
void setOwnImage(Image &image)
Sets the image from an owned copy.
Definition open_gl_image.h:69
 
void init(OpenGlWrapper &open_gl)
Initializes the OpenGL buffers and shader attributes needed for rendering the image.
Definition open_gl_image.cpp:33
 
void setBottomLeft(float x, float y)
Sets the bottom-left corner position of the image quad.
Definition open_gl_image.h:116
 
void drawImage(OpenGlWrapper &open_gl)
Draws the image to the current OpenGL context.
Definition open_gl_image.cpp:59
 
void setScissor(bool scissor)
Enables or disables scissor test when drawing the image.
Definition open_gl_image.h:156
 
void setBottomRight(float x, float y)
Sets the bottom-right corner position of the image quad.
Definition open_gl_image.h:121
 
void setTopLeft(float x, float y)
Sets the top-left corner position of the image quad.
Definition open_gl_image.h:111
 
void setTopRight(float x, float y)
Sets the top-right corner position of the image quad.
Definition open_gl_image.h:126
 
void setColor(Colour color)
Sets the color tint applied to the image.
Definition open_gl_image.h:92
 
virtual void init(OpenGlWrapper &open_gl) override
Initializes OpenGL buffers and shader attributes.
Definition open_gl_multi_quad.cpp:37
 
void setQuad(int i, float x, float y, float w, float h)
Sets the position and size of a quad in normalized device space.
Definition open_gl_multi_quad.h:313
 
void setTargetComponent(Component *target_component)
Sets a target component to help position the quads.
Definition open_gl_multi_quad.h:358
 
virtual void render(OpenGlWrapper &open_gl, bool animate) override
Renders the quads using OpenGL.
Definition open_gl_multi_quad.cpp:92
 
virtual void destroy(OpenGlWrapper &open_gl) override
Releases OpenGL resources when the component is destroyed.
Definition open_gl_multi_quad.cpp:69
 
force_inline void setColor(Colour color)
Sets the base color for the quads.
Definition open_gl_multi_quad.h:102
 
void setAdditive(bool additive)
Enables or disables additive blending for rendering.
Definition open_gl_multi_quad.h:377
 
A convenience class for a single quad rendered via OpenGL.
Definition open_gl_multi_quad.h:447
 
static Path star()
Definition paths.h:446
 
@ kLight
Definition open_gl_image_component.h:309
 
Interface for events from the PresetBrowser (e.g. preset selected, deleted, or browser hidden).
Definition preset_browser.h:427
 
static constexpr int kLeftPadding
Definition preset_browser.h:415
 
PresetBrowser()
Constructs a PresetBrowser.
Definition preset_browser.cpp:580
 
void resized() override
Called when the component is resized. Arranges layout of child components.
Definition preset_browser.cpp:690
 
static constexpr int kStoreHeight
Definition preset_browser.h:420
 
Rectangle< int > getInfoRect()
Returns the rectangle reserved for the preset info area.
Definition preset_browser.cpp:829
 
static constexpr int kTopPadding
Definition preset_browser.h:416
 
void newSelection(File selection) override
Called when a new File is selected.
Definition preset_browser.cpp:1037
 
bool keyStateChanged(bool is_key_down, Component *origin) override
Definition preset_browser.cpp:910
 
static constexpr int kCommentsFontHeight
Definition preset_browser.h:421
 
void externalPresetLoaded(File file)
Loads an external preset file and sets it as the current selection.
Definition preset_browser.cpp:943
 
void jumpToPreset(int indices)
Jumps to a preset a certain number of steps away.
Definition preset_browser.cpp:916
 
static constexpr int kNameFontHeight
Definition preset_browser.h:418
 
~PresetBrowser()
Destructor.
Definition preset_browser.cpp:651
 
void setDeleteSection(DeleteSection *delete_section)
Sets the DeleteSection for handling preset deletion.
Definition preset_browser.cpp:1032
 
void allSelected() override
Called when "All" special selection is made.
Definition preset_browser.cpp:1042
 
void textEditorEscapeKeyPressed(TextEditor &editor) override
Definition preset_browser.cpp:866
 
void loadNextPreset()
Loads the next preset in the list.
Definition preset_browser.cpp:939
 
void setSaveSection(SaveSection *save_section)
Sets the SaveSection for handling preset saving.
Definition preset_browser.cpp:1027
 
static constexpr int kAuthorFontHeight
Definition preset_browser.h:419
 
void paintBackground(Graphics &g) override
Paints the background of the section. Calls paintContainer, heading, knobs, children.
Definition preset_browser.cpp:653
 
void addListener(Listener *listener)
Adds a listener to receive events from the PresetBrowser.
Definition preset_browser.cpp:1023
 
void favoritesSelected() override
Called when "Favorites" special selection is made.
Definition preset_browser.cpp:1048
 
void filterPresets()
Filters the displayed presets based on search text and selected styles.
Definition preset_browser.cpp:849
 
bool keyPressed(const KeyPress &key, Component *origin) override
Definition preset_browser.cpp:890
 
static constexpr int kMiddlePadding
Definition preset_browser.h:417
 
void buttonClicked(Button *clicked_button) override
Called when a button is clicked. Updates the synth parameter accordingly.
Definition preset_browser.cpp:878
 
void loadPresets()
Loads all presets from known directories.
Definition preset_browser.cpp:836
 
void paintBackgroundShadow(Graphics &g) override
Stub for painting background shadows. Overridden by subclasses if needed.
Definition preset_browser.cpp:685
 
void textEditorTextChanged(TextEditor &editor) override
Definition preset_browser.cpp:862
 
void visibilityChanged() override
Definition preset_browser.cpp:785
 
void loadPrevPreset()
Loads the previous preset in the list.
Definition preset_browser.cpp:935
 
void fileDeleted(File deleted_file) override
Called after a file is deleted.
Definition preset_browser.cpp:874
 
void save(File preset) override
Called after saving a preset.
Definition preset_browser.cpp:870
 
Rectangle< int > getSearchRect()
Returns the rectangle reserved for the search area.
Definition preset_browser.cpp:822
 
A cache for preset metadata such as author and style for faster repeated lookups.
Definition preset_browser.h:21
 
std::string getStyle(const File &preset)
Retrieves the style of a given preset, caching the result.
Definition preset_browser.h:41
 
std::string getAuthor(const File &preset)
Retrieves the author of a given preset, caching the result.
Definition preset_browser.h:28
 
Interface for receiving preset selection and deletion requests.
Definition preset_browser.h:67
 
int getSelectedIndex()
Gets the index of the currently selected preset.
Definition preset_browser.cpp:404
 
void respondToMenuCallback(int result)
Handles actions from the preset context menu.
Definition preset_browser.cpp:191
 
void mouseExit(const MouseEvent &e) override
Definition preset_browser.cpp:187
 
void mouseDown(const MouseEvent &e) override
Definition preset_browser.cpp:291
 
void resized() override
Called when the component is resized. Arranges layout of child components.
Definition preset_browser.cpp:120
 
static constexpr float kScrollSensitivity
Definition preset_browser.h:112
 
static constexpr float kAuthorWidthPercent
Definition preset_browser.h:110
 
void leftClick(const MouseEvent &e)
Called on left-click to select, rename, or favorite a preset.
Definition preset_browser.cpp:236
 
void scrollBarMoved(ScrollBar *scroll_bar, double range_start) override
Definition preset_browser.cpp:312
 
void reloadPresets()
Reloads the currently displayed presets from disk.
Definition preset_browser.cpp:342
 
void menuClick(const MouseEvent &e)
Called on right-click to show a context menu.
Definition preset_browser.cpp:217
 
void mouseMove(const MouseEvent &e) override
Definition preset_browser.cpp:181
 
PresetList()
Constructs a PresetList.
Definition preset_browser.cpp:40
 
void renderOpenGlComponents(OpenGlWrapper &open_gl, bool animate) override
Renders all OpenGL components in this section and sub-sections.
Definition preset_browser.cpp:520
 
void redoCache()
Updates the cached images for rows after sorting or filtering.
Definition preset_browser.cpp:363
 
void textEditorFocusLost(TextEditor &text_editor) override
Definition preset_browser.cpp:303
 
void setScrollBarRange()
Definition preset_browser.cpp:317
 
void destroyOpenGlComponents(OpenGlWrapper &open_gl) override
Destroys all OpenGL components in this section and sub-sections.
Definition preset_browser.cpp:571
 
void initOpenGlComponents(OpenGlWrapper &open_gl) override
Initializes all OpenGL components in this section and sub-sections.
Definition preset_browser.cpp:419
 
void finishRename()
Finalizes a preset rename operation.
Definition preset_browser.cpp:328
 
static constexpr float kStyleWidthPercent
Definition preset_browser.h:109
 
Column
Definition preset_browser.h:85
 
@ kAuthor
Definition preset_browser.h:90
 
@ kDate
Definition preset_browser.h:91
 
@ kName
Definition preset_browser.h:88
 
@ kStyle
Definition preset_browser.h:89
 
@ kStar
Definition preset_browser.h:87
 
void textEditorReturnKeyPressed(TextEditor &text_editor) override
Definition preset_browser.cpp:298
 
void setPresets(Array< File > presets)
Sets the array of presets to display.
Definition preset_browser.cpp:157
 
void mouseWheelMove(const MouseEvent &e, const MouseWheelDetails &wheel) override
Definition preset_browser.cpp:163
 
void paintBackground(Graphics &g) override
Paints the background of the section. Calls paintContainer, heading, knobs, children.
Definition preset_browser.cpp:71
 
void shiftSelectedPreset(int indices)
Moves the selected preset up or down by a number of indices.
Definition preset_browser.cpp:352
 
int getRowHeight()
Gets the row height in pixels.
Definition preset_browser.h:269
 
static constexpr float kDateWidthPercent
Definition preset_browser.h:111
 
static constexpr float kNameWidthPercent
Definition preset_browser.h:108
 
static constexpr int kNumCachedRows
Definition preset_browser.h:105
 
void textEditorEscapeKeyPressed(TextEditor &editor) override
Definition preset_browser.cpp:308
 
@ kOpenFileLocation
Definition preset_browser.h:98
 
@ kRename
Definition preset_browser.h:99
 
@ kDelete
Definition preset_browser.h:100
 
void filter(String filter_string, const std::set< std::string > &styles)
Filters the displayed presets by name, author, and styles.
Definition preset_browser.cpp:372
 
static constexpr float kStarWidthPercent
Definition preset_browser.h:107
 
int getRowFromPosition(float mouse_position)
Converts a mouse Y position into a row index.
Definition preset_browser.cpp:175
 
int getScrollableRange()
Gets the scrollable height of the presets.
Definition preset_browser.cpp:412
 
A UI overlay for saving presets or other files.
Definition save_section.h:21
 
void addSaveListener(Listener *listener)
Adds a listener to be notified when saving occurs.
Definition save_section.h:161
 
Manages and provides access to vertex and fragment shaders used by the OpenGL rendering pipeline.
Definition shaders.h:19
 
@ kBodyRounding
Definition skin.h:71
 
@ kLargePadding
Definition skin.h:82
 
@ kWidgetRoundedCorner
Definition skin.h:104
 
@ kWidgetPrimary1
Definition skin.h:165
 
@ kWidgetBackground
Definition skin.h:173
 
@ kBodyText
Definition skin.h:133
 
@ kLightenScreen
Definition skin.h:141
 
@ kTextEditorSelection
Definition skin.h:203
 
@ kTextComponentText
Definition skin.h:148
 
@ kTextEditorCaret
Definition skin.h:202
 
@ kBody
Definition skin.h:129
 
@ kPresetBrowser
Definition skin.h:57
 
A base class providing foundational functionality for the Vital synthesizer’s engine,...
Definition synth_base.h:42
 
void setAuthor(const String &author)
Sets the author metadata of the current preset.
Definition synth_base.cpp:681
 
bool loadFromFile(File preset, std::string &error)
Attempts to load a preset from a file.
Definition synth_base.cpp:338
 
String getAuthor()
Gets the author of the current preset.
Definition synth_base.cpp:701
 
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
 
void setPresetName(const String &preset_name)
Sets the preset name.
Definition synth_base.cpp:693
 
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
 
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
 
virtual void renderOpenGlComponents(OpenGlWrapper &open_gl, bool animate)
Renders all OpenGL components in this section and sub-sections.
Definition synth_section.cpp:357
 
virtual void animate(bool animate)
Triggers animation state change in sub-sections if needed.
Definition synth_section.cpp:822
 
void addSubSection(SynthSection *section, bool show=true)
Adds a subsection (another SynthSection) as a child.
Definition synth_section.cpp:457
 
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
 
virtual void paintBody(Graphics &g, Rectangle< int > bounds)
Paints the body background within given bounds.
Definition synth_section.cpp:165
 
void paintChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all child sections.
Definition synth_section.cpp:274
 
virtual int getPixelMultiple() const
Definition synth_section.cpp:729
 
virtual void destroyOpenGlComponents(OpenGlWrapper &open_gl)
Destroys all OpenGL components in this section and sub-sections.
Definition synth_section.cpp:383
 
void showPopupSelector(Component *source, Point< int > position, const PopupItems &options, std::function< void(int)> callback, std::function< void()> cancel={ })
Shows a popup selector with options.
Definition synth_section.cpp:119
 
float size_ratio_
Definition synth_section.h:821
 
void addButton(OpenGlToggleButton *button, bool show=true)
Definition synth_section.cpp:428
 
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
 
virtual void paintBorder(Graphics &g, Rectangle< int > bounds)
Paints the border around given bounds.
Definition synth_section.cpp:170
 
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
 
float getSizeRatio() const
Definition synth_section.h:765
 
float getTitleWidth()
Definition synth_section.cpp:629
 
void setSkinOverride(Skin::SectionOverride skin_override)
Definition synth_section.h:303
 
virtual void initOpenGlComponents(OpenGlWrapper &open_gl)
Initializes all OpenGL components in this section and sub-sections.
Definition synth_section.cpp:349
 
virtual void paintTabShadow(Graphics &g)
Paints a tab-like shadow effect around the component.
Definition synth_section.cpp:188
 
float getWidgetMargin()
Definition synth_section.cpp:676
 
static TextLookAndFeel * instance()
Singleton instance access.
Definition text_look_and_feel.h:106
 
nlohmann::json json
Definition line_generator.h:7
 
const std::string kPresetStyleNames[]
Names for preset categories or styles.
Definition synth_strings.h:81
 
force_inline int nextPowerOfTwo(mono_float value)
Finds the next power of two greater than or equal to a float value.
Definition utils.h:370
 
const std::string kPresetExtension
File extension for Vital preset files.
Definition synth_constants.h:85
 
A helper struct containing references to OpenGL context, shaders, and display scale.
Definition shaders.h:174