During handle dragging, how to limit the dragging area? #631
-
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
Hi there! And welcome :) It's an excellent question. I think this should be a common enough situation, ideally we would have a built-in way to achieve these constraints that you outline. We don't really have that right now. The handle element moves the target using the Even better though is if we implement this functionality on the library side. For example by adding some attributes we could use on the handle element to constrain the movement. Maybe you would like to contribute with something like that? Edit: See update below. |
Beta Was this translation helpful? Give feedback.
-
Hey, I recently had the same problem. But instead of reimplementing the element, as it is not in the public include folder, I implemented a helper class that handles such windows in the same way as the handle element does: class RmlMoveableDocument final : public Rml::EventListener {
public:
RmlMoveableDocument() : document(nullptr) {}
void AttachDocument(Rml::ElementDocument* _document)
{
document = _document;
document->AddEventListener(Rml::EventId::Dragstart, this);
document->AddEventListener(Rml::EventId::Handledrag, this);
document->AddEventListener(Rml::EventId::Resize, this);
}
void DeattachDocument()
{
if (document == nullptr)
{
return;
}
document->RemoveEventListener(Rml::EventId::Resize, this);
document->RemoveEventListener(Rml::EventId::Handledrag, this);
document->RemoveEventListener(Rml::EventId::Dragstart, this);
document = nullptr;
}
void ResetProperties()
{
document->RemoveProperty(Rml::PropertyId::Left);
document->RemoveProperty(Rml::PropertyId::Top);
}
private:
void ProcessEvent(Rml::Event& event) override
{
switch (event.GetId())
{
case Rml::EventId::Dragstart: OnDragStart(); break;
case Rml::EventId::Handledrag: OnDrag(event); break;
case Rml::EventId::Resize: OnResize(); break;
}
}
void OnDragStart() { move_start_position = document->GetAbsoluteOffset(Rml::BoxArea::Border); }
void OnDrag(Rml::Event& event)
{
if (event.GetTargetElement()->HasAttribute("move_target"))
OnMove(event);
}
void OnMove(Rml::Event& event)
{
Rml::Vector2f position = move_start_position;
position.x += event.GetParameter("handle_x", 0.f);
position.y += event.GetParameter("handle_y", 0.f);
ClampPosition(position);
document->SetProperty(Rml::PropertyId::Left, {position.x, Rml::Unit::PX});
document->SetProperty(Rml::PropertyId::Top, {position.y, Rml::Unit::PX});
}
void OnResize() { ResetProperties(); }
void ClampPosition(Rml::Vector2f& position)
{
const Rml::Vector2i dimensions = document->GetContext()->GetDimensions();
const float width = document->GetClientWidth();
const float height = document->GetClientHeight();
position.x = Rml::Math::Clamp(position.x, 0.f, dimensions.x - width);
position.y = Rml::Math::Clamp(position.y, 0.f, dimensions.y - height);
}
private:
Rml::ElementDocument* document;
Rml::Vector2f move_start_position;
}; Feel free to use this snippet and modify it to your needs. The only thing is that the
|
Beta Was this translation helpful? Give feedback.
-
Update: I've pushed several changes now to how the handle element behaves on master. In particular, it now automatically constrains the area that the target can be dragged in to its containing block. This can further be customized with the new So from now on you get the desired behavior from the handle element straight out of the box :) |
Beta Was this translation helpful? Give feedback.
Hi there! And welcome :)
It's an excellent question. I think this should be a common enough situation, ideally we would have a built-in way to achieve these constraints that you outline. We don't really have that right now.
The handle element moves the target using the
left
andtop
properties, as it looks like you've discovered. And it sets them just before issuing thehandledrag
call. So based on that, the code you posted should work in principle. I think one possible issue here, is that the absolute position is not immediately updated, it's only done so after a call to update. I think you would get a more correct x-position if you read theleft
property directly. Another alternative is …