Merge Insert as FX: load ReaSampler 9000 onto the selected track from the panel
# Conflicts: # src/shell/actions/CLAUDE.md
This commit is contained in:
@@ -10,8 +10,8 @@ VST3 editor (`shell/instrument/`).
|
||||
|
||||
Pure layout/hit-test/palette modules the panel draws through (`theme`,
|
||||
`component_geometry`, `bank_grid`, `tab_strip`, `mode_switch`, `action_bar`,
|
||||
`footer_bar`, `overflow_menu`, `prune_button`, `mode_enable`, `tooltip`, `card_drag`,
|
||||
`card_meta`) live in `core/ui` / `core/model` and are documented there — this
|
||||
`footer_bar`, `overflow_menu`, `prune_button`, `mode_enable`, `insert_fx_enable`,
|
||||
`tooltip`, `card_drag`, `card_meta`) live in `core/ui` / `core/model` and are documented there — this
|
||||
directory consumes them but does not own them. The promptless bank-mutation verbs
|
||||
(`bankOpCreate`/`Rename`/`Delete`/… + `persistBankOp`) that `panel_bank_ops` skins
|
||||
live in `shell/bank_ops`, a sibling directory, not here.
|
||||
|
||||
@@ -128,6 +128,17 @@ std::vector<ActionBarRow> topBarRows() {
|
||||
rows.push_back({"INSERT_SELECTED_CONFORM", "Insert Conform",
|
||||
"insert selected sample at edit cursor (conform to tempo)",
|
||||
ActionCluster::Placement, true});
|
||||
// The one top-bar row with a live/dead gate: it places the PLAYER, and one instance
|
||||
// holds one capture. Only the payload half of the fold is knowable at draw time —
|
||||
// core/ui/insert_fx_enable.h states why the track half stays a press-time message.
|
||||
// Counts through focusedSelectionIds() (not the raw selection) so the drawn state
|
||||
// can't diverge from doInsertAsFx's own count — the raw selection can go stale
|
||||
// against live membership (e.g. an undo/redo book restore) without being cleared.
|
||||
rows.push_back({"LOAD_INSTRUMENT_ON_TRACK", "Insert as FX",
|
||||
"insert selected sample as ReaSampler 9000 on the selected track",
|
||||
ActionCluster::Placement,
|
||||
insertFxButtonEnabled(
|
||||
static_cast<int>(focusedSelectionIds().size()))});
|
||||
return rows;
|
||||
}
|
||||
|
||||
@@ -268,12 +279,27 @@ bool currentTooltip(int w, int h, std::string& textOut, int& ax, int& ay, int& a
|
||||
if (s.index == hv.index) { slot = &s; break; }
|
||||
if (!slot) return false;
|
||||
|
||||
const ActionBarRow& row = rows[static_cast<std::size_t>(hv.index)];
|
||||
|
||||
// Insert as FX paints dead only for the payload axis (NoCapture/MultiCapture);
|
||||
// speak that refusal here rather than the generic phrase, so a dead button says
|
||||
// WHY. NoTrack stays a press-time message (insert_fx_enable.h: track selection
|
||||
// has no change callback, so it is only ever knowable at press time).
|
||||
if (row.suffix == "LOAD_INSTRUMENT_ON_TRACK" && !row.enabled) {
|
||||
const InsertFxRefusal refusal =
|
||||
insertFxRefusal(static_cast<int>(focusedSelectionIds().size()), /*trackSelected=*/true);
|
||||
if (refusal != InsertFxRefusal::None) {
|
||||
textOut = insertFxRefusalMessage(refusal);
|
||||
ax = slot->x; ay = slot->y; aw = slot->width; ah = slot->height;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// fullName is stored prefix-free; strip defensively in case a source ever
|
||||
// carries the display prefix. Tooltip carries name + binding when bound
|
||||
// (e.g. "capture selected item — F5"), name only when unbound.
|
||||
const std::string phrase = stripActionPrefix(rows[static_cast<std::size_t>(hv.index)].fullName,
|
||||
actionDisplayPrefix());
|
||||
const int cmd = resolveBarCommandId(rows[static_cast<std::size_t>(hv.index)]);
|
||||
const std::string phrase = stripActionPrefix(row.fullName, actionDisplayPrefix());
|
||||
const int cmd = resolveBarCommandId(row);
|
||||
const std::string binding = barBindingText(cmd);
|
||||
textOut = binding.empty() ? phrase : phrase + " \xe2\x80\x94 " + binding; // " — " (em dash, UTF-8)
|
||||
ax = slot->x; ay = slot->y; aw = slot->width; ah = slot->height;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "core/ui/component_geometry.h"
|
||||
#include "core/ui/drag_out.h"
|
||||
#include "core/ui/footer_bar.h"
|
||||
#include "core/ui/insert_fx_enable.h"
|
||||
#include "core/ui/mode_enable.h"
|
||||
#include "core/ui/overflow_menu.h"
|
||||
#include "core/ui/prune_button.h"
|
||||
@@ -134,6 +135,10 @@ using ui::hitTestMenuButton;
|
||||
using ui::hitTestPruneButton;
|
||||
using ui::hitTestSlot;
|
||||
using ui::hitTestTabStrip;
|
||||
using ui::insertFxButtonEnabled;
|
||||
using ui::insertFxRefusal;
|
||||
using ui::insertFxRefusalMessage;
|
||||
using ui::InsertFxRefusal;
|
||||
using ui::kCardNameScrimAlpha;
|
||||
using ui::kCardStripHeight;
|
||||
using ui::kCardStripPad;
|
||||
@@ -420,8 +425,9 @@ struct ActionBarRow {
|
||||
std::string shortLabel;
|
||||
std::string fullName;
|
||||
ActionCluster cluster = ActionCluster::Capture;
|
||||
bool enabled = true; // opposite-mode gate for bottom-bar tag buttons; always true
|
||||
// for the top bar (unconditional triggers)
|
||||
bool enabled = true; // opposite-mode gate for the bottom-bar tag buttons, and the
|
||||
// payload gate for the top bar's Insert as FX; every other top-
|
||||
// bar row is an unconditional trigger and stays true
|
||||
};
|
||||
|
||||
// Modifier state at event time. Alt = the replace modifier.
|
||||
|
||||
Reference in New Issue
Block a user