73 lines
3.6 KiB
C++
73 lines
3.6 KiB
C++
#pragma once
|
|
#include "core/ui/rect.h"
|
|
// drag_out — decision logic behind the bank_panel's native OS drag-out. OLE/SWELL initiation and
|
|
// the panel gesture hook stay in the shell (drag_out_win.* + shell/panel/panel_drag.cpp).
|
|
//
|
|
// Gesture boundary: the panel's own internal drag (press a selected cell, drop onto a pool/bank
|
|
// region or tab) lives entirely inside the panel client rect. The moment the pointer LEAVES that
|
|
// rect while a drag is armed with samples, the gesture becomes OS-bound — dragged out to another
|
|
// window/Explorer/DAW. A single-capture drag that leaves the rect but is still over REAPER's own
|
|
// UI is instead an InstrumentDrop (heading for a track's FX button); do not regress this boundary.
|
|
//
|
|
// Path-list assembly: turns armed sample ids into the absolute path list the OS drop carries
|
|
// (Windows CF_HDROP / macOS file-list pasteboard) — set algebra only; the shell resolves each id
|
|
// to its on-disk bank file. No temp files; copy-only is enforced at the OS layer (drag_out_win).
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace reasampler::ui {
|
|
|
|
// --- Gesture boundary ---------------------------------------------------------
|
|
|
|
// The panel's client rect, own client coords, top-left origin. Half-open: [x, x+width) x
|
|
// [y, y+height).
|
|
using PanelClientRect = Rect;
|
|
|
|
// Live drag state reduced to what the boundary decision needs. Pre-threshold "armed but not yet
|
|
// dragging" is not a drag for this decision.
|
|
struct DragState {
|
|
bool dragging = false; // threshold crossed; a drag is in progress
|
|
bool hasArmedSamples = false; // payload holds >= 1 sample id
|
|
bool singleCapture = false; // payload holds EXACTLY one sample (arms InstrumentDrop)
|
|
bool overReaperUi = false; // pointer is over REAPER's own UI (shell-supplied)
|
|
};
|
|
|
|
// What the shell should do with the drag given the current pointer position.
|
|
enum class DragGesture {
|
|
None, // no drag under way, or an empty payload
|
|
Internal, // dragging inside the panel — bank-to-bank move/copy
|
|
InstrumentDrop, // single-capture drag left the panel but is over REAPER's UI — shell
|
|
// hover-tracks the TCP FX button; on release adds a preloaded instance
|
|
OsDrag, // dragging with samples, pointer left REAPER entirely — hand to the OS
|
|
};
|
|
|
|
// Decides the gesture for a drag at pointer (px, py) over `client`, given `state`. Position-only
|
|
// + state-only (no hidden state), so re-entry back inside always returns Internal.
|
|
DragGesture decideGesture(int px, int py, const PanelClientRect& client,
|
|
const DragState& state);
|
|
|
|
// --- Path-list assembly -------------------------------------------------------
|
|
|
|
// One armed sample reduced to what path assembly needs: the shell-resolved absolute path (empty
|
|
// if unresolvable) and whether it exists on disk.
|
|
struct ResolvedSample {
|
|
std::string absolutePath;
|
|
bool fileExists = false;
|
|
};
|
|
|
|
// Outcome of assembling the drag's path list. An empty `paths` means nothing draggable — do not
|
|
// start a drag.
|
|
struct PathList {
|
|
std::vector<std::string> paths; // de-duped, existing files, first-seen order
|
|
int skippedMissing = 0; // resolved but file doesn't exist (stale index entry)
|
|
int skippedUnresolved = 0; // shell couldn't resolve a path at all
|
|
int skippedDuplicate = 0; // same absolute path seen more than once
|
|
};
|
|
|
|
// Assembles the drag path list from the resolved samples (selection order). Comparison is
|
|
// exact-string — the shell normalizes case/slashes upstream if it wants Windows-style dedup.
|
|
PathList assemblePathList(const std::vector<ResolvedSample>& resolved);
|
|
|
|
} // namespace reasampler::ui
|