82 lines
3.1 KiB
C++
82 lines
3.1 KiB
C++
#pragma once
|
|
#include "core/ui/rect.h"
|
|
// action_bar — layout + hit-test for the bank_panel's task-grouped toolbars: buttons cluster by
|
|
// task (Capture/Placement/Maintenance/Tagging/Switching); on a narrow panel, whole trailing
|
|
// buttons drop rather than shrink or clip. The destructive Prune button lives separately in
|
|
// prune_button, kept out of this cluster on purpose.
|
|
|
|
#include <vector>
|
|
|
|
namespace reasampler::ui {
|
|
|
|
// Task cluster a button belongs to. Cluster order is caller-supplied via ClusterSpec, not fixed
|
|
// here; a slot just carries which cluster it landed in.
|
|
enum class ActionCluster {
|
|
Capture,
|
|
Placement,
|
|
Maintenance,
|
|
Tagging,
|
|
Switching,
|
|
};
|
|
|
|
using ActionBarRect = Rect;
|
|
|
|
// One visible button's placement, top-left origin. `index` is its position in the caller's flat
|
|
// action list (cluster order), so index also selects the action to fire on a hit. Only buttons
|
|
// that fit get a slot — overflow is dropped whole, never clipped.
|
|
struct ActionBarSlot {
|
|
int index = 0;
|
|
ActionCluster cluster = ActionCluster::Capture;
|
|
int x = 0;
|
|
int y = 0;
|
|
int width = 0;
|
|
int height = 0;
|
|
// Label sub-rect, full button height, horizontally inset so text clears the edge.
|
|
int labelX = 0, labelY = 0, labelW = 0, labelH = 0;
|
|
|
|
bool operator==(const ActionBarSlot& o) const {
|
|
return index == o.index && cluster == o.cluster &&
|
|
x == o.x && y == o.y && width == o.width && height == o.height &&
|
|
labelX == o.labelX && labelY == o.labelY &&
|
|
labelW == o.labelW && labelH == o.labelH;
|
|
}
|
|
};
|
|
|
|
// One cluster's button count, in the order the caller wants it drawn. count == 0 skips the
|
|
// cluster (no gap emitted). Flat action indices run cluster-by-cluster in this order.
|
|
struct ClusterSpec {
|
|
ActionCluster cluster = ActionCluster::Capture;
|
|
int count = 0;
|
|
};
|
|
|
|
// Layout inputs, in pixels; defaults are the bank_panel action-bar metrics.
|
|
struct ActionBarSpec {
|
|
int buttonWidth = 108;
|
|
int buttonGap = 4;
|
|
int clusterGap = 16;
|
|
int sidePad = 8;
|
|
int verticalInset = 3;
|
|
};
|
|
|
|
// How many buttons (from the front) fit at spec.buttonWidth. Split out so the shell can size an
|
|
// overflow affordance without re-deriving it. A bar too narrow for even one button yields 0.
|
|
struct BarFit {
|
|
int visibleCount = 0;
|
|
int hiddenCount = 0;
|
|
};
|
|
|
|
BarFit computeBarFit(const ActionBarRect& bar, const std::vector<ClusterSpec>& clusters,
|
|
const ActionBarSpec& spec);
|
|
|
|
// Lays out the visible buttons (per computeBarFit) left-to-right in cluster order.
|
|
std::vector<ActionBarSlot> computeBarSlots(const ActionBarRect& bar,
|
|
const std::vector<ClusterSpec>& clusters,
|
|
const ActionBarSpec& spec);
|
|
|
|
// Flat action index under (px, py), or -1 for a miss (outside the bar, in a gap, or past the
|
|
// last visible button). Gaps are real dead-zones here, not resolved to the nearest button.
|
|
int hitTestActionBar(int px, int py, const ActionBarRect& bar,
|
|
const std::vector<ClusterSpec>& clusters, const ActionBarSpec& spec);
|
|
|
|
} // namespace reasampler::ui
|