Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Source/Canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,13 @@ bool Canvas::keyPressed(KeyPress const& key)

void Canvas::deselectAll()
{
for (auto obj : selectedComponents){
if (auto* object = dynamic_cast<Object*>(obj.get())){
if (auto& objectGui = object->gui) {
objectGui->geometryLock(true);
}
}
}
selectedComponents.deselectAll();

editor->sidebar->hideParameters();
Expand Down Expand Up @@ -2352,8 +2359,18 @@ void Canvas::setSelected(Component* component, bool shouldNowBeSelected, bool up
{
if (!shouldNowBeSelected) {
selectedComponents.deselect(component);
if (auto* object = dynamic_cast<Object*>(component)){
if (auto& objectGui = object->gui) {
objectGui->geometryLock(true);
}
}
} else {
selectedComponents.addToSelection(component);
if (auto* object = dynamic_cast<Object*>(component)){
if (auto& objectGui = object->gui) {
objectGui->geometryLock(false);
}
}
}

if (updateCommandStatus) {
Expand Down Expand Up @@ -2402,6 +2419,7 @@ void Canvas::findLassoItemsInArea(Array<WeakReference<Component>>& itemsFound, R
for (auto* object : objects) {
if (lassoArea.intersects(object->getSelectableBounds())) {
itemsFound.add(object);
object->geometryLocked = false;
} else if (!ModifierKeys::getCurrentModifiers().isAnyModifierKeyDown()) {
setSelected(object, false, false);
}
Expand Down
3 changes: 3 additions & 0 deletions Source/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,9 @@ void Object::mouseDown(MouseEvent const& e)
return;
}

if (gui->getProperties()["canvas_hovering"].equals(var(true)))
geometryLocked = false;

wasLockedOnMouseDown = false;

if (e.mods.isShiftDown()) {
Expand Down
2 changes: 2 additions & 0 deletions Source/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ class Object : public Component
Value presentationMode;
Value hvccMode = Value(var(false));

bool geometryLocked = false;

Canvas* cnv;
PluginEditor* editor;

Expand Down
102 changes: 79 additions & 23 deletions Source/Objects/CanvasObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

class CanvasObject final : public ObjectBase {

bool locked;
Value sizeProperty = SynchronousValue();
Value hitAreaSize = SynchronousValue();
Rectangle<float> hitArea;
bool hideHitArea = false;

IEMHelper iemHelper;

Expand All @@ -17,11 +19,14 @@ class CanvasObject final : public ObjectBase {
, iemHelper(ptr, object, this)
{
object->setColour(PlugDataColour::outlineColourId, Colours::transparentBlack);
locked = getValue<bool>(object->locked);

objectParameters.addParamSize(&sizeProperty);
objectParameters.addParamInt("Active area size", ParameterCategory::cDimensions, &hitAreaSize, 15);
objectParameters.addParamColour("Canvas color", cGeneral, &iemHelper.secondaryColour, PlugDataColour::guiObjectInternalOutlineColour);
iemHelper.addIemParameters(objectParameters, false, true, 20, 12, 14);

// We use a property as otherwise we will have cyclical dependency between the base class and this
getProperties().set("canvas_hovering", false);
}

void updateSizeProperty() override
Expand All @@ -48,9 +53,34 @@ class CanvasObject final : public ObjectBase {
iemHelper.updateLabel(labels);
}

void updateHitArea()
{
// resize the hit area if the size of the canvas is smaller than the hit area
if (auto iemgui = ptr.get<t_iemgui>()) {
hitArea = Rectangle<float>(iemgui->x_w, iemgui->x_h).withPosition(1, 1);
}
if ((hitArea.getWidth() > (getWidth() - 2)) || (hitArea.getHeight() > (getHeight() - 2))) {
auto shortestLength = jmin(getWidth(), getHeight()) - 2;
hitArea = Rectangle<float>(1, 1, shortestLength, shortestLength);
}
if (getWidth() < 4 || getHeight() < 4) {
hitArea = getLocalBounds().toFloat();
hideHitArea = true;
} else {
hideHitArea = false;
}

repaint();
}

void receiveObjectMessage(hash32 symbol, pd::Atom const atoms[8], int numAtoms) override
{
iemHelper.receiveObjectMessage(symbol, atoms, numAtoms);
switch (symbol) {
case hash("size"):
updateHitArea();
default:
iemHelper.receiveObjectMessage(symbol, atoms, numAtoms);
}
}

void update() override
Expand All @@ -59,6 +89,10 @@ class CanvasObject final : public ObjectBase {
sizeProperty = Array<var> { var(cnvObj->x_vis_w), var(cnvObj->x_vis_h) };
}

if (auto iemgui = ptr.get<t_iemgui>()) {
hitAreaSize = iemgui->x_w;
}

iemHelper.update();
}

Expand All @@ -71,18 +105,41 @@ class CanvasObject final : public ObjectBase {
return {};
}

void resized() override
{
updateHitArea();

ObjectBase::resized();
}

void setIsHovering(bool isHover)
{
if (!getProperties()["canvas_hovering"].equals(var(isHover))) {
getProperties().set("canvas_hovering", isHover);
repaint();
}
}

bool canReceiveMouseEvent(int x, int y) override
{
if (auto iemgui = ptr.get<t_iemgui>()) {
return !locked && Rectangle<int>(iemgui->x_w, iemgui->x_h).contains(x - Object::margin, y - Object::margin);
if (hitArea.contains(x - Object::margin, y - Object::margin)) {
setIsHovering(true);
return true;
};
}

setIsHovering(false);

if (!object->geometryLocked)
return true;

return false;
}

void lock(bool isLocked) override
void geometryLock(bool isLocked) override
{
locked = isLocked;
object->geometryLocked = isLocked;
}

void setPdBounds(Rectangle<int> b) override
Expand Down Expand Up @@ -122,24 +179,15 @@ class CanvasObject final : public ObjectBase {
Colour bgcolour = Colour::fromString(iemHelper.secondaryColour.toString());
auto b = getLocalBounds().toFloat();

nvgFillColor(nvg, convertColour(bgcolour));
nvgBeginPath(nvg);
nvgRoundedRect(nvg, b.getX(), b.getY(), b.getWidth(), b.getHeight(), Corners::objectCornerRadius);
nvgFill(nvg);
auto nvgBgColour = convertColour(bgcolour);
// FIXME: This should be exactly 0.5f of shortest edge, but nanovg doesn't do really small rounded corner radius correctly yet?
auto cornerRadius = jmin(Corners::objectCornerRadius, jmin(getWidth(), getHeight()) * 0.55f);
nvgDrawRoundedRect(nvg, b.getX(), b.getY(), b.getWidth(), b.getHeight(), nvgBgColour, nvgBgColour, cornerRadius);

if (!locked) {
Rectangle<float> draggableRect;
if (auto iemgui = ptr.get<t_iemgui>()) {
draggableRect = Rectangle<float>(iemgui->x_w, iemgui->x_h);
} else {
return;
}

nvgStrokeColor(nvg, convertColour(object->isSelected() ? cnv->editor->getLookAndFeel().findColour(PlugDataColour::objectSelectedOutlineColourId) : bgcolour.contrasting(0.75f)));
nvgStrokeWidth(nvg, 1.0f);
nvgBeginPath(nvg);
nvgRoundedRect(nvg, draggableRect.getX() + 1.0f, draggableRect.getY() + 1.0f, draggableRect.getWidth() - 2.0f, draggableRect.getHeight() - 2.0f, Corners::objectCornerRadius);
nvgStroke(nvg);
if (!getValue<bool>(object->locked) && !hideHitArea) {
auto cornerRadius = jmin(Corners::objectCornerRadius, hitArea.getWidth() * 0.5f);
auto selectionRectColour = convertColour((object->isSelected() || (getProperties()["canvas_hovering"].equals(var(true)))) ? cnv->editor->getLookAndFeel().findColour(PlugDataColour::objectSelectedOutlineColourId) : bgcolour.contrasting(0.75f));
nvgDrawRoundedRect(nvg, hitArea.getX(), hitArea.getY(), hitArea.getWidth(), hitArea.getHeight(), nvgRGBAf(0, 0, 0, 0), selectionRectColour, cornerRadius);
}
}

Expand All @@ -159,6 +207,14 @@ class CanvasObject final : public ObjectBase {
}

object->updateBounds();
} if (v.refersToSameSourceAs(hitAreaSize)) {
auto size = getValue<int>(hitAreaSize);
hitAreaSize = size = jmax(4, size);
if (auto iemgui = ptr.get<t_iemgui>()) {
iemgui->x_w = size;
iemgui->x_h = size;
}
updateHitArea();
} else {
iemHelper.valueChanged(v);
}
Expand Down
2 changes: 2 additions & 0 deletions Source/Objects/ObjectBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ class ObjectBase : public Component
// Objects can override this to do custom locking behaviour
virtual void lock(bool isLocked);

virtual void geometryLock(bool isLocked) {};

// Returns the Pd class name of the object
String getType() const;

Expand Down