| 2013 | } |
| 2014 | |
| 2015 | void RenderingController::HandlePUT_mxnSelectedSlice(const httplib::Request& req, httplib::Response& res) const |
| 2016 | { |
| 2017 | const auto id = ReadRequiredPathParam(req, "id"); |
| 2018 | |
| 2019 | if (!IsValidMxNWindowId(id)) |
| 2020 | { |
| 2021 | const auto error = ErrorResponse::InvalidRequest( |
| 2022 | "Malformed MxN window id '" + id + "'. Expected pattern: <prefix>__<bare> with URL-segment-safe characters.", |
| 2023 | req.path); |
| 2024 | this->SendErrorResponse(res, 400, error); |
| 2025 | return; |
| 2026 | } |
| 2027 | |
| 2028 | if (req.body.empty()) |
| 2029 | { |
| 2030 | const auto error = ErrorResponse::InvalidRequest("Request body is required.", req.path); |
| 2031 | this->SendErrorResponse(res, 400, error); |
| 2032 | return; |
| 2033 | } |
| 2034 | |
| 2035 | nlohmann::json body; |
| 2036 | try |
| 2037 | { |
| 2038 | body = nlohmann::json::parse(req.body); |
| 2039 | } |
| 2040 | catch (const nlohmann::json::exception&) |
| 2041 | { |
| 2042 | const auto error = ErrorResponse::InvalidRequest("Invalid JSON body.", req.path); |
| 2043 | this->SendErrorResponse(res, 400, error); |
| 2044 | return; |
| 2045 | } |
| 2046 | |
| 2047 | // MxN slice PUT is step-only. World-anchor moves on a single cell live at |
| 2048 | // the per-cell selected-position resource; global anchor moves at |
| 2049 | // /rendering/selected-position. |
| 2050 | unsigned int step = 0; |
| 2051 | if (const auto err = ParseSliceStepBody(body, |
| 2052 | "MxN selected-slice", |
| 2053 | "Use PUT /rendering/editors/mxn/windows/{id}/selected-position for a per-cell " |
| 2054 | "world anchor, or PUT /rendering/selected-position for the global anchor.", |
| 2055 | step)) |
| 2056 | { |
| 2057 | const auto error = ErrorResponse::InvalidRequest(*err, req.path); |
| 2058 | this->SendErrorResponse(res, 400, error); |
| 2059 | return; |
| 2060 | } |
| 2061 | |
| 2062 | if (m_RenderWindowBridge == nullptr || !m_RenderWindowBridge->HasMxNSelectedSliceStepSetter()) |
| 2063 | { |
| 2064 | const auto error = ErrorResponse::RenderWindowNotAvailable(req.path); |
| 2065 | this->SendErrorResponse(res, 503, error); |
| 2066 | return; |
| 2067 | } |
| 2068 | |
| 2069 | try |
| 2070 | { |
| 2071 | m_RenderWindowBridge->SetMxNSelectedSliceStep(id, step); |
| 2072 | res.status = 204; |