mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-23 17:02:39 +00:00
* Add wxInspector dep * Initial intergration of wxInspector * docs: add wxInspector plugins design spec Design spec for two wxInspector plugins (DPIAware + CustomWidgets) that expose OrcaSlicer's custom control properties in the inspector property grid. Covers: DPIAware scale-factor properties, Button, CheckBox, TextInput, SwitchButton, ProgressBar, Label, and LabeledStaticBox. * docs: add wxInspector plugins implementation plan 6-task plan covering: source changes to existing widget headers, DPIAwarePlugin, CustomWidgetsPlugin, registration helper, MainFrame/CMake wiring, and build verification. * feat: add getters/setters for wxInspector plugin access Add minimal public accessors to DPIAware (set_scale_factor, set_prev_scale_factor, set_em_unit, force_rescale), Button (GetStyle, GetType, IsSelected), CheckBox (IsHalfChecked), TextInput (GetCornerRadius), and LabeledStaticBox (GetCornerRadius, GetBorderWidth, GetBorderColor, GetScale). * feat: add wxInspector plugin registration helper Add RegisterOrcaInspectorPlugins() inline function that creates and registers the DPIAwarePlugin and CustomWidgetsPlugin as static instances (matching wxInspector's built-in pattern). * feat: add DPIAware wxInspector plugin Exposes DPI scaling properties (scale_factor, prev_scale_factor, em_unit, normal_font, force_rescale) on DPIFrame and DPIDialog widgets. Uses dynamic_cast for detection and a template helper to capture the correct static type for lambda accessors. * feat: add OrcaCustomWidgets wxInspector plugin Exposes Orca-specific properties on 7 widget types: - Button: Style, Type, Selected - CheckBox: Half Checked - TextInput: Label, Text Value, Corner Radius - SwitchButton: Value - ProgressBar: Proportion, Show Number - Label: Is Hyperlink, Font Point Size - LabeledStaticBox: Corner Radius, Border Width, Border Color, Scale Each widget type uses dynamic_cast for safe detection. * feat: wire wxInspector plugins into MainFrame and build Call RegisterOrcaInspectorPlugins() in MainFrame constructor after SetupInspectorAccelerator(). Add all 5 plugin source files to SLIC3R_GUI_SOURCES in CMakeLists.txt. * fix: move plugin registration to GUI_App::on_init_inner Register plugins once in app init rather than in MainFrame constructor, which may be recreated during the application lifetime. * fix: include plugin headers in Registration.hpp for complete types Static locals require complete type. Include DPIAwarePlugin.hpp and CustomWidgetsPlugin.hpp instead of forward-declaring. Also remove unused include from MainFrame.cpp (registration moved to GUI_App). * fix: qualify DPIFrame/DPIDialog with Slic3r::GUI namespace * Make DPIDialog inspectable. For other dialogs, we will add them if necessary later. * docs: add spec for moving wxInspectable into DPIAware template Move wxInspector::wxInspectable base class from DPIDialog and MainFrame into the common DPIAware<P> template, making all DPIAware widgets automatically visible in the inspector tree. Co-Authored-By: Claude <noreply@anthropic.com> * docs: add implementation plan for moving wxInspectable into DPIAware Co-Authored-By: Claude <noreply@anthropic.com> * docs: update spec/plan — move SetupInspectorAccelerator into DPIAware too Co-Authored-By: Claude <noreply@anthropic.com> * refactor: move wxInspectable and SetupInspectorAccelerator into DPIAware DPIAware<P> now inherits wxInspector::wxInspectable and calls SetupInspectorAccelerator in its constructor, making all DPIAware widgets automatically appear in the inspector tree with the Ctrl+Shift+I shortcut. DPIDialog now uses 'using' to inherit the constructor. Remove redundant wxInspectable inheritance and SetupInspectorAccelerator calls from DPIDialog and MainFrame. Co-Authored-By: Claude <noreply@anthropic.com> * fix: use LB_HYPERLINK constant instead of magic number 0x0020 Co-Authored-By: Claude <noreply@anthropic.com> * Clean up * Fix Linux build * Don't build wxInspector sample * Use shallow clone * Try fix flatpak build * Attempt to fix build again * Fix build failure caused by https://github.com/wxWidgets/wxWidgets/commit/436c16135ec7ddf580f44624bf74c592aae43b66 * wxWidgets build only download required submodules * This should fix build on Windows on ARM * Enable PIC * Disable layout inspector by default for public release * Use wxInspector 1.0.0 release --------- Co-authored-by: Claude <noreply@anthropic.com>
213 lines
5.2 KiB
C++
213 lines
5.2 KiB
C++
/**
|
|
* @file DevUtil.h
|
|
* @brief Provides common static utility methods for general use.
|
|
*
|
|
* This class offers a collection of static helper functions such as string manipulation,
|
|
* file operations, and other frequently used utilities.
|
|
*/
|
|
|
|
#pragma once
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
|
|
#include <boost/log/trivial.hpp>
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <boost/format.hpp>
|
|
|
|
#include "nlohmann/json.hpp"
|
|
|
|
/* Sequence Id*/
|
|
#define STUDIO_START_SEQ_ID 20000
|
|
#define STUDIO_END_SEQ_ID 30000
|
|
#define CLOUD_SEQ_ID 0
|
|
|
|
namespace Slic3r
|
|
{
|
|
|
|
class DevUtil
|
|
{
|
|
public:
|
|
DevUtil() = delete;
|
|
DevUtil(const DevUtil&) = delete;
|
|
DevUtil& operator=(const DevUtil&) = delete;
|
|
|
|
public:
|
|
static int get_flag_bits(std::string str, int start, int count = 1);
|
|
static int get_flag_bits(int num, int start, int count = 1, int base = 10);
|
|
static uint32_t get_flag_bits_no_border(std::string str, int start_idx, int count = 1);
|
|
|
|
// eg. get_hex_bits(16, 1, 10) = 1
|
|
static int get_hex_bits(int num, int pos, int input_num_base = 10) { return get_flag_bits(num, pos * 4, 4, input_num_base);};
|
|
|
|
static float string_to_float(const std::string& str_value);
|
|
|
|
static std::string convertToIp(long long ip);
|
|
|
|
// sequence id check
|
|
static bool is_studio_cmd(int seq) { return seq >= STUDIO_START_SEQ_ID && seq < STUDIO_END_SEQ_ID;};
|
|
static bool is_cloud_cmd(int seq) { return seq == CLOUD_SEQ_ID;};
|
|
};
|
|
|
|
|
|
class DevJsonValParser
|
|
{
|
|
public:
|
|
template<typename T>
|
|
static T GetVal(const nlohmann::json& j, const std::string& key, const T& default_val = T())
|
|
{
|
|
try
|
|
{
|
|
if (j.contains(key)) { return j[key].get<T>(); }
|
|
}
|
|
catch (const nlohmann::json::exception& e)
|
|
{
|
|
assert(0 && __FUNCTION__);
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what();
|
|
}
|
|
|
|
return default_val;
|
|
}
|
|
|
|
template<typename T>
|
|
static void ParseVal(const nlohmann::json& j, const std::string& key, T& val)
|
|
{
|
|
try
|
|
{
|
|
if (j.contains(key)) { val = j[key].get<T>(); }
|
|
}
|
|
catch (const nlohmann::json::exception& e)
|
|
{
|
|
assert(0 && __FUNCTION__);
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what();
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
static void ParseVal(const nlohmann::json& j, const std::string& key, T& val, T default_val)
|
|
{
|
|
try
|
|
{
|
|
j.contains(key) ? (val = j[key].get<T>()) : (val = default_val);
|
|
}
|
|
catch (const nlohmann::json::exception& e)
|
|
{
|
|
assert(0 && __FUNCTION__);
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what();
|
|
}
|
|
}
|
|
|
|
public:
|
|
static std::string get_longlong_val(const nlohmann::json& j);
|
|
};
|
|
|
|
|
|
struct NumericStrCompare
|
|
{
|
|
bool operator()(const std::string& a, const std::string& b) const noexcept
|
|
{
|
|
int ai = -1;
|
|
try {
|
|
ai = std::stoi(a);
|
|
} catch (...) { };
|
|
|
|
int bi = -1;
|
|
try {
|
|
bi = std::stoi(b);
|
|
} catch (...) { };
|
|
|
|
return ai < bi;
|
|
}
|
|
};
|
|
|
|
enum class DirtyMode{
|
|
COUNTER,
|
|
TIMER
|
|
};
|
|
|
|
template<typename T>
|
|
class DevDirtyHandler{
|
|
public:
|
|
DevDirtyHandler(T init_value, int setting_threshold, DirtyMode mode): m_value(init_value), m_setting_threshold(setting_threshold), m_mode(mode)
|
|
{
|
|
m_threshold = setting_threshold;
|
|
}
|
|
~DevDirtyHandler(){};
|
|
|
|
T GetValue() const { return m_value; };
|
|
|
|
void SetOptimisticValue(const T& data)
|
|
{
|
|
m_value = data;
|
|
m_start_time = time(nullptr);
|
|
m_threshold = m_setting_threshold;
|
|
}
|
|
|
|
void UpdateValue(const T& data)
|
|
{
|
|
if (m_mode == DirtyMode::COUNTER)
|
|
{
|
|
if (m_threshold > 0)
|
|
m_threshold--;
|
|
else
|
|
m_value = data;
|
|
}
|
|
else if (m_mode == DirtyMode::TIMER)
|
|
{
|
|
if (time(nullptr) - m_start_time > m_threshold)
|
|
m_value = data;
|
|
}
|
|
}
|
|
|
|
private:
|
|
T m_value;
|
|
DirtyMode m_mode;
|
|
int m_setting_threshold{0};
|
|
|
|
int m_start_time{0};
|
|
int m_threshold{0};
|
|
};
|
|
|
|
|
|
static std::string s_get_diameter_str(float diameter)
|
|
{
|
|
return (boost::format("%.2f") % diameter).str();
|
|
}
|
|
|
|
static std::string s_get_diameter_str(const std::string& diameter)
|
|
{
|
|
try {
|
|
float dia = boost::lexical_cast<float>(diameter);
|
|
return s_get_diameter_str(dia);
|
|
} catch (...) {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed to boost::lexical_cast: " << diameter;
|
|
return diameter;
|
|
}
|
|
|
|
try {
|
|
float dia = std::stof(diameter);
|
|
return s_get_diameter_str(dia);
|
|
} catch (...) {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " std::stof: " << diameter;
|
|
return diameter;
|
|
}
|
|
}
|
|
|
|
static float s_get_diameter(const std::string& diameter)
|
|
{
|
|
try {
|
|
return boost::lexical_cast<float>(diameter);
|
|
} catch (...) {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed to boost::lexical_cast: " << diameter;
|
|
}
|
|
|
|
try {
|
|
return std::stof(diameter);
|
|
} catch (...) {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " std::stof: " << diameter;
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
}; // namespace Slic3r
|