Merge pull request #494 from jpcima/editor-improvement
editor: add the next and previous file buttons
This commit is contained in:
commit
07ced8891e
3 changed files with 144 additions and 29 deletions
|
|
@ -11,7 +11,7 @@ widget_class mainView {open
|
||||||
class Background
|
class Background
|
||||||
}
|
}
|
||||||
Fl_Group {} {
|
Fl_Group {} {
|
||||||
comment {theme=darkTheme}
|
comment {theme=darkTheme} open
|
||||||
xywh {0 0 800 110}
|
xywh {0 0 800 110}
|
||||||
class LogicalGroup
|
class LogicalGroup
|
||||||
} {
|
} {
|
||||||
|
|
@ -44,16 +44,6 @@ widget_class mainView {open
|
||||||
xywh {185 5 380 100} box ROUNDED_BOX
|
xywh {185 5 380 100} box ROUNDED_BOX
|
||||||
class RoundedGroup
|
class RoundedGroup
|
||||||
} {
|
} {
|
||||||
Fl_Box {} {
|
|
||||||
label {File:}
|
|
||||||
xywh {200 13 40 30} labelsize 16
|
|
||||||
class Label
|
|
||||||
}
|
|
||||||
Fl_Box {} {
|
|
||||||
label {KS:}
|
|
||||||
xywh {200 45 40 30} labelsize 16
|
|
||||||
class Label
|
|
||||||
}
|
|
||||||
Fl_Box {} {
|
Fl_Box {} {
|
||||||
label {Separator 1}
|
label {Separator 1}
|
||||||
xywh {195 41 360 5} box BORDER_BOX labeltype NO_LABEL
|
xywh {195 41 360 5} box BORDER_BOX labeltype NO_LABEL
|
||||||
|
|
@ -66,12 +56,12 @@ widget_class mainView {open
|
||||||
}
|
}
|
||||||
Fl_Box sfzFileLabel_ {
|
Fl_Box sfzFileLabel_ {
|
||||||
label {DefaultInstrument.sfz}
|
label {DefaultInstrument.sfz}
|
||||||
xywh {265 12 230 30} labelsize 20
|
xywh {195 11 250 31} labelsize 20 align 20
|
||||||
class Label
|
class Label
|
||||||
}
|
}
|
||||||
Fl_Box {} {
|
Fl_Box {} {
|
||||||
label {Key switch}
|
label {Key switch:}
|
||||||
xywh {265 44 230 30} labelsize 20
|
xywh {195 44 250 30} labelsize 20 align 20
|
||||||
class Label
|
class Label
|
||||||
}
|
}
|
||||||
Fl_Box {} {
|
Fl_Box {} {
|
||||||
|
|
@ -79,14 +69,24 @@ widget_class mainView {open
|
||||||
xywh {195 76 60 25} labelsize 12 align 24
|
xywh {195 76 60 25} labelsize 12 align 24
|
||||||
class Label
|
class Label
|
||||||
}
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
comment {tag=kTagPreviousSfzFile} selected
|
||||||
|
xywh {455 14 25 25} labelsize 24
|
||||||
|
class PreviousFileButton
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
comment {tag=kTagNextSfzFile}
|
||||||
|
xywh {480 14 25 25} labelsize 24
|
||||||
|
class NextFileButton
|
||||||
|
}
|
||||||
Fl_Button {} {
|
Fl_Button {} {
|
||||||
comment {tag=kTagLoadSfzFile}
|
comment {tag=kTagLoadSfzFile}
|
||||||
xywh {500 14 25 25} labelsize 24
|
xywh {505 14 25 25} labelsize 24
|
||||||
class LoadFileButton
|
class LoadFileButton
|
||||||
}
|
}
|
||||||
Fl_Button {} {
|
Fl_Button {} {
|
||||||
comment {tag=kTagEditSfzFile}
|
comment {tag=kTagEditSfzFile}
|
||||||
xywh {525 14 25 25} labelsize 24
|
xywh {530 14 25 25} labelsize 24
|
||||||
class EditFileButton
|
class EditFileButton
|
||||||
}
|
}
|
||||||
Fl_Box infoVoicesLabel_ {
|
Fl_Box infoVoicesLabel_ {
|
||||||
|
|
@ -216,7 +216,7 @@ widget_class mainView {open
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Fl_Group {subPanels_[kPanelSettings]} {selected
|
Fl_Group {subPanels_[kPanelSettings]} {
|
||||||
xywh {5 109 790 286}
|
xywh {5 109 790 286}
|
||||||
class LogicalGroup
|
class LogicalGroup
|
||||||
} {
|
} {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,13 @@
|
||||||
#include "NativeHelpers.h"
|
#include "NativeHelpers.h"
|
||||||
#include <absl/strings/string_view.h>
|
#include <absl/strings/string_view.h>
|
||||||
#include <absl/strings/match.h>
|
#include <absl/strings/match.h>
|
||||||
|
#include <absl/strings/ascii.h>
|
||||||
#include <ghc/fs_std.hpp>
|
#include <ghc/fs_std.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <system_error>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
@ -46,6 +51,8 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
enum {
|
enum {
|
||||||
kTagLoadSfzFile,
|
kTagLoadSfzFile,
|
||||||
kTagEditSfzFile,
|
kTagEditSfzFile,
|
||||||
|
kTagPreviousSfzFile,
|
||||||
|
kTagNextSfzFile,
|
||||||
kTagSetVolume,
|
kTagSetVolume,
|
||||||
kTagSetNumVoices,
|
kTagSetNumVoices,
|
||||||
kTagSetOversampling,
|
kTagSetOversampling,
|
||||||
|
|
@ -101,9 +108,12 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
|
|
||||||
void chooseSfzFile();
|
void chooseSfzFile();
|
||||||
void changeSfzFile(const std::string& filePath);
|
void changeSfzFile(const std::string& filePath);
|
||||||
|
void changeToNextSfzFile(long offset);
|
||||||
void chooseScalaFile();
|
void chooseScalaFile();
|
||||||
void changeScalaFile(const std::string& filePath);
|
void changeScalaFile(const std::string& filePath);
|
||||||
|
|
||||||
|
static bool scanDirectoryFiles(const fs::path& dirPath, std::function<bool(const fs::path&)> filter, std::vector<fs::path>& fileNames);
|
||||||
|
|
||||||
static absl::string_view simplifiedFileName(absl::string_view path, absl::string_view removedSuffix, absl::string_view ifEmpty);
|
static absl::string_view simplifiedFileName(absl::string_view path, absl::string_view removedSuffix, absl::string_view ifEmpty);
|
||||||
|
|
||||||
void updateSfzFileLabel(const std::string& filePath);
|
void updateSfzFileLabel(const std::string& filePath);
|
||||||
|
|
@ -333,7 +343,7 @@ void Editor::Impl::createFrameContents()
|
||||||
lightTheme.titleBoxText = { 0xff, 0xff, 0xff };
|
lightTheme.titleBoxText = { 0xff, 0xff, 0xff };
|
||||||
lightTheme.titleBoxBackground = { 0x2e, 0x34, 0x36 };
|
lightTheme.titleBoxBackground = { 0x2e, 0x34, 0x36 };
|
||||||
lightTheme.icon = lightTheme.text;
|
lightTheme.icon = lightTheme.text;
|
||||||
lightTheme.iconHighlight = { 0xa8, 0x62, 0x34 };
|
lightTheme.iconHighlight = { 0xfd, 0x98, 0x00 };
|
||||||
lightTheme.valueText = { 0xff, 0xff, 0xff };
|
lightTheme.valueText = { 0xff, 0xff, 0xff };
|
||||||
lightTheme.valueBackground = { 0x2e, 0x34, 0x36 };
|
lightTheme.valueBackground = { 0x2e, 0x34, 0x36 };
|
||||||
lightTheme.knobActiveTrackColor = { 0x00, 0xb6, 0x2a };
|
lightTheme.knobActiveTrackColor = { 0x00, 0xb6, 0x2a };
|
||||||
|
|
@ -345,7 +355,7 @@ void Editor::Impl::createFrameContents()
|
||||||
darkTheme.titleBoxText = { 0x00, 0x00, 0x00 };
|
darkTheme.titleBoxText = { 0x00, 0x00, 0x00 };
|
||||||
darkTheme.titleBoxBackground = { 0xba, 0xbd, 0xb6 };
|
darkTheme.titleBoxBackground = { 0xba, 0xbd, 0xb6 };
|
||||||
darkTheme.icon = darkTheme.text;
|
darkTheme.icon = darkTheme.text;
|
||||||
darkTheme.iconHighlight = { 0xa8, 0x62, 0x34 };
|
darkTheme.iconHighlight = { 0xfd, 0x98, 0x00 };
|
||||||
darkTheme.valueText = { 0x2e, 0x34, 0x36 };
|
darkTheme.valueText = { 0x2e, 0x34, 0x36 };
|
||||||
darkTheme.valueBackground = { 0xff, 0xff, 0xff };
|
darkTheme.valueBackground = { 0xff, 0xff, 0xff };
|
||||||
darkTheme.knobActiveTrackColor = { 0x00, 0xb6, 0x2a };
|
darkTheme.knobActiveTrackColor = { 0x00, 0xb6, 0x2a };
|
||||||
|
|
@ -377,6 +387,8 @@ void Editor::Impl::createFrameContents()
|
||||||
typedef STextButton HomeButton;
|
typedef STextButton HomeButton;
|
||||||
typedef STextButton SettingsButton;
|
typedef STextButton SettingsButton;
|
||||||
typedef STextButton EditFileButton;
|
typedef STextButton EditFileButton;
|
||||||
|
typedef STextButton PreviousFileButton;
|
||||||
|
typedef STextButton NextFileButton;
|
||||||
typedef SPiano Piano;
|
typedef SPiano Piano;
|
||||||
|
|
||||||
auto createLogicalGroup = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
|
auto createLogicalGroup = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
|
||||||
|
|
@ -505,6 +517,12 @@ void Editor::Impl::createFrameContents()
|
||||||
auto createLoadFileButton = [&createGlyphButton](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int fontsize) {
|
auto createLoadFileButton = [&createGlyphButton](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int fontsize) {
|
||||||
return createGlyphButton(u8"\ue1a3", bounds, tag, fontsize);
|
return createGlyphButton(u8"\ue1a3", bounds, tag, fontsize);
|
||||||
};
|
};
|
||||||
|
auto createPreviousFileButton = [&createGlyphButton](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int fontsize) {
|
||||||
|
return createGlyphButton(u8"\ue0d9", bounds, tag, fontsize);
|
||||||
|
};
|
||||||
|
auto createNextFileButton = [&createGlyphButton](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int fontsize) {
|
||||||
|
return createGlyphButton(u8"\ue0da", bounds, tag, fontsize);
|
||||||
|
};
|
||||||
auto createPiano = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
|
auto createPiano = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
|
||||||
SPiano* piano = new SPiano(bounds);
|
SPiano* piano = new SPiano(bounds);
|
||||||
return piano;
|
return piano;
|
||||||
|
|
@ -669,6 +687,56 @@ void Editor::Impl::changeSfzFile(const std::string& filePath)
|
||||||
updateSfzFileLabel(filePath);
|
updateSfzFileLabel(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::Impl::changeToNextSfzFile(long offset)
|
||||||
|
{
|
||||||
|
if (currentSfzFile_.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const fs::path filePath = fs::u8path(currentSfzFile_);
|
||||||
|
const fs::path dirPath = filePath.parent_path();
|
||||||
|
|
||||||
|
// extract file names of regular files from the sfz directory
|
||||||
|
std::vector<fs::path> fileNames;
|
||||||
|
fileNames.reserve(64);
|
||||||
|
|
||||||
|
auto fileFilter = [](const fs::path &name) -> bool {
|
||||||
|
std::string ext = name.extension().u8string();
|
||||||
|
absl::AsciiStrToLower(&ext);
|
||||||
|
return ext == ".sfz";
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!scanDirectoryFiles(dirPath, fileFilter, fileNames))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// sort file names
|
||||||
|
const size_t size = fileNames.size();
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::sort(fileNames.begin(), fileNames.end());
|
||||||
|
|
||||||
|
// find our current position in the file name list
|
||||||
|
size_t currentIndex = 0;
|
||||||
|
const fs::path currentFileName = filePath.filename();
|
||||||
|
|
||||||
|
while (currentIndex + 1 < size && fileNames[currentIndex] < currentFileName)
|
||||||
|
++currentIndex;
|
||||||
|
|
||||||
|
// advance to the next or previous item
|
||||||
|
typedef typename std::make_signed<size_t>::type signed_size_t;
|
||||||
|
|
||||||
|
size_t newIndex = static_cast<signed_size_t>(currentIndex) + offset;
|
||||||
|
if (static_cast<signed_size_t>(newIndex) < 0)
|
||||||
|
newIndex = static_cast<signed_size_t>(newIndex) %
|
||||||
|
static_cast<signed_size_t>(size) + size;
|
||||||
|
newIndex %= size;
|
||||||
|
|
||||||
|
if (newIndex != currentIndex) {
|
||||||
|
const fs::path newFilePath = dirPath / fileNames[newIndex];
|
||||||
|
changeSfzFile(newFilePath.u8string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::Impl::chooseScalaFile()
|
void Editor::Impl::chooseScalaFile()
|
||||||
{
|
{
|
||||||
SharedPointer<CNewFileSelector> fs = owned(CNewFileSelector::create(frame_));
|
SharedPointer<CNewFileSelector> fs = owned(CNewFileSelector::create(frame_));
|
||||||
|
|
@ -694,6 +762,39 @@ void Editor::Impl::changeScalaFile(const std::string& filePath)
|
||||||
updateScalaFileLabel(filePath);
|
updateScalaFileLabel(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Editor::Impl::scanDirectoryFiles(const fs::path& dirPath, std::function<bool(const fs::path&)> filter, std::vector<fs::path>& fileNames)
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
fs::directory_iterator it { dirPath, ec };
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fileNames.clear();
|
||||||
|
|
||||||
|
while (!ec && it != fs::directory_iterator()) {
|
||||||
|
const fs::directory_entry& ent = *it;
|
||||||
|
|
||||||
|
std::error_code fileEc;
|
||||||
|
const fs::file_status status = ent.status(fileEc);
|
||||||
|
if (fileEc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (status.type() == fs::file_type::regular) {
|
||||||
|
fs::path fileName = ent.path().filename();
|
||||||
|
if (!filter || filter(fileName))
|
||||||
|
fileNames.push_back(std::move(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
it.increment(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
absl::string_view Editor::Impl::simplifiedFileName(absl::string_view path, absl::string_view removedSuffix, absl::string_view ifEmpty)
|
absl::string_view Editor::Impl::simplifiedFileName(absl::string_view path, absl::string_view removedSuffix, absl::string_view ifEmpty)
|
||||||
{
|
{
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
|
|
@ -892,6 +993,20 @@ void Editor::Impl::valueChanged(CControl* ctl)
|
||||||
openFileInExternalEditor(currentSfzFile_.c_str());
|
openFileInExternalEditor(currentSfzFile_.c_str());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kTagPreviousSfzFile:
|
||||||
|
if (value != 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Call::later([this]() { changeToNextSfzFile(-1); });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kTagNextSfzFile:
|
||||||
|
if (value != 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Call::later([this]() { changeToNextSfzFile(+1); });
|
||||||
|
break;
|
||||||
|
|
||||||
case kTagLoadScalaFile:
|
case kTagLoadScalaFile:
|
||||||
if (value != 1)
|
if (value != 1)
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -18,24 +18,24 @@ SettingsButton* const view__7 = createSettingsButton(CRect(107, 69, 132, 94), kT
|
||||||
view__3->addView(view__7);
|
view__3->addView(view__7);
|
||||||
RoundedGroup* const view__8 = createRoundedGroup(CRect(185, 5, 565, 105), -1, "", kCenterText, 14);
|
RoundedGroup* const view__8 = createRoundedGroup(CRect(185, 5, 565, 105), -1, "", kCenterText, 14);
|
||||||
view__2->addView(view__8);
|
view__2->addView(view__8);
|
||||||
Label* const view__9 = createLabel(CRect(15, 8, 55, 38), -1, "File:", kCenterText, 16);
|
HLine* const view__9 = createHLine(CRect(10, 36, 370, 41), -1, "", kCenterText, 14);
|
||||||
view__8->addView(view__9);
|
view__8->addView(view__9);
|
||||||
Label* const view__10 = createLabel(CRect(15, 40, 55, 70), -1, "KS:", kCenterText, 16);
|
HLine* const view__10 = createHLine(CRect(10, 68, 370, 73), -1, "", kCenterText, 14);
|
||||||
view__8->addView(view__10);
|
view__8->addView(view__10);
|
||||||
HLine* const view__11 = createHLine(CRect(10, 36, 370, 41), -1, "", kCenterText, 14);
|
Label* const view__11 = createLabel(CRect(10, 6, 260, 37), -1, "DefaultInstrument.sfz", kLeftText, 20);
|
||||||
|
sfzFileLabel_ = view__11;
|
||||||
view__8->addView(view__11);
|
view__8->addView(view__11);
|
||||||
HLine* const view__12 = createHLine(CRect(10, 68, 370, 73), -1, "", kCenterText, 14);
|
Label* const view__12 = createLabel(CRect(10, 39, 260, 69), -1, "Key switch:", kLeftText, 20);
|
||||||
view__8->addView(view__12);
|
view__8->addView(view__12);
|
||||||
Label* const view__13 = createLabel(CRect(80, 7, 310, 37), -1, "DefaultInstrument.sfz", kCenterText, 20);
|
Label* const view__13 = createLabel(CRect(10, 71, 70, 96), -1, "Voices:", kRightText, 12);
|
||||||
sfzFileLabel_ = view__13;
|
|
||||||
view__8->addView(view__13);
|
view__8->addView(view__13);
|
||||||
Label* const view__14 = createLabel(CRect(80, 39, 310, 69), -1, "Key switch", kCenterText, 20);
|
PreviousFileButton* const view__14 = createPreviousFileButton(CRect(270, 9, 295, 34), kTagPreviousSfzFile, "", kCenterText, 24);
|
||||||
view__8->addView(view__14);
|
view__8->addView(view__14);
|
||||||
Label* const view__15 = createLabel(CRect(10, 71, 70, 96), -1, "Voices:", kRightText, 12);
|
NextFileButton* const view__15 = createNextFileButton(CRect(295, 9, 320, 34), kTagNextSfzFile, "", kCenterText, 24);
|
||||||
view__8->addView(view__15);
|
view__8->addView(view__15);
|
||||||
LoadFileButton* const view__16 = createLoadFileButton(CRect(315, 9, 340, 34), kTagLoadSfzFile, "", kCenterText, 24);
|
LoadFileButton* const view__16 = createLoadFileButton(CRect(320, 9, 345, 34), kTagLoadSfzFile, "", kCenterText, 24);
|
||||||
view__8->addView(view__16);
|
view__8->addView(view__16);
|
||||||
EditFileButton* const view__17 = createEditFileButton(CRect(340, 9, 365, 34), kTagEditSfzFile, "", kCenterText, 24);
|
EditFileButton* const view__17 = createEditFileButton(CRect(345, 9, 370, 34), kTagEditSfzFile, "", kCenterText, 24);
|
||||||
view__8->addView(view__17);
|
view__8->addView(view__17);
|
||||||
Label* const view__18 = createLabel(CRect(75, 71, 125, 96), -1, "", kCenterText, 12);
|
Label* const view__18 = createLabel(CRect(75, 71, 125, 96), -1, "", kCenterText, 12);
|
||||||
infoVoicesLabel_ = view__18;
|
infoVoicesLabel_ = view__18;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue