Skip to content

Commit

Permalink
Rename zones and start on reorder zones (#1220)
Browse files Browse the repository at this point in the history
Implement a givenName for zone; set it on empty zone.
Make it so the UI gesture renames it. Allow a drag to reorder
of zones which is starting to work ok but has some selection
bugs.

Addresses #1198
  • Loading branch information
baconpaul authored Aug 30, 2024
1 parent b054fac commit 20b1d26
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 32 deletions.
80 changes: 72 additions & 8 deletions src-ui/app/edit-screen/components/GroupZoneTreeControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
int zonePad = 16;
int grouplabelPad = zonePad;

enum DragOverState
{
NONE,
DRAG_OVER
} dragOverState{NONE};

void paint(juce::Graphics &g) override
{
if (!gsb)
Expand Down Expand Up @@ -168,6 +174,12 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
juce::Justification::centredLeft);
g.setColour(textColor);
g.drawText(sg.second, nb, juce::Justification::centredLeft);

if (dragOverState == DRAG_OVER)
{
g.setColour(editor->themeColor(theme::ColorMap::accent_1b));
g.drawHorizontalLine(1, 0, getWidth());
}
}
else
{
Expand All @@ -190,6 +202,12 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
jcmp::GlyphPainter::paintGlyph(g, b, jcmp::GlyphPainter::JOG_RIGHT,
textColor.withAlpha(0.5f));
}

if (dragOverState == DRAG_OVER)
{
g.setColour(editor->themeColor(theme::ColorMap::accent_1b));
g.drawHorizontalLine(1, zonePad, getWidth());
}
}
}

Expand All @@ -211,7 +229,11 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
{
p.addSectionHeader("Zone");
p.addSeparator();
p.addItem("Rename", []() {});
p.addItem("Rename", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
w->doZoneRename();
});
p.addItem("Delete", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
Expand Down Expand Up @@ -291,11 +313,29 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::

bool isInterestedInDragSource(const SourceDetails &dragSourceDetails) override
{
return !isZone();
return true; // !isZone();
}

void itemDragEnter(const SourceDetails &dragSourceDetails) override
{
SCLOG("Item Drag Enter");
dragOverState = DRAG_OVER;
repaint();
}
void itemDragMove(const SourceDetails &dragSourceDetails) override
{
// SCLOG("Item Drag Move");
}
void itemDragExit(const SourceDetails &dragSourceDetails) override
{
dragOverState = NONE;
repaint();
}

void itemDropped(const SourceDetails &dragSourceDetails) override
{
dragOverState = NONE;
repaint();
auto sc = dragSourceDetails.sourceComponent;
if (!sc) // weak component
return;
Expand All @@ -321,21 +361,45 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
const auto &sg = tgl[rowNumber];
assert(sg.first.zone < 0);
auto st = gsb->partGroupSidebar->style();
renameEditor->setFont(
st->getFont(jcmp::Label::Styles::styleClass, jcmp::Label::Styles::labelfont));
renameEditor->applyFontToAllText(
st->getFont(jcmp::Label::Styles::styleClass, jcmp::Label::Styles::labelfont));
auto groupFont = gsb->editor->themeApplier.interRegularFor(11);
renameEditor->setFont(groupFont);
renameEditor->applyFontToAllText(groupFont);
renameEditor->setText(sg.second);
renameEditor->setSelectAllWhenFocused(true);
renameEditor->setIndents(2, 1);
renameEditor->setVisible(true);
renameEditor->grabKeyboardFocus();
}

void doZoneRename()
{
const auto &tgl = lbm->thisGroup;

const auto &sg = tgl[rowNumber];
auto st = gsb->partGroupSidebar->style();
auto zoneFont = gsb->editor->themeApplier.interLightFor(11);
renameEditor->setFont(zoneFont);
renameEditor->applyFontToAllText(zoneFont);
renameEditor->setText(sg.second);
renameEditor->setSelectAllWhenFocused(true);
renameEditor->setIndents(2, 1);
renameEditor->setVisible(true);
renameEditor->grabKeyboardFocus();
}

void textEditorReturnKeyPressed(juce::TextEditor &) override
{
auto za = getZoneAddress();
gsb->sendToSerialization(
cmsg::RenameGroup({za, renameEditor->getText().toStdString()}));
if (isZone())
{
gsb->sendToSerialization(
cmsg::RenameZone({za, renameEditor->getText().toStdString()}));
}
else
{
gsb->sendToSerialization(
cmsg::RenameGroup({za, renameEditor->getText().toStdString()}));
}
renameEditor->setVisible(false);
}
void textEditorEscapeKeyPressed(juce::TextEditor &) override
Expand Down
5 changes: 5 additions & 0 deletions src-ui/app/editor-impl/SCXTEditorResponseHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ void SCXTEditor::onSamplesUpdated(
void SCXTEditor::onStructureUpdated(const engine::Engine::pgzStructure_t &s)
{
if (editScreen && editScreen->partSidebar)
{
editScreen->partSidebar->setPartGroupZoneStructure(s);
}
if (editScreen && editScreen->mappingPane)
{
}
}

void SCXTEditor::onGroupOrZoneProcessorDataAndMetadata(
Expand Down
4 changes: 3 additions & 1 deletion src/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,10 +624,12 @@ void Engine::createEmptyZone(scxt::engine::KeyboardRange krange, scxt::engine::V

// 2. Create a zone object on this thread but don't add it
auto zptr = std::make_unique<Zone>();
// TODO fixme
zptr->mapping.keyboardRange = krange;
zptr->mapping.velocityRange = vrange;
zptr->mapping.rootKey = (krange.keyStart + krange.keyEnd) / 2;
zptr->givenName = "Empty Zone (" + std::to_string(zptr->id.id) + ")";

// give it a name

// Drop into selected group logic goes here
auto [sp, sg] = selectionManager->bestPartGroupForNewSample(*this);
Expand Down
5 changes: 5 additions & 0 deletions src/engine/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ struct Group : MoveableOnly<Group>,
return res;
}

void swapZonesByIndex(size_t zoneIndex0, size_t zoneIndex1)
{
std::swap(zones[zoneIndex0], zones[zoneIndex1]);
}

bool isActive() const;
void addActiveZone();
void removeActiveZone();
Expand Down
4 changes: 3 additions & 1 deletion src/engine/zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,11 @@ struct Zone : MoveableOnly<Zone>, HasGroupZoneProcessors<Zone>, SampleRateSuppor
void process(Engine &onto);
template <bool OS> void processWithOS(Engine &onto);

// TODO: editable name
std::string givenName{};
std::string getName() const
{
if (!givenName.empty())
return givenName;
if (samplePointers[0])
return samplePointers[0]->getDisplayName();
return id.to_string();
Expand Down
15 changes: 14 additions & 1 deletion src/json/engine_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,22 @@ SC_STREAMDEF(scxt::engine::Zone::AssociatedSampleSet, SC_FROM({
}));

SC_STREAMDEF(scxt::engine::Zone, SC_FROM({
// special case. before given name for empty samples we used id.
// crystalize this name for old patches. You can probably remove this
// code in october 2024.
auto useGivenName = t.givenName;
if (useGivenName.empty() && !t.sampleData.samples[0].active)
{
SCLOG("Crystalizing given name on stream");
useGivenName = t.getName();
}
// but just that bit

v = {{"sampleData", t.sampleData}, {"mappingData", t.mapping},
{"outputInfo", t.outputInfo}, {"processorStorage", t.processorStorage},
{"routingTable", t.routingTable}, {"modulatorStorage", t.modulatorStorage},
{"aegStorage", t.egStorage[0]}, {"eg2Storage", t.egStorage[1]}};
{"aegStorage", t.egStorage[0]}, {"eg2Storage", t.egStorage[1]},
{"givenName", useGivenName}};
}),
SC_TO({
auto &zone = to;
Expand All @@ -377,6 +389,7 @@ SC_STREAMDEF(scxt::engine::Zone, SC_FROM({
findIfArray(v, "modulatorStorage", zone.modulatorStorage);
findOrDefault(v, "aegStorage", zone.egStorage[0]);
findOrDefault(v, "eg2Storage", zone.egStorage[1]);
findOrSet(v, "givenName", "", zone.givenName);
zone.onRoutingChanged();
}));

Expand Down
1 change: 1 addition & 0 deletions src/messaging/client/client_serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ enum ClientToSerializationMessagesIds
c2s_delete_selected_zones,
c2s_delete_group,
c2s_clear_part,
c2s_rename_zone,
c2s_rename_group,

c2s_set_tuning_mode,
Expand Down
10 changes: 0 additions & 10 deletions src/messaging/client/group_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,5 @@ CLIENT_TO_SERIAL_CONSTRAINED(UpdateGroupOutputBoolValue, c2s_update_group_output
detail::updateGroupMemberValue(&engine::Group::outputInfo, payload,
engine, cont));

using renameGroup_t = std::tuple<selection::SelectionManager::ZoneAddress, std::string>;
inline void renameGroup(const renameGroup_t &payload, const engine::Engine &engine,
MessageController &cont)
{
const auto &[p, g, z] = std::get<0>(payload);
engine.getPatch()->getPart(p)->getGroup(g)->name = std::get<1>(payload);
serializationSendToClient(s2c_send_pgz_structure, engine.getPartGroupZoneStructure(), cont);
}
CLIENT_TO_SERIAL(RenameGroup, c2s_rename_group, renameGroup_t, renameGroup(payload, engine, cont));

} // namespace scxt::messaging::client
#endif // SHORTCIRCUIT_GROUP_MESSAGES_H
24 changes: 24 additions & 0 deletions src/messaging/client/group_or_zone_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,29 @@ CLIENT_TO_SERIAL_CONSTRAINED(
}
}))

using renameGroupZonePayload_t = std::tuple<selection::SelectionManager::ZoneAddress, std::string>;
inline void doRenameGroup(const renameGroupZonePayload_t &payload, const engine::Engine &engine,
MessageController &cont)
{
const auto &[p, g, z] = std::get<0>(payload);
engine.getPatch()->getPart(p)->getGroup(g)->name = std::get<1>(payload);
serializationSendToClient(s2c_send_pgz_structure, engine.getPartGroupZoneStructure(), cont);
}
CLIENT_TO_SERIAL(RenameGroup, c2s_rename_group, renameGroupZonePayload_t,
doRenameGroup(payload, engine, cont));

inline void doRenameZone(const renameGroupZonePayload_t &payload, const engine::Engine &engine,
MessageController &cont)
{
const auto &[p, g, z] = std::get<0>(payload);
engine.getPatch()->getPart(p)->getGroup(g)->getZone(z)->givenName = std::get<1>(payload);
serializationSendToClient(s2c_send_pgz_structure, engine.getPartGroupZoneStructure(), cont);
serializationSendToClient(s2c_send_selected_group_zone_mapping_summary,
engine.getPatch()->getPart(p)->getZoneMappingSummary(),
*(engine.getMessageController()));
}
CLIENT_TO_SERIAL(RenameZone, c2s_rename_zone, renameGroupZonePayload_t,
doRenameZone(payload, engine, cont));

} // namespace scxt::messaging::client
#endif // SHORTCIRCUITXT_GROUP_OR_ZONE_MESSAGES_H
41 changes: 30 additions & 11 deletions src/messaging/client/structure_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,23 +285,42 @@ inline void moveZoneFromTo(const zoneAddressFromTo_t &payload, engine::Engine &e
auto &src = payload.first;
auto &tgt = payload.second;

assert(src.part == tgt.part);

auto nad = engine.getPatch()->getPart(tgt.part)->getGroup(tgt.group)->getZones().size();

cont.scheduleAudioThreadCallbackUnderStructureLock(
[s = src, t = tgt](auto &e) {
auto &zoneO = e.getPatch()->getPart(s.part)->getGroup(s.group)->getZone(s.zone);
e.terminateVoicesForZone(*zoneO);
if (s.group == t.group)
{
// Its a zone swap
auto &group = e.getPatch()->getPart(s.part)->getGroup(s.group);
auto &zoneS = group->getZone(s.zone);
auto &zoneT = group->getZone(t.zone);
e.terminateVoicesForZone(*zoneS);
e.terminateVoicesForZone(*zoneT);
group->swapZonesByIndex(s.zone, t.zone);
}
else
{
auto &zoneO = e.getPatch()->getPart(s.part)->getGroup(s.group)->getZone(s.zone);
e.terminateVoicesForZone(*zoneO);

auto zid = zoneO->id;
auto z = e.getPatch()->getPart(s.part)->getGroup(s.group)->removeZone(zid);
if (z)
e.getPatch()->getPart(t.part)->getGroup(t.group)->addZone(z);
auto zid = zoneO->id;
auto z = e.getPatch()->getPart(s.part)->getGroup(s.group)->removeZone(zid);
if (z)
e.getPatch()->getPart(t.part)->getGroup(t.group)->addZone(z);
}
},
[nad, t = tgt](auto &engine) {
auto tc = t;
tc.zone = nad;
auto act = selection::SelectionManager::SelectActionContents(tc, true, true, true);
engine.getSelectionManager()->selectAction(act);
[nad, s = src, t = tgt](auto &engine) {
if (s.group != t.group)
{
// Swapped groups. We almost definitely need to select in the new group
auto tc = t;
tc.zone = nad;
auto act = selection::SelectionManager::SelectActionContents(tc, true, true, true);
engine.getSelectionManager()->selectAction(act);
}
serializationSendToClient(s2c_send_pgz_structure, engine.getPartGroupZoneStructure(),
*(engine.getMessageController()));
serializationSendToClient(s2c_send_selected_group_zone_mapping_summary,
Expand Down

0 comments on commit 20b1d26

Please sign in to comment.