250 lines
7.4 KiB
C++
250 lines
7.4 KiB
C++
#include "DragCanvas.hpp"
|
|
#include "wxExtensions.hpp"
|
|
#include "GUI_App.hpp"
|
|
|
|
namespace Slic3r { namespace GUI {
|
|
|
|
#define CANVAS_WIDTH FromDIP(240)
|
|
#define SHAPE_SIZE FromDIP(20)
|
|
#define SHAPE_GAP (2 * SHAPE_SIZE)
|
|
#define LINE_HEIGHT (SHAPE_SIZE + FromDIP(5))
|
|
static const wxColour CANVAS_BORDER_COLOR = wxColour(0xCECECE);
|
|
|
|
DragCanvas::DragCanvas(wxWindow* parent, const std::vector<std::string>& colors, const std::vector<int>& order)
|
|
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
|
|
, m_drag_mode(DragMode::NONE)
|
|
, m_max_shape_pos(wxPoint(0, 0))
|
|
{
|
|
SetBackgroundColour(*wxWHITE);
|
|
|
|
m_arrow_bmp = create_scaled_bitmap("plate_settings_arrow", this, 16);
|
|
|
|
set_shape_list(colors, order);
|
|
|
|
Bind(wxEVT_PAINT, &DragCanvas::on_paint, this);
|
|
Bind(wxEVT_ERASE_BACKGROUND, &DragCanvas::on_erase, this);
|
|
Bind(wxEVT_LEFT_DOWN, &DragCanvas::on_mouse, this);
|
|
Bind(wxEVT_LEFT_UP, &DragCanvas::on_mouse, this);
|
|
Bind(wxEVT_MOTION, &DragCanvas::on_mouse, this);
|
|
Bind(wxEVT_ENTER_WINDOW, &DragCanvas::on_mouse, this);
|
|
Bind(wxEVT_LEAVE_WINDOW, &DragCanvas::on_mouse, this);
|
|
}
|
|
|
|
DragCanvas::~DragCanvas()
|
|
{
|
|
for (int i = 0; i < m_dragshape_list.size(); i++) {
|
|
delete m_dragshape_list[i];
|
|
}
|
|
m_dragshape_list.clear();
|
|
|
|
if (m_drag_image)
|
|
delete m_drag_image;
|
|
}
|
|
|
|
void DragCanvas::set_shape_list(const std::vector<std::string>& colors, const std::vector<int>& order)
|
|
{
|
|
m_dragshape_list.clear();
|
|
|
|
for (int i = 0; i < order.size(); i++) {
|
|
wxBitmap* bmp = get_extruder_color_icon(colors[order[i] - 1], std::to_string(order[i]), SHAPE_SIZE, SHAPE_SIZE);
|
|
DragShape* shape = new DragShape(*bmp, order[i]);
|
|
m_dragshape_list.push_back(shape);
|
|
}
|
|
|
|
// wrapping lines
|
|
for (int i = 0; i < order.size(); i++) {
|
|
int shape_pos_x = FromDIP(10) + i * SHAPE_GAP;
|
|
int shape_pos_y = FromDIP(5);
|
|
while (shape_pos_x + SHAPE_SIZE > CANVAS_WIDTH) {
|
|
shape_pos_x -= CANVAS_WIDTH;
|
|
shape_pos_y += LINE_HEIGHT;
|
|
|
|
int row = shape_pos_y / LINE_HEIGHT + 1;
|
|
if (row > 1) {
|
|
if (row % 2 == 0) {
|
|
shape_pos_x += (SHAPE_GAP - SHAPE_SIZE);
|
|
}
|
|
else {
|
|
shape_pos_x -= (SHAPE_GAP - SHAPE_SIZE);
|
|
shape_pos_x += SHAPE_GAP;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_max_shape_pos.x = std::max(m_max_shape_pos.x, shape_pos_x);
|
|
m_max_shape_pos.y = std::max(m_max_shape_pos.y, shape_pos_y);
|
|
m_dragshape_list[i]->SetPosition(wxPoint(shape_pos_x, shape_pos_y));
|
|
}
|
|
|
|
int rows = m_max_shape_pos.y / LINE_HEIGHT + 1;
|
|
SetMinSize(wxSize(CANVAS_WIDTH, LINE_HEIGHT * rows + FromDIP(5)));
|
|
}
|
|
|
|
std::vector<int> DragCanvas::get_shape_list_order()
|
|
{
|
|
std::vector<int> res;
|
|
std::vector<DragShape*> ordered_list = get_ordered_shape_list();
|
|
res.reserve(ordered_list.size());
|
|
for (auto& item : ordered_list) {
|
|
res.push_back(item->get_index());
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::vector<DragShape*> DragCanvas::get_ordered_shape_list()
|
|
{
|
|
std::vector<DragShape*> ordered_list = m_dragshape_list;
|
|
std::sort(ordered_list.begin(), ordered_list.end(), [](const DragShape* l, const DragShape* r) {
|
|
if (l->GetPosition().y < r->GetPosition().y)
|
|
return true;
|
|
else if (l->GetPosition().y == r->GetPosition().y) {
|
|
return l->GetPosition().x < r->GetPosition().x;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
});
|
|
return ordered_list;
|
|
}
|
|
|
|
void DragCanvas::on_paint(wxPaintEvent& event)
|
|
{
|
|
wxPaintDC dc(this);
|
|
|
|
for (int i = 0; i < m_dragshape_list.size(); i++) {
|
|
m_dragshape_list[i]->paint(dc, m_dragshape_list[i] == m_slot_shape);
|
|
|
|
auto arrow_pos = m_dragshape_list[i]->GetPosition() - wxSize(SHAPE_GAP - SHAPE_SIZE, 0);
|
|
if (arrow_pos.x < 0) {
|
|
arrow_pos.x = m_max_shape_pos.x;
|
|
arrow_pos.y -= LINE_HEIGHT;
|
|
}
|
|
arrow_pos += wxSize((SHAPE_GAP - SHAPE_SIZE - m_arrow_bmp.GetWidth() / dc.GetContentScaleFactor()) / 2, (SHAPE_SIZE - m_arrow_bmp.GetHeight() / dc.GetContentScaleFactor()) / 2);
|
|
dc.DrawBitmap(m_arrow_bmp, arrow_pos);
|
|
}
|
|
}
|
|
|
|
void DragCanvas::on_erase(wxEraseEvent& event)
|
|
{
|
|
wxSize size = GetSize();
|
|
if (event.GetDC())
|
|
{
|
|
auto& dc = *(event.GetDC());
|
|
dc.SetPen(CANVAS_BORDER_COLOR);
|
|
dc.SetBrush(*wxWHITE_BRUSH);
|
|
dc.DrawRectangle({ 0,0 }, size);
|
|
}
|
|
else
|
|
{
|
|
wxClientDC dc(this);
|
|
dc.SetPen(CANVAS_BORDER_COLOR);
|
|
dc.SetBrush(*wxWHITE_BRUSH);
|
|
dc.DrawRectangle({ 0,0 }, size);
|
|
}
|
|
}
|
|
|
|
void DragCanvas::on_mouse(wxMouseEvent& event)
|
|
{
|
|
if (event.LeftDown())
|
|
{
|
|
DragShape* shape = find_shape(event.GetPosition());
|
|
if (shape)
|
|
{
|
|
m_drag_mode = DragMode::DRAGGING;
|
|
m_drag_start_pos = event.GetPosition();
|
|
m_dragging_shape = shape;
|
|
|
|
if (m_drag_image) {
|
|
delete m_drag_image;
|
|
m_drag_image = nullptr;
|
|
}
|
|
m_drag_image = new wxDragImage(m_dragging_shape->GetBitmap());
|
|
|
|
wxPoint offset = m_drag_start_pos - m_dragging_shape->GetPosition();
|
|
bool success = m_drag_image->BeginDrag(offset, this);
|
|
if (!success)
|
|
{
|
|
delete m_drag_image;
|
|
m_drag_image = nullptr;
|
|
m_drag_mode = DragMode::NONE;
|
|
}
|
|
}
|
|
}
|
|
else if (event.Dragging() && m_drag_mode == DragMode::DRAGGING)
|
|
{
|
|
DragShape* shape = find_shape(event.GetPosition());
|
|
|
|
if (shape) {
|
|
if (shape != m_dragging_shape) {
|
|
m_slot_shape = shape;
|
|
Refresh();
|
|
Update();
|
|
}
|
|
}
|
|
else {
|
|
if (m_slot_shape) {
|
|
m_slot_shape = nullptr;
|
|
Refresh();
|
|
Update();
|
|
}
|
|
}
|
|
m_drag_image->Move(event.GetPosition());
|
|
m_drag_image->Show();
|
|
}
|
|
else if (event.LeftUp() && m_drag_mode != DragMode::NONE)
|
|
{
|
|
m_drag_mode = DragMode::NONE;
|
|
|
|
if (m_drag_image) {
|
|
m_drag_image->Hide();
|
|
m_drag_image->EndDrag();
|
|
|
|
// swap position
|
|
if (m_slot_shape && m_dragging_shape) {
|
|
auto highlighted_pos = m_slot_shape->GetPosition();
|
|
m_slot_shape->SetPosition(m_dragging_shape->GetPosition());
|
|
m_dragging_shape->SetPosition(highlighted_pos);
|
|
m_slot_shape = nullptr;
|
|
m_dragging_shape = nullptr;
|
|
}
|
|
}
|
|
Refresh();
|
|
Update();
|
|
}
|
|
}
|
|
|
|
DragShape* DragCanvas::find_shape(const wxPoint& pt) const
|
|
{
|
|
for (auto& shape : m_dragshape_list) {
|
|
if (shape->hit_test(pt))
|
|
return shape;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
DragShape::DragShape(const wxBitmap& bitmap, int index)
|
|
: m_bitmap(bitmap)
|
|
, m_pos(wxPoint(0,0))
|
|
, m_index(index)
|
|
{
|
|
}
|
|
|
|
bool DragShape::hit_test(const wxPoint& pt) const
|
|
{
|
|
wxRect rect(wxRect(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight()));
|
|
return rect.Contains(pt.x, pt.y);
|
|
}
|
|
|
|
void DragShape::paint(wxDC& dc, bool highlight)
|
|
{
|
|
dc.DrawBitmap(m_bitmap, m_pos);
|
|
if (highlight)
|
|
{
|
|
dc.SetPen(*wxWHITE_PEN);
|
|
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
|
dc.DrawRectangle(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight());
|
|
}
|
|
}
|
|
|
|
}} |