Merge branch 'dev' of https://github.com/prusa3d/Slic3r into full_transform

This commit is contained in:
Enrico Turri 2018-09-14 08:51:06 +02:00
commit 7ef1eb306a
15 changed files with 1327 additions and 559 deletions

View file

@ -5418,6 +5418,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx)
}
m_on_select_object_callback.call(obj_id, vol_id);
Slic3r::GUI::select_current_volume(obj_id, vol_id);
}
std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)

View file

@ -116,7 +116,6 @@ wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr;
PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr;
_3DScene *g_3DScene = nullptr;
wxColour g_color_label_modified;
wxColour g_color_label_sys;
wxColour g_color_label_default;
@ -136,14 +135,9 @@ wxButton* g_wiping_dialog_button = nullptr;
//showed/hided controls according to the view mode
wxWindow *g_right_panel = nullptr;
wxBoxSizer *g_frequently_changed_parameters_sizer = nullptr;
wxBoxSizer *g_expert_mode_part_sizer = nullptr;
wxBoxSizer *g_scrolled_window_sizer = nullptr;
wxBoxSizer *g_info_sizer = nullptr;
wxBoxSizer *g_object_list_sizer = nullptr;
wxButton *g_btn_export_gcode = nullptr;
wxButton *g_btn_export_stl = nullptr;
wxButton *g_btn_reslice = nullptr;
wxButton *g_btn_print = nullptr;
wxButton *g_btn_send_gcode = nullptr;
std::vector<wxButton*> g_buttons;
wxStaticBitmap *g_manifold_warning_icon = nullptr;
bool g_show_print_info = false;
bool g_show_manifold_warning_icon = false;
@ -224,27 +218,36 @@ void set_preset_updater(PresetUpdater *updater)
g_PresetUpdater = updater;
}
void set_3DScene(_3DScene *scene)
enum ActionButtons
{
g_3DScene = scene;
}
abExportGCode,
abReslice,
abPrint,
abSendGCode,
};
void set_objects_from_perl( wxWindow* parent, wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *expert_mode_part_sizer, wxBoxSizer *scrolled_window_sizer,
void set_objects_from_perl( wxWindow* parent,
wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *info_sizer,
wxButton *btn_export_gcode,
wxButton *btn_export_stl, wxButton *btn_reslice,
wxButton *btn_print, wxButton *btn_send_gcode,
wxButton *btn_reslice,
wxButton *btn_print,
wxButton *btn_send_gcode,
wxStaticBitmap *manifold_warning_icon)
{
g_right_panel = parent;
g_right_panel = parent->GetParent();
g_frequently_changed_parameters_sizer = frequently_changed_parameters_sizer;
g_expert_mode_part_sizer = expert_mode_part_sizer;
g_scrolled_window_sizer = scrolled_window_sizer;
g_btn_export_gcode = btn_export_gcode;
g_btn_export_stl = btn_export_stl;
g_btn_reslice = btn_reslice;
g_btn_print = btn_print;
g_btn_send_gcode = btn_send_gcode;
g_info_sizer = info_sizer;
g_buttons.push_back(btn_export_gcode);
g_buttons.push_back(btn_reslice);
g_buttons.push_back(btn_print);
g_buttons.push_back(btn_send_gcode);
// Update font style for buttons
for (auto btn : g_buttons)
btn->SetFont(bold_font());
g_manifold_warning_icon = manifold_warning_icon;
}
@ -934,12 +937,11 @@ wxString from_u8(const std::string &str)
return wxString::FromUTF8(str.c_str());
}
void add_expert_mode_part( wxWindow* parent, wxBoxSizer* sizer,
Model &model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene)
void set_model_events_from_perl(Model &model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene)
{
set_event_object_selection_changed(event_object_selection_changed);
set_event_object_settings_changed(event_object_settings_changed);
@ -1076,7 +1078,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
};
optgroup->append_line(line);
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM, 2);
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2);
m_optgroups.push_back(optgroup);// ogFrequentlyChangingParameters
@ -1103,25 +1105,24 @@ void show_frequently_changed_parameters(bool show)
void show_buttons(bool show)
{
g_btn_export_stl->Show(show);
g_btn_reslice->Show(show);
g_buttons[abReslice]->Show(show);
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) {
TabPrinter *tab = dynamic_cast<TabPrinter*>(g_wxTabPanel->GetPage(i));
if (!tab)
continue;
if (g_PresetBundle->printers.get_selected_preset().printer_technology() == ptFFF) {
g_btn_print->Show(show && !tab->m_config->opt_string("serial_port").empty());
g_btn_send_gcode->Show(show && !tab->m_config->opt_string("print_host").empty());
g_buttons[abPrint]->Show(show && !tab->m_config->opt_string("serial_port").empty());
g_buttons[abSendGCode]->Show(show && !tab->m_config->opt_string("print_host").empty());
}
break;
}
}
void show_info_sizer(bool show)
void show_info_sizer(const bool show, const bool is_update_settings/* = false*/)
{
g_scrolled_window_sizer->Show(static_cast<size_t>(0), show);
g_scrolled_window_sizer->Show(1, show && g_show_print_info);
g_manifold_warning_icon->Show(show && g_show_manifold_warning_icon);
g_info_sizer->Show(static_cast<size_t>(0), show);
g_info_sizer->Show(1, show && g_show_print_info);
g_manifold_warning_icon->Show(show && (!is_update_settings && g_show_manifold_warning_icon));
}
void show_object_name(bool show)
@ -1133,20 +1134,10 @@ void show_object_name(bool show)
void update_mode()
{
wxWindowUpdateLocker noUpdates(g_right_panel);
// TODO There is a not the best place of it!
//*** Update style of the "Export G-code" button****
if (g_btn_export_gcode->GetFont() != bold_font()){
g_btn_export_gcode->SetBackgroundColour(wxColour(252, 77, 1));
g_btn_export_gcode->SetFont(bold_font());
}
// ***********************************
wxWindowUpdateLocker noUpdates(g_right_panel->GetParent());
ConfigMenuIDs mode = get_view_mode();
// show_frequently_changed_parameters(mode >= ConfigMenuModeRegular);
// g_expert_mode_part_sizer->Show(mode == ConfigMenuModeExpert);
g_object_list_sizer->Show(mode == ConfigMenuModeExpert);
show_info_sizer(mode == ConfigMenuModeExpert);
show_buttons(mode == ConfigMenuModeExpert);
@ -1157,7 +1148,7 @@ void update_mode()
// show_collpane_settings(mode == ConfigMenuModeExpert);
// *************************
g_right_panel->Layout();
g_right_panel->GetParent()->GetParent()->Layout();
g_right_panel->GetParent()->Layout();
}
bool is_expert_mode(){
@ -1233,6 +1224,20 @@ void get_current_screen_size(unsigned &width, unsigned &height)
height = disp_size.GetHeight();
}
void enable_action_buttons(bool enable)
{
if (g_buttons.empty())
return;
// Update background colour for buttons
const wxColour bgrd_color = enable ? wxColour(224, 224, 224/*255, 96, 0*/) : wxColour(204, 204, 204);
for (auto btn : g_buttons) {
btn->Enable(enable);
btn->SetBackgroundColour(bgrd_color);
}
}
void about()
{
AboutDialog dlg;

View file

@ -35,7 +35,6 @@ class AppConfig;
class PresetUpdater;
class DynamicPrintConfig;
class TabIface;
class _3DScene;
#define _(s) Slic3r::GUI::I18N::translate((s))
@ -101,13 +100,10 @@ void set_tab_panel(wxNotebook *tab_panel);
void set_app_config(AppConfig *app_config);
void set_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater);
void set_3DScene(_3DScene *scene);
void set_objects_from_perl( wxWindow* parent,
wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *expert_mode_part_sizer,
wxBoxSizer *scrolled_window_sizer,
wxBoxSizer *info_sizer,
wxButton *btn_export_gcode,
wxButton *btn_export_stl,
wxButton *btn_reslice,
wxButton *btn_print,
wxButton *btn_send_gcode,
@ -186,6 +182,8 @@ bool select_language(wxArrayString & names, wxArrayLong & identifiers);
// update right panel of the Plater according to view mode
void update_mode();
void show_info_sizer(const bool show, const bool is_update_settinfs = false);
std::vector<Tab *>& get_tabs_list();
bool checked_tab(Tab* tab);
void delete_tab_from_list(Tab* tab);
@ -204,12 +202,11 @@ wxString L_str(const std::string &str);
// Return wxString from std::string in UTF8
wxString from_u8(const std::string &str);
void add_expert_mode_part( wxWindow* parent, wxBoxSizer* sizer,
Model &model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene);
void set_model_events_from_perl(Model &model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene);
void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer);
// Update view mode according to selected menu
void update_mode();
@ -228,6 +225,9 @@ int get_export_option(wxFileDialog* dlg);
// Returns the dimensions of the screen on which the main frame is displayed
void get_current_screen_size(unsigned &width, unsigned &height);
// Update buttons view according to enable/disable
void enable_action_buttons(bool enable);
// Display an About dialog
extern void about();
// Ask the destop to open the datadir using the default file explorer.

View file

@ -13,6 +13,9 @@
#include "Geometry.hpp"
#include "slic3r/Utils/FixModelByWin10.hpp"
#include <wx/glcanvas.h>
#include "3DScene.hpp"
namespace Slic3r
{
namespace GUI
@ -23,10 +26,12 @@ wxSizer *m_sizer_object_movers = nullptr;
wxDataViewCtrl *m_objects_ctrl = nullptr;
PrusaObjectDataViewModel *m_objects_model = nullptr;
wxCollapsiblePane *m_collpane_settings = nullptr;
PrusaDoubleSlider *m_slider = nullptr;
wxGLCanvas *m_preview_canvas = nullptr;
wxIcon m_icon_modifiermesh;
wxIcon m_icon_solidmesh;
wxIcon m_icon_manifold_warning;
wxBitmap m_icon_modifiermesh;
wxBitmap m_icon_solidmesh;
wxBitmap m_icon_manifold_warning;
wxBitmap m_bmp_cog;
wxBitmap m_bmp_split;
@ -64,8 +69,6 @@ bool m_part_settings_changed = false;
wxString g_selected_extruder = "";
#endif //__WXOSX__
// typedef std::map<std::string, std::string> t_category_icon;
typedef std::map<std::string, wxBitmap> t_category_icon;
inline t_category_icon& get_category_icon() {
static t_category_icon CATEGORY_ICON;
if (CATEGORY_ICON.empty()){
@ -138,11 +141,11 @@ void set_objects_from_model(Model &model) {
}
void init_mesh_icons(){
m_icon_modifiermesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
m_icon_solidmesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
// init icon for manifold warning
m_icon_manifold_warning = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
// init bitmap for "Split to sub-objects" context menu
m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG);
@ -233,7 +236,7 @@ wxDataViewColumn* object_ctrl_create_extruder_column(int extruders_count)
void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz)
{
m_objects_ctrl = new wxDataViewCtrl(win, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_objects_ctrl->SetInitialSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects
m_objects_ctrl->SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects
objects_sz = new wxBoxSizer(wxVERTICAL);
objects_sz->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20);
@ -245,9 +248,10 @@ void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz)
m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT);
#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
// column 0(Icon+Text) of the view control:
m_objects_ctrl->AppendIconTextColumn(_(L("Name")), 0, wxDATAVIEW_CELL_INERT, 200,
wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE);
// column 0(Icon+Text) of the view control:
// And Icon can be consisting of several bitmaps
m_objects_ctrl->AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(),
0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
// column 1 of the view control:
m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45,
@ -278,7 +282,7 @@ wxBoxSizer* create_objects_list(wxWindow *win)
m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) {
object_ctrl_context_menu();
event.Skip();
// event.Skip();
});
m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX
@ -316,15 +320,15 @@ wxBoxSizer* create_edit_object_buttons(wxWindow* win)
//*** button's functions
btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&) {
on_btn_load(win);
// on_btn_load(win);
});
btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) {
on_btn_load(win, true);
// on_btn_load(win, true);
});
btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) {
on_btn_load(win, true, true);
// on_btn_load(win, true, true);
});
btn_delete ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_del(); });
@ -663,7 +667,7 @@ void add_object_to_list(const std::string &name, ModelObject* model_object)
int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
stats.facets_added + stats.facets_reversed + stats.backwards_edges;
if (errors > 0) {
const wxDataViewIconText data(item_name, m_icon_manifold_warning);
const PrusaDataViewBitmapText data(item_name, m_icon_manifold_warning);
wxVariant variant;
variant << data;
m_objects_model->SetValue(variant, item, 0);
@ -736,6 +740,24 @@ void select_current_object(int idx)
g_prevent_list_events = false;
}
void select_current_volume(int idx, int vol_idx)
{
if (vol_idx < 0) {
select_current_object(idx);
return;
}
g_prevent_list_events = true;
m_objects_ctrl->UnselectAll();
if (idx < 0) {
g_prevent_list_events = false;
return;
}
m_objects_ctrl->Select(m_objects_model->GetItemByVolumeId(idx, vol_idx));
part_selection_changed();
g_prevent_list_events = false;
}
void remove()
{
auto item = m_objects_ctrl->GetSelection();
@ -761,8 +783,17 @@ void object_ctrl_selection_changed()
if (m_event_object_selection_changed > 0) {
wxCommandEvent event(m_event_object_selection_changed);
event.SetInt(int(m_objects_model->GetParent(m_objects_ctrl->GetSelection()) != wxDataViewItem(0)));
event.SetId(m_selected_object_id);
event.SetId(m_selected_object_id); // set $obj_idx
const wxDataViewItem item = m_objects_ctrl->GetSelection();
if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0))
event.SetInt(-1); // set $vol_idx
else {
const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
if (vol_idx == -2) // is settings item
event.SetInt(m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item))); // set $vol_idx
else
event.SetInt(vol_idx);
}
get_main_frame()->ProcessWindowEvent(event);
}
@ -775,9 +806,9 @@ void object_ctrl_context_menu()
{
wxDataViewItem item;
wxDataViewColumn* col;
printf("object_ctrl_context_menu\n");
// printf("object_ctrl_context_menu\n");
const wxPoint pt = get_mouse_position_in_control();
printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y);
// printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y);
m_objects_ctrl->HitTest(pt, item, col);
if (!item)
#ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX
@ -791,9 +822,9 @@ void object_ctrl_context_menu()
#else
return;
#endif // __WXOSX__
printf("item exists\n");
// printf("item exists\n");
const wxString title = col->GetTitle();
printf("title = *%s*\n", title.data().AsChar());
// printf("title = *%s*\n", title.data().AsChar());
if (title == " ")
show_context_menu();
@ -839,6 +870,15 @@ void object_ctrl_item_value_change(wxDataViewEvent& event)
}
}
void show_manipulation_og(const bool show)
{
wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer();
if (show == grid_sizer->IsShown(2))
return;
for (size_t id = 2; id < 12; id++)
grid_sizer->Show(id, show);
}
//update_optgroup
void update_settings_list()
{
@ -859,14 +899,19 @@ void update_settings_list()
m_option_sizer->Clear(true);
if (m_config)
bool show_manipulations = true;
const auto item = m_objects_ctrl->GetSelection();
if (m_config && m_objects_model->IsSettingsItem(item))
{
auto extra_column = [](wxWindow* parent, const Line& line)
{
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("erase.png")), wxBITMAP_TYPE_PNG),
auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG),
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
#ifdef __WXMSW__
btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif // __WXMSW__
btn->Bind(wxEVT_BUTTON, [opt_key](wxEvent &event){
(*m_config)->erase(opt_key);
wxTheApp->CallAfter([]() { update_settings_list(); });
@ -876,60 +921,75 @@ void update_settings_list()
std::map<std::string, std::vector<std::string>> cat_options;
auto opt_keys = (*m_config)->keys();
if (opt_keys.size() == 1 && opt_keys[0] == "extruder")
return;
m_og_settings.resize(0);
std::vector<std::string> categories;
if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder"))// return;
{
auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
get_preset_bundle()->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
get_preset_bundle()->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
for (auto& opt_key : opt_keys) {
auto category = (*m_config)->def()->get(opt_key)->category;
if (category.empty() ||
(category == "Extruders" && extruders_cnt == 1)) continue;
for (auto& opt_key : opt_keys) {
auto category = (*m_config)->def()->get(opt_key)->category;
if (category.empty() ||
(category == "Extruders" && extruders_cnt==1)) continue;
std::vector< std::string > new_category;
std::vector< std::string > new_category;
auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category);
cat_opt.push_back(opt_key);
if (cat_opt.size() == 1)
cat_options[category] = cat_opt;
}
auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category);
cat_opt.push_back(opt_key);
if (cat_opt.size() == 1)
cat_options[category] = cat_opt;
}
for (auto& cat : cat_options) {
if (cat.second.size() == 1 && cat.second[0] == "extruder")
continue;
auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, *m_config, false, ogDEFAULT, extra_column);
optgroup->label_width = 150;
optgroup->sidetext_width = 70;
m_og_settings.resize(0);
for (auto& cat : cat_options) {
if (cat.second.size() == 1 && cat.second[0] == "extruder")
continue;
for (auto& opt : cat.second)
{
if (opt == "extruder")
continue;
Option option = optgroup->get_option(opt);
option.opt.width = 70;
optgroup->append_single_option_line(option);
}
optgroup->reload_config();
m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0);
m_og_settings.push_back(optgroup);
auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, *m_config, false, ogDEFAULT, extra_column);
optgroup->label_width = 100;
optgroup->sidetext_width = 70;
categories.push_back(cat.first);
}
}
for (auto& opt : cat.second)
{
if (opt == "extruder")
continue;
Option option = optgroup->get_option(opt);
option.opt.width = 70;
optgroup->append_single_option_line(option);
}
optgroup->reload_config();
m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0);
m_og_settings.push_back(optgroup);
}
if (m_og_settings.empty()) {
m_objects_ctrl->Select(m_objects_model->Delete(item));
part_selection_changed();
}
else {
if (!categories.empty())
m_objects_model->UpdateSettingsDigest(item, categories);
show_manipulations = false;
}
}
show_manipulation_og(show_manipulations);
show_info_sizer(show_manipulations && item && m_objects_model->GetParent(item) == wxDataViewItem(0));
#ifdef __linux__
no_updates.reset(nullptr);
#endif
/*get_right_panel()*/parent->Layout();
get_right_panel()->GetParent()->GetParent()->Layout();
parent->Layout();
get_right_panel()->GetParent()->Layout();
}
void get_settings_choice(wxMenu *menu, int id, bool is_part)
{
auto category_name = menu->GetLabel(id);
const auto category_name = menu->GetLabel(id);
wxArrayString names;
wxArrayInt selections;
@ -977,15 +1037,35 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part)
(*m_config)->set_key_value(opt_key, m_default_config.get()->option(opt_key)->clone());
}
// Add settings item for object
const auto item = m_objects_ctrl->GetSelection();
if (item) {
const auto settings_item = m_objects_model->HasSettings(item);
m_objects_ctrl->Select(settings_item ? settings_item :
m_objects_model->AddSettingsChild(item));
#ifndef __WXOSX__
part_selection_changed();
#endif //no __WXOSX__
}
else
update_settings_list();
}
bool cur_item_hase_children()
{
wxDataViewItemArray children;
if (m_objects_model->GetChildren(m_objects_ctrl->GetSelection(), children) > 0)
return true;
return false;
void menu_item_add_generic(wxMenuItem* &menu, int id) {
auto sub_menu = new wxMenu;
std::vector<std::string> menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") };
for (auto& item : menu_items)
sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item)));
#ifndef __WXMSW__
sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) {
load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString());
});
#endif //no __WXMSW__
menu->SetSubMenu(sub_menu);
}
wxMenuItem* menu_item_split(wxMenu* menu, int id) {
@ -994,11 +1074,11 @@ wxMenuItem* menu_item_split(wxMenu* menu, int id) {
return menu_item;
}
wxMenuItem* menu_item_settings(wxMenu* menu, int id) {
wxMenuItem* menu_item_settings(wxMenu* menu, int id, const bool is_part) {
auto menu_item = new wxMenuItem(menu, id, _(L("Add settings")));
menu_item->SetBitmap(m_bmp_cog);
auto sub_menu = create_add_settings_popupmenu(false);
auto sub_menu = create_add_settings_popupmenu(is_part);
menu_item->SetSubMenu(sub_menu);
return menu_item;
}
@ -1008,44 +1088,54 @@ wxMenu *create_add_part_popupmenu()
wxMenu *menu = new wxMenu;
std::vector<std::string> menu_items = { L("Add part"), L("Add modifier"), L("Add generic") };
wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+2);
wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+4+2);
int i = 0;
for (auto& item : menu_items) {
auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item));
menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh);
menu->Append(menu_item);
if (item == "Add generic")
menu_item_add_generic(menu_item, config_id_base + i);
menu->Append(menu_item);
i++;
}
menu->AppendSeparator();
auto menu_item = menu_item_split(menu, config_id_base + i);
auto menu_item = menu_item_split(menu, config_id_base + i + 4);
menu->Append(menu_item);
menu_item->Enable(!cur_item_hase_children());
menu_item->Enable(is_splittable_object(false));
menu->AppendSeparator();
// Append settings popupmenu
menu->Append(menu_item_settings(menu, config_id_base + i + 1));
menu->Append(menu_item_settings(menu, config_id_base + i + 5, false));
wxWindow* win = get_tab_panel()->GetPage(0);
menu->Bind(wxEVT_MENU, [config_id_base, win, menu](wxEvent &event){
menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){
switch (event.GetId() - config_id_base) {
case 0:
on_btn_load(win);
on_btn_load();
break;
case 1:
on_btn_load(win, true);
on_btn_load(true);
break;
case 2:
on_btn_load(win, true, true);
// on_btn_load(true, true);
break;
case 3:
case 3:
case 4:
case 5:
case 6:
#ifdef __WXMSW__
load_lambda(menu->GetLabel(event.GetId()).ToStdString());
#endif // __WXMSW__
break;
case 7: //3:
on_btn_split(false);
break;
default:{
default:
#ifdef __WXMSW__
get_settings_choice(menu, event.GetId(), false);
break;}
#endif // __WXMSW__
break;
}
});
@ -1057,11 +1147,13 @@ wxMenu *create_part_settings_popupmenu()
wxMenu *menu = new wxMenu;
wxWindowID config_id_base = wxWindow::NewControlId(2);
menu->Append(menu_item_split(menu, config_id_base));
auto menu_item = menu_item_split(menu, config_id_base);
menu->Append(menu_item);
menu_item->Enable(is_splittable_object(true));
menu->AppendSeparator();
// Append settings popupmenu
menu->Append(menu_item_settings(menu, config_id_base + 1));
menu->Append(menu_item_settings(menu, config_id_base + 1, true));
menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){
switch (event.GetId() - config_id_base) {
@ -1093,35 +1185,35 @@ wxMenu *create_add_settings_popupmenu(bool is_part)
wxNullBitmap : categories.at(cat.first));
menu->Append(menu_item);
}
#ifndef __WXMSW__
menu->Bind(wxEVT_MENU, [menu](wxEvent &event) {
get_settings_choice(menu, event.GetId(), true);
});
#endif //no __WXMSW__
return menu;
}
void show_context_menu()
{
auto item = m_objects_ctrl->GetSelection();
const auto item = m_objects_ctrl->GetSelection();
if (item)
{
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
auto menu = create_add_part_popupmenu();
get_tab_panel()->GetPage(0)->PopupMenu(menu);
}
else {
auto menu = create_part_settings_popupmenu();
get_tab_panel()->GetPage(0)->PopupMenu(menu);
}
if (m_objects_model->IsSettingsItem(item))
return;
const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ?
create_add_part_popupmenu() :
create_part_settings_popupmenu();
get_tab_panel()->GetPage(0)->PopupMenu(menu);
}
}
// ******
void load_part( wxWindow* parent, ModelObject* model_object,
void load_part( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier)
{
wxWindow* parent = get_tab_panel()->GetPage(0);
wxArrayString input_files;
open_model(parent, input_files);
for (int i = 0; i < input_files.size(); ++i) {
@ -1159,10 +1251,10 @@ void load_part( wxWindow* parent, ModelObject* model_object,
}
}
void load_lambda( wxWindow* parent, ModelObject* model_object,
void load_lambda( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier)
{
auto dlg = new LambdaObjectDialog(parent);
auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow());
if (dlg->ShowModal() == wxID_CANCEL) {
return;
}
@ -1208,7 +1300,49 @@ void load_lambda( wxWindow* parent, ModelObject* model_object,
m_parts_changed = true;
}
void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/* = false*/)
void load_lambda(const std::string& type_name)
{
if (m_selected_object_id < 0) return;
auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name);
if (dlg->ShowModal() == wxID_CANCEL)
return;
const std::string name = "lambda-"+type_name;
TriangleMesh mesh;
const auto params = dlg->ObjectParameters();
if (type_name == _("Box"))
mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]);
else if (type_name == _("Cylinder"))
mesh = make_cylinder(params.cyl_r, params.cyl_h);
else if (type_name == _("Sphere"))
mesh = make_sphere(params.sph_rho);
else if (type_name == _("Slab")){
const auto& size = (*m_objects)[m_selected_object_id]->bounding_box().size();
mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h);
// box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z
mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z);
}
mesh.repair();
auto new_volume = (*m_objects)[m_selected_object_id]->add_volume(mesh);
new_volume->modifier = true;
new_volume->name = name;
// set a default extruder value, since user can't add it manually
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
m_parts_changed = true;
parts_changed(m_selected_object_id);
m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(),
name, m_icon_modifiermesh));
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
object_ctrl_selection_changed();
#endif //no __WXOSX__ //__WXMSW__
}
void on_btn_load(bool is_modifier /*= false*/, bool is_lambda/* = false*/)
{
auto item = m_objects_ctrl->GetSelection();
if (!item)
@ -1222,19 +1356,54 @@ void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/
if (obj_idx < 0) return;
wxArrayString part_names;
if (is_lambda)
load_lambda(parent, (*m_objects)[obj_idx], part_names, is_modifier);
load_lambda((*m_objects)[obj_idx], part_names, is_modifier);
else
load_part(parent, (*m_objects)[obj_idx], part_names, is_modifier);
load_part((*m_objects)[obj_idx], part_names, is_modifier);
parts_changed(obj_idx);
for (int i = 0; i < part_names.size(); ++i)
m_objects_ctrl->Select( m_objects_model->AddChild(item, part_names.Item(i),
is_modifier ? m_icon_modifiermesh : m_icon_solidmesh));
// part_selection_changed();
#ifdef __WXMSW__
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
object_ctrl_selection_changed();
#endif //__WXMSW__
#endif //no __WXOSX__//__WXMSW__
}
void remove_settings_from_config()
{
auto opt_keys = (*m_config)->keys();
if (opt_keys.size() == 1 && opt_keys[0] == "extruder")
return;
int extruder = -1;
if ((*m_config)->has("extruder"))
extruder = (*m_config)->option<ConfigOptionInt>("extruder")->value;
(*m_config)->clear();
if (extruder >=0 )
(*m_config)->set_key_value("extruder", new ConfigOptionInt(extruder));
}
bool remove_subobject_from_object(const int volume_id)
{
const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
// if user is deleting the last solid part, throw error
int solid_cnt = 0;
for (auto vol : (*m_objects)[m_selected_object_id]->volumes)
if (!vol->modifier)
++solid_cnt;
if (!volume->modifier && solid_cnt == 1) {
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
return false;
}
(*m_objects)[m_selected_object_id]->delete_volume(volume_id);
m_parts_changed = true;
parts_changed(m_selected_object_id);
return true;
}
void on_btn_del()
@ -1242,50 +1411,67 @@ void on_btn_del()
auto item = m_objects_ctrl->GetSelection();
if (!item) return;
auto volume_id = m_objects_model->GetVolumeIdByItem(item);
if (volume_id < 0)
const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
if (volume_id ==-1)
return;
auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
// if user is deleting the last solid part, throw error
int solid_cnt = 0;
for (auto vol : (*m_objects)[m_selected_object_id]->volumes)
if (!vol->modifier)
++solid_cnt;
if (!volume->modifier && solid_cnt == 1) {
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
return;
}
(*m_objects)[m_selected_object_id]->delete_volume(volume_id);
m_parts_changed = true;
parts_changed(m_selected_object_id);
if (volume_id ==-2)
remove_settings_from_config();
else if (!remove_subobject_from_object(volume_id))
return;
m_objects_ctrl->Select(m_objects_model->Delete(item));
part_selection_changed();
// #ifdef __WXMSW__
// object_ctrl_selection_changed();
// #endif //__WXMSW__
}
bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume)
{
if (!item || m_selected_object_id < 0)
return false;
const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
if (volume_id < 0) {
if (split_part) return false;
volume = (*m_objects)[m_selected_object_id]->volumes[0];
}
else
volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
if (volume)
return true;
return false;
}
bool is_splittable_object(const bool split_part)
{
const wxDataViewItem item = m_objects_ctrl->GetSelection();
if (!item) return false;
wxDataViewItemArray children;
if (!split_part && m_objects_model->GetChildren(item, children) > 0)
return false;
ModelVolume* volume;
if (!get_volume_by_item(split_part, item, volume) || !volume)
return false;
TriangleMeshPtrs meshptrs = volume->mesh.split();
if (meshptrs.size() <= 1) {
delete meshptrs.front();
return false;
}
return true;
}
void on_btn_split(const bool split_part)
{
auto item = m_objects_ctrl->GetSelection();
const auto item = m_objects_ctrl->GetSelection();
if (!item || m_selected_object_id<0)
return;
auto volume_id = m_objects_model->GetVolumeIdByItem(item);
ModelVolume* volume;
if (volume_id < 0) {
if (split_part) return;
else
volume = (*m_objects)[m_selected_object_id]->volumes[0]; }
else
volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config;
auto nozzle_dmrs_cnt = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
auto split_rez = volume->split(nozzle_dmrs_cnt);
if (split_rez == 1) {
if (!get_volume_by_item(split_part, item, volume)) return;
DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config;
const auto nozzle_dmrs_cnt = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
if (volume->split(nozzle_dmrs_cnt) == 1) {
wxMessageBox(_(L("The selected object couldn't be split because it contains only one part.")));
return;
}
@ -1299,7 +1485,8 @@ void on_btn_split(const bool split_part)
for (auto id = 0; id < model_object->volumes.size(); id++)
m_objects_model->AddChild(parent, model_object->volumes[id]->name,
model_object->volumes[id]->modifier ? m_icon_modifiermesh : m_icon_solidmesh,
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
model_object->volumes[id]->config.has("extruder") ?
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
false);
m_objects_ctrl->Expand(parent);
@ -1308,10 +1495,14 @@ void on_btn_split(const bool split_part)
for (auto id = 0; id < model_object->volumes.size(); id++)
m_objects_model->AddChild(item, model_object->volumes[id]->name,
m_icon_solidmesh,
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
model_object->volumes[id]->config.has("extruder") ?
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
false);
m_objects_ctrl->Expand(item);
}
m_parts_changed = true;
parts_changed(m_selected_object_id);
}
void on_btn_move_up(){
@ -1392,33 +1583,49 @@ void part_selection_changed()
auto item = m_objects_ctrl->GetSelection();
int obj_idx = -1;
auto og = get_optgroup(ogFrequentlyObjectSettings);
m_config = nullptr;
wxString object_name = wxEmptyString;
if (item)
{
const bool is_settings_item = m_objects_model->IsSettingsItem(item);
bool is_part = false;
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
wxString og_name = wxEmptyString;
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
obj_idx = m_objects_model->GetIdByItem(item);
og->set_name(" " + _(L("Object Settings")) + " ");
og_name = _(L("Object manipulation"));
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config);
}
else {
auto parent = m_objects_model->GetParent(item);
// Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
// Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
obj_idx = m_objects_model->GetIdByItem(parent);
og->set_name(" " + _(L("Part Settings")) + " ");
is_part = true;
auto volume_id = m_objects_model->GetVolumeIdByItem(item);
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
if (is_settings_item) {
if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) {
og_name = _(L("Object Settings to modify"));
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config);
}
else {
og_name = _(L("Part Settings to modify"));
is_part = true;
auto main_parent = m_objects_model->GetParent(parent);
obj_idx = m_objects_model->GetIdByItem(main_parent);
const auto volume_id = m_objects_model->GetVolumeIdByItem(parent);
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
}
}
else {
og_name = _(L("Part manipulation"));
is_part = true;
const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
}
}
auto config = m_config;
og->set_value("object_name", m_objects_model->GetName(item));
og->set_name(" " + og_name + " ");
object_name = m_objects_model->GetName(item);
m_default_config = std::make_shared<DynamicPrintConfig>(*DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)));
}
else {
wxString empty_str = wxEmptyString;
og->set_value("object_name", empty_str);
m_config = nullptr;
}
og->set_value("object_name", object_name);
update_settings_list();
@ -1647,7 +1854,7 @@ void on_begin_drag(wxDataViewEvent &event)
wxDataViewItem item(event.GetItem());
// only allow drags for item, not containers
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) {
event.Veto();
return;
}
@ -1671,7 +1878,7 @@ void on_drop_possible(wxDataViewEvent &event)
// only allow drags for item or background, not containers
if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
event.GetDataFormat() != wxDF_UNICODETEXT)
event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item))
event.Veto();
}
@ -1681,7 +1888,7 @@ void on_drop(wxDataViewEvent &event)
// only allow drops for item, not containers
if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
event.GetDataFormat() != wxDF_UNICODETEXT) {
event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) {
event.Veto();
return;
}
@ -1709,6 +1916,9 @@ void on_drop(wxDataViewEvent &event)
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id+=delta, cnt++)
std::swap(volumes[id], volumes[id +delta]);
m_parts_changed = true;
parts_changed(m_selected_object_id);
g_prevent_list_events = false;
}
@ -1725,5 +1935,103 @@ void update_objects_list_extruder_column(int extruders_count)
set_extruder_column_hidden(extruders_count <= 1);
}
void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas)
{
m_slider = new PrusaDoubleSlider(parent, wxID_ANY, 0, 0, 0, 100);
sizer->Add(m_slider, 0, wxEXPAND, 0);
m_preview_canvas = canvas;
m_preview_canvas->Bind(wxEVT_KEY_DOWN, update_double_slider_from_canvas);
m_slider->Bind(wxEVT_SCROLL_CHANGED, [parent](wxEvent& event) {
_3DScene::set_toolpaths_range(m_preview_canvas, m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6);
if (parent->IsShown())
m_preview_canvas->Refresh();
});
}
void fill_slider_values(std::vector<std::pair<int, double>> &values,
const std::vector<double> &layers_z)
{
std::vector<double> layers_all_z = _3DScene::get_current_print_zs(m_preview_canvas, false);
if (layers_all_z.size() == layers_z.size())
for (int i = 0; i < layers_z.size(); i++)
values.push_back(std::pair<int, double>(i+1, layers_z[i]));
else if (layers_all_z.size() > layers_z.size()) {
int cur_id = 0;
for (int i = 0; i < layers_z.size(); i++)
for (int j = cur_id; j < layers_all_z.size(); j++)
if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) {
values.push_back(std::pair<int, double>(j+1, layers_z[i]));
cur_id = j;
break;
}
}
}
void set_double_slider_thumbs( const bool force_sliders_full_range,
const std::vector<double> &layers_z,
const double z_low, const double z_high)
{
// Force slider full range only when slider is created.
// Support selected diapason on the all next steps
if (/*force_sliders_full_range*/z_high == 0.0) {
m_slider->SetLowerValue(0);
m_slider->SetHigherValue(layers_z.size() - 1);
return;
}
for (int i = layers_z.size() - 1; i >= 0; i--)
if (z_low >= layers_z[i]) {
m_slider->SetLowerValue(i);
break;
}
for (int i = layers_z.size() - 1; i >= 0 ; i--)
if (z_high >= layers_z[i]) {
m_slider->SetHigherValue(i);
break;
}
}
void update_double_slider(bool force_sliders_full_range)
{
std::vector<std::pair<int, double>> values;
std::vector<double> layers_z = _3DScene::get_current_print_zs(m_preview_canvas, true);
fill_slider_values(values, layers_z);
const double z_low = m_slider->GetLowerValueD();
const double z_high = m_slider->GetHigherValueD();
m_slider->SetMaxValue(layers_z.size() - 1);
m_slider->SetSliderValues(values);
set_double_slider_thumbs(force_sliders_full_range, layers_z, z_low, z_high);
}
void reset_double_slider()
{
m_slider->SetHigherValue(0);
m_slider->SetLowerValue(0);
}
void update_double_slider_from_canvas(wxKeyEvent& event)
{
if (event.HasModifiers()) {
event.Skip();
return;
}
const auto key = event.GetKeyCode();
if (key == 'U' || key == 'D') {
const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1;
m_slider->SetHigherValue(new_pos);
if (event.ShiftDown()) m_slider->SetLowerValue(m_slider->GetHigherValue());
}
else if (key == 'S')
m_slider->ChangeOneLayerLock();
else
event.Skip();
}
} //namespace GUI
} //namespace Slic3r

View file

@ -9,13 +9,15 @@ class wxArrayString;
class wxMenu;
class wxDataViewEvent;
class wxKeyEvent;
class wxControl;
class wxGLCanvas;
class wxBitmap;
namespace Slic3r {
class ModelObject;
class Model;
namespace GUI {
//class wxGLCanvas;
enum ogGroup{
ogFrequentlyChangingParameters,
@ -44,6 +46,9 @@ struct OBJECT_PARAMETERS
double slab_z = 0.0;
};
typedef std::map<std::string, wxBitmap> t_category_icon;
inline t_category_icon& get_category_icon();
void add_collapsible_panes(wxWindow* parent, wxBoxSizer* sizer);
void add_objects_list(wxWindow* parent, wxBoxSizer* sizer);
void add_object_settings(wxWindow* parent, wxBoxSizer* sizer);
@ -66,16 +71,17 @@ void set_object_count(int idx, int count);
void unselect_objects();
// Select current object in the list on c++ side
void select_current_object(int idx);
// Select current volume in the list on c++ side
void select_current_volume(int idx, int vol_idx);
// Remove objects/sub-object from the list
void remove();
//void create_double_slider(wxWindow* parent, wxControl* slider);
void object_ctrl_selection_changed();
void object_ctrl_context_menu();
void object_ctrl_key_event(wxKeyEvent& event);
void object_ctrl_item_value_change(wxDataViewEvent& event);
void show_context_menu();
bool is_splittable_object(const bool split_part);
void init_mesh_icons();
void set_event_object_selection_changed(const int& event);
@ -87,13 +93,14 @@ void set_objects_from_model(Model &model);
bool is_parts_changed();
bool is_part_settings_changed();
void load_part( wxWindow* parent, ModelObject* model_object,
void load_part( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier);
void load_lambda(wxWindow* parent, ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier);
void load_lambda( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier);
void load_lambda( const std::string& type_name);
void on_btn_load(wxWindow* parent, bool is_modifier = false, bool is_lambda = false);
void on_btn_load(bool is_modifier = false, bool is_lambda = false);
void on_btn_del();
void on_btn_split(const bool split_part);
void on_btn_move_up();
@ -126,6 +133,13 @@ void on_drop(wxDataViewEvent &event);
// update extruder column for objects_ctrl according to extruders count
void update_objects_list_extruder_column(int extruders_count);
// Create/Update/Reset double slider on 3dPreview
void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas);
void update_double_slider(bool force_sliders_full_range);
void reset_double_slider();
// update DoubleSlider after keyDown in canvas
void update_double_slider_from_canvas(wxKeyEvent& event);
} //namespace GUI
} //namespace Slic3r
#endif //slic3r_GUI_ObjectParts_hpp_

View file

@ -10,10 +10,12 @@ namespace GUI
{
static wxString dots("", wxConvUTF8);
LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent,
const wxString type_name):
m_type_name(type_name)
{
Create(parent, wxID_ANY, _(L("Lambda Object")),
wxDefaultPosition, wxDefaultSize,
parent->GetScreenPosition(), wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
// instead of double dim[3] = { 1.0, 1.0, 1.0 };
@ -24,11 +26,20 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
sizer = new wxBoxSizer(wxVERTICAL);
// modificator options
m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxCHB_TOP);
sizer->Add(m_modificator_options_book, 1, wxEXPAND| wxALL, 10);
if (m_type_name == wxEmptyString) {
m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxCHB_TOP);
sizer->Add(m_modificator_options_book, 1, wxEXPAND | wxALL, 10);
}
else {
m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
sizer->Add(m_panel, 1, wxEXPAND | wxALL, 10);
}
ConfigOptionDef def;
def.width = 70;
auto optgroup = init_modificator_options_page(_(L("Box")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
int opt_id = opt_key == "l" ? 0 :
opt_key == "w" ? 1 :
@ -37,8 +48,6 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
object_parameters.dim[opt_id] = boost::any_cast<double>(value);
};
ConfigOptionDef def;
def.width = 70;
def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("L");
@ -52,8 +61,10 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
def.label = L("H");
option = Option(def, "h");
optgroup->append_single_option_line(option);
}
optgroup = init_modificator_options_page(_(L("Cylinder")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
int val = boost::any_cast<int>(value);
if (opt_key == "cyl_r")
@ -66,14 +77,16 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
def.type = coInt;
def.default_value = new ConfigOptionInt{ 1 };
def.label = L("Radius");
option = Option(def, "cyl_r");
auto option = Option(def, "cyl_r");
optgroup->append_single_option_line(option);
def.label = L("Height");
option = Option(def, "cyl_h");
optgroup->append_single_option_line(option);
}
optgroup = init_modificator_options_page(_(L("Sphere")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
if (opt_key == "sph_rho")
object_parameters.sph_rho = boost::any_cast<double>(value);
@ -83,10 +96,12 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("Rho");
option = Option(def, "sph_rho");
auto option = Option(def, "sph_rho");
optgroup->append_single_option_line(option);
}
optgroup = init_modificator_options_page(_(L("Slab")));
if (optgroup){
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
double val = boost::any_cast<double>(value);
if (opt_key == "slab_z")
@ -96,13 +111,16 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
else return;
};
def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("H");
option = Option(def, "slab_h");
auto option = Option(def, "slab_h");
optgroup->append_single_option_line(option);
def.label = L("Initial Z");
option = Option(def, "slab_z");
optgroup->append_single_option_line(option);
}
Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e)
{
@ -127,8 +145,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
}
}));
auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
const auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxButton* btn_OK = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
btn_OK->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
@ -155,9 +172,11 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
// Called from the constructor.
// Create a panel for a rectangular / circular / custom bed shape.
ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString title){
ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(const wxString& title){
if (!m_type_name.IsEmpty() && m_type_name != title)
return nullptr;
auto panel = new wxPanel(m_modificator_options_book);
auto panel = m_type_name.IsEmpty() ? new wxPanel(m_modificator_options_book) : m_panel;
ConfigOptionsGroupShp optgroup;
optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Add")) + " " +title + " " +dots);
@ -165,8 +184,12 @@ ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString
m_optgroups.push_back(optgroup);
panel->SetSizerAndFit(optgroup->sizer);
m_modificator_options_book->AddPage(panel, title);
if (m_type_name.IsEmpty()) {
panel->SetSizerAndFit(optgroup->sizer);
m_modificator_options_book->AddPage(panel, title);
}
else
panel->SetSizer(optgroup->sizer);
return optgroup;
}

View file

@ -7,6 +7,8 @@
#include <wx/sizer.h>
#include <wx/choicebk.h>
class wxPanel;
namespace Slic3r
{
namespace GUI
@ -14,16 +16,19 @@ namespace GUI
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
class LambdaObjectDialog : public wxDialog
{
wxChoicebook* m_modificator_options_book;
wxChoicebook* m_modificator_options_book = nullptr;
std::vector <ConfigOptionsGroupShp> m_optgroups;
wxString m_type_name;
wxPanel* m_panel = nullptr;
public:
LambdaObjectDialog(wxWindow* parent);
LambdaObjectDialog(wxWindow* parent,
const wxString type_name = wxEmptyString);
~LambdaObjectDialog(){}
bool CanClose() { return true; } // ???
OBJECT_PARAMETERS& ObjectParameters(){ return object_parameters; }
ConfigOptionsGroupShp init_modificator_options_page(wxString title);
ConfigOptionsGroupShp init_modificator_options_page(const wxString& title);
// Note whether the window was already closed, so a pending update is not executed.
bool m_already_closed = false;

View file

@ -158,7 +158,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// if we have an extra column, build it
if (extra_column) {
if (extra_column) {
grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL, 0);
grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3);
}
else {
// if the callback provides no sizer for the extra cell, put a spacer

View file

@ -161,8 +161,10 @@ public:
ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt),
staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){
stb = new wxStaticBox(_parent, wxID_ANY, title);
stb->SetFont(bold_font());
if (staticbox) {
stb = new wxStaticBox(_parent, wxID_ANY, title);
stb->SetFont(bold_font());
}
sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
auto num_columns = 1U;
if (label_width != 0) num_columns++;

View file

@ -2,6 +2,7 @@
#include "GUI.hpp"
#include "../../libslic3r/Utils.hpp"
#include "BitmapCache.hpp"
#include <wx/sizer.h>
#include <wx/statline.h>
@ -357,11 +358,53 @@ void PrusaObjectDataViewModelNode::set_part_action_icon() {
m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG);
}
Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector<std::string>& categories)
{
if (m_type != "settings" || m_opt_categories == categories)
return false;
m_opt_categories = categories;
m_name = wxEmptyString;
m_icon = m_empty_icon;
auto categories_icon = Slic3r::GUI::get_category_icon();
for (auto& cat : m_opt_categories)
m_name += cat + "; ";
wxBitmap *bmp = m_bitmap_cache->find(m_name.ToStdString());
if (bmp == nullptr) {
std::vector<wxBitmap> bmps;
for (auto& cat : m_opt_categories)
bmps.emplace_back(categories_icon.find(cat) == categories_icon.end() ?
wxNullBitmap : categories_icon.at(cat));
bmp = m_bitmap_cache->insert(m_name.ToStdString(), bmps);
}
m_bmp = *bmp;
return true;
}
// *****************************************************************************
// ----------------------------------------------------------------------------
// PrusaObjectDataViewModel
// ----------------------------------------------------------------------------
PrusaObjectDataViewModel::PrusaObjectDataViewModel()
{
m_bitmap_cache = new Slic3r::GUI::BitmapCache;
}
PrusaObjectDataViewModel::~PrusaObjectDataViewModel()
{
for (auto object : m_objects)
delete object;
delete m_bitmap_cache;
m_bitmap_cache = nullptr;
}
wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name)
{
auto root = new PrusaObjectDataViewModelNode(name);
@ -386,34 +429,50 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int ins
wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_item,
const wxString &name,
const wxIcon& icon,
const wxBitmap& icon,
const int extruder/* = 0*/,
const bool create_frst_child/* = true*/)
{
PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID();
if (!root) return wxDataViewItem(0);
wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder);
const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder);
if (root->GetChildren().Count() == 0 && create_frst_child)
if (create_frst_child && (root->GetChildren().Count() == 0 ||
(root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == "settings")))
{
auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0);
const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);
const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0);
root->Append(node);
// notify control
wxDataViewItem child((void*)node);
const wxDataViewItem child((void*)node);
ItemAdded(parent_item, child);
}
auto volume_id = root->GetChildCount();
auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id);
const auto volume_id = root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == "settings" ?
root->GetChildCount() - 1 : root->GetChildCount();
const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id);
root->Append(node);
// notify control
wxDataViewItem child((void*)node);
const wxDataViewItem child((void*)node);
ItemAdded(parent_item, child);
return child;
}
wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem &parent_item)
{
PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID();
if (!root) return wxDataViewItem(0);
const auto node = new PrusaObjectDataViewModelNode(root);
root->Insert(node, 0);
// notify control
const wxDataViewItem child((void*)node);
ItemAdded(parent_item, child);
return child;
}
wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
{
auto ret_item = wxDataViewItem(0);
@ -438,7 +497,7 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
//update volume_id value for remaining child-nodes
auto children = node_parent->GetChildren();
for (size_t i = 0; i < node_parent->GetChildCount(); i++)
for (size_t i = 0; i < node_parent->GetChildCount() && v_id>=0; i++)
{
auto volume_id = children[i]->GetVolumeId();
if (volume_id > v_id)
@ -460,9 +519,10 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
delete node;
// set m_containet to FALSE if parent has no child
if (node_parent && node_parent->GetChildCount() == 0){
if (node_parent) {
#ifndef __WXGTK__
node_parent->m_container = false;
if (node_parent->GetChildCount() == 0)
node_parent->m_container = false;
#endif //__WXGTK__
ret_item = parent;
}
@ -522,6 +582,26 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemById(int obj_idx)
}
wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_idx)
{
if (obj_idx >= m_objects.size()) {
printf("Error! Out of objects range.\n");
return wxDataViewItem(0);
}
auto parent = m_objects[obj_idx];
if (parent->GetChildCount() == 0) {
printf("Error! Object has no one volume.\n");
return wxDataViewItem(0);
}
for (size_t i = 0; i < parent->GetChildCount(); i++)
if (parent->GetNthChild(i)->m_volume_id == volume_idx)
return wxDataViewItem(parent->GetNthChild(i));
return wxDataViewItem(0);
}
int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item)
{
wxASSERT(item.IsOk());
@ -534,7 +614,7 @@ int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item)
return it - m_objects.begin();
}
int PrusaObjectDataViewModel::GetVolumeIdByItem(wxDataViewItem& item)
int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item)
{
wxASSERT(item.IsOk());
@ -568,6 +648,12 @@ wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const
return node->m_icon;
}
wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const
{
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
return node->m_bmp;
}
void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const
{
wxASSERT(item.IsOk());
@ -576,8 +662,8 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem
switch (col)
{
case 0:{
const wxDataViewIconText data(node->m_name, node->m_icon);
variant << data;
const PrusaDataViewBitmapText data(node->m_name, node->m_bmp);
variant << data;
break;}
case 1:
variant = node->m_copy;
@ -667,26 +753,35 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i
if (!node_parent) // happens if item.IsOk()==false
return ret_item;
PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id);
const size_t shift = node_parent->GetChildren().Item(0)->m_type == "settings" ? 1 : 0;
PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift);
node_parent->GetChildren().Remove(deleted_node);
ItemDeleted(parent, wxDataViewItem(deleted_node));
node_parent->Insert(deleted_node, new_volume_id);
node_parent->Insert(deleted_node, new_volume_id+shift);
ItemAdded(parent, wxDataViewItem(deleted_node));
const auto settings_item = HasSettings(wxDataViewItem(deleted_node));
if (settings_item)
ItemAdded(wxDataViewItem(deleted_node), settings_item);
//update volume_id value for child-nodes
auto children = node_parent->GetChildren();
int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id;
int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id;
for (int id = id_frst; id <= id_last; ++id)
children[id]->SetVolumeId(id);
children[id+shift]->SetVolumeId(id);
return wxDataViewItem(node_parent->GetNthChild(new_volume_id));
return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift));
}
// bool MyObjectTreeModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const
// {
//
// }
bool PrusaObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const
{
wxASSERT(item.IsOk());
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
// disable extruder selection for the "Settings" item
return !(col == 2 && node->m_extruder.IsEmpty());
}
wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) const
{
@ -738,6 +833,87 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent,
return count;
}
wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const
{
if (!item.IsOk())
return wxDataViewItem(0);
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
if (node->GetChildCount() == 0)
return wxDataViewItem(0);
auto& children = node->GetChildren();
if (children[0]->m_type == "settings")
return wxDataViewItem((void*)children[0]);;
return wxDataViewItem(0);
}
bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const
{
if (!item.IsOk())
return false;
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
return node->m_type == "settings";
}
void PrusaObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item,
const std::vector<std::string>& categories)
{
if (!item.IsOk()) return;
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
if (!node->update_settings_digest(categories))
return;
ItemChanged(item);
}
IMPLEMENT_VARIANT_OBJECT(PrusaDataViewBitmapText)
// ---------------------------------------------------------
// PrusaIconTextRenderer
// ---------------------------------------------------------
bool PrusaBitmapTextRenderer::SetValue(const wxVariant &value)
{
m_value << value;
return true;
}
bool PrusaBitmapTextRenderer::GetValue(wxVariant& WXUNUSED(value)) const
{
return false;
}
bool PrusaBitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state)
{
int xoffset = 0;
const wxBitmap& icon = m_value.GetBitmap();
if (icon.IsOk())
{
dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon.GetHeight()) / 2);
xoffset = icon.GetWidth() + 4;
}
RenderText(m_value.GetText(), xoffset, rect, dc, state);
return true;
}
wxSize PrusaBitmapTextRenderer::GetSize() const
{
if (!m_value.GetText().empty())
{
wxSize size = GetTextExtent(m_value.GetText());
if (m_value.GetBitmap().IsOk())
size.x += m_value.GetBitmap().GetWidth() + 4;
return size;
}
return wxSize(80, 20);
}
// ----------------------------------------------------------------------------
// PrusaDoubleSlider
@ -829,16 +1005,28 @@ wxSize PrusaDoubleSlider::DoGetBestSize() const
void PrusaDoubleSlider::SetLowerValue(const int lower_val)
{
m_selection = ssLower;
m_lower_value = lower_val;
correct_lower_value();
Refresh();
Update();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
}
void PrusaDoubleSlider::SetHigherValue(const int higher_val)
{
m_selection = ssHigher;
m_higher_value = higher_val;
correct_higher_value();
Refresh();
Update();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
}
void PrusaDoubleSlider::SetMaxValue(const int max_value)
@ -905,6 +1093,13 @@ void PrusaDoubleSlider::get_size(int *w, int *h)
is_horizontal() ? *w -= m_lock_icon_dim : *h -= m_lock_icon_dim;
}
double PrusaDoubleSlider::get_double_value(const SelectedSlider& selection) const
{
if (m_values.empty())
return 0.0;
return m_values[selection == ssLower ? m_lower_value : m_higher_value].second;
}
void PrusaDoubleSlider::get_lower_and_higher_position(int& lower_pos, int& higher_pos)
{
const double step = get_scroll_step();
@ -1010,7 +1205,7 @@ wxString PrusaDoubleSlider::get_label(const SelectedSlider& selection) const
void PrusaDoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const
{
if (m_is_one_layer && selection != m_selection || !selection)
if ((m_is_one_layer || m_higher_value==m_lower_value) && selection != m_selection || !selection)
return;
wxCoord text_width, text_height;
const wxString label = get_label(selection);
@ -1178,6 +1373,20 @@ bool PrusaDoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect)
return false;
}
void PrusaDoubleSlider::ChangeOneLayerLock()
{
m_is_one_layer = !m_is_one_layer;
m_selection == ssLower ? correct_lower_value() : correct_higher_value();
if (!m_selection) m_selection = ssHigher;
Refresh();
Update();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
}
void PrusaDoubleSlider::OnLeftDown(wxMouseEvent& event)
{
this->CaptureMouse();
@ -1245,6 +1454,10 @@ void PrusaDoubleSlider::OnMotion(wxMouseEvent& event)
Refresh();
Update();
event.Skip();
wxCommandEvent e(wxEVT_SCROLL_CHANGED);
e.SetEventObject(this);
ProcessWindowEvent(e);
}
void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event)

View file

@ -144,6 +144,49 @@ public:
#endif //__WXMSW__
// *****************************************************************************
// ----------------------------------------------------------------------------
// PrusaDataViewBitmapText: helper class used by PrusaBitmapTextRenderer
// ----------------------------------------------------------------------------
class PrusaDataViewBitmapText : public wxObject
{
public:
PrusaDataViewBitmapText(const wxString &text = wxEmptyString,
const wxBitmap& bmp = wxNullBitmap) :
m_text(text), m_bmp(bmp)
{ }
PrusaDataViewBitmapText(const PrusaDataViewBitmapText &other)
: wxObject(),
m_text(other.m_text),
m_bmp(other.m_bmp)
{ }
void SetText(const wxString &text) { m_text = text; }
wxString GetText() const { return m_text; }
void SetBitmap(const wxIcon &icon) { m_bmp = icon; }
const wxBitmap &GetBitmap() const { return m_bmp; }
bool IsSameAs(const PrusaDataViewBitmapText& other) const {
return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp);
}
bool operator==(const PrusaDataViewBitmapText& other) const {
return IsSameAs(other);
}
bool operator!=(const PrusaDataViewBitmapText& other) const {
return !IsSameAs(other);
}
private:
wxString m_text;
wxBitmap m_bmp;
};
DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText)
// ----------------------------------------------------------------------------
// PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel
// ----------------------------------------------------------------------------
@ -155,7 +198,9 @@ class PrusaObjectDataViewModelNode
{
PrusaObjectDataViewModelNode* m_parent;
MyObjectTreeModelNodePtrArray m_children;
wxIcon m_empty_icon;
wxIcon m_empty_icon;
wxBitmap m_empty_bmp;
std::vector< std::string > m_opt_categories;
public:
PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) {
m_parent = NULL;
@ -174,18 +219,31 @@ public:
PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent,
const wxString& sub_obj_name,
const wxIcon& icon,
const wxBitmap& bmp,
const wxString& extruder,
const int volume_id=-1) {
m_parent = parent;
m_name = sub_obj_name;
m_copy = wxEmptyString;
m_icon = icon;
m_bmp = bmp;
m_type = "volume";
m_volume_id = volume_id;
m_extruder = extruder;
m_extruder = extruder;
#ifdef __WXGTK__
// it's necessary on GTK because of control have to know if this item will be container
// in another case you couldn't to add subitem for this item
// it will be produce "segmentation fault"
m_container = true;
#endif //__WXGTK__
set_part_action_icon();
}
}
PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent) :
m_parent(parent),
m_name("Settings to modified"),
m_copy(wxEmptyString),
m_type("settings"),
m_extruder(wxEmptyString) {}
~PrusaObjectDataViewModelNode()
{
@ -200,9 +258,10 @@ public:
wxString m_name;
wxIcon& m_icon = m_empty_icon;
wxBitmap& m_bmp = m_empty_bmp;
wxString m_copy;
std::string m_type;
int m_volume_id;
int m_volume_id = -2;
bool m_container = false;
wxString m_extruder = "default";
wxBitmap m_action_icon;
@ -226,6 +285,8 @@ public:
}
void Insert(PrusaObjectDataViewModelNode* child, unsigned int n)
{
if (!m_container)
m_container = true;
m_children.Insert(child, n);
}
void Append(PrusaObjectDataViewModelNode* child)
@ -258,9 +319,9 @@ public:
switch (col)
{
case 0:{
wxDataViewIconText data;
PrusaDataViewBitmapText data;
data << variant;
m_icon = data.GetIcon();
m_bmp = data.GetBitmap();
m_name = data.GetText();
return true;}
case 1:
@ -281,6 +342,11 @@ public:
{
m_icon = icon;
}
void SetBitmap(const wxBitmap &icon)
{
m_bmp = icon;
}
void SetType(const std::string& type){
m_type = type;
@ -326,6 +392,7 @@ public:
// Set action icons for node
void set_object_action_icon();
void set_part_action_icon();
bool update_settings_digest(const std::vector<std::string>& categories);
};
// ----------------------------------------------------------------------------
@ -336,26 +403,24 @@ class PrusaObjectDataViewModel :public wxDataViewModel
{
std::vector<PrusaObjectDataViewModelNode*> m_objects;
public:
PrusaObjectDataViewModel(){}
~PrusaObjectDataViewModel()
{
for (auto object : m_objects)
delete object;
}
PrusaObjectDataViewModel();
~PrusaObjectDataViewModel();
wxDataViewItem Add(const wxString &name);
wxDataViewItem Add(const wxString &name, const int instances_count);
wxDataViewItem AddChild(const wxDataViewItem &parent_item,
const wxString &name,
const wxIcon& icon,
const int = 0,
const wxBitmap& icon,
const int extruder = 0,
const bool create_frst_child = true);
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
wxDataViewItem Delete(const wxDataViewItem &item);
void DeleteAll();
void DeleteChildren(wxDataViewItem& parent);
wxDataViewItem GetItemById(int obj_idx);
wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
int GetIdByItem(wxDataViewItem& item);
int GetVolumeIdByItem(wxDataViewItem& item);
int GetVolumeIdByItem(const wxDataViewItem& item);
bool IsEmpty() { return m_objects.empty(); }
// helper method for wxLog
@ -363,6 +428,7 @@ public:
wxString GetName(const wxDataViewItem &item) const;
wxString GetCopy(const wxDataViewItem &item) const;
wxIcon& GetIcon(const wxDataViewItem &item) const;
wxBitmap& GetBitmap(const wxDataViewItem &item) const;
// helper methods to change the model
@ -383,8 +449,7 @@ public:
int new_volume_id,
const wxDataViewItem &parent);
// virtual bool IsEnabled(const wxDataViewItem &item,
// unsigned int col) const override;
virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
virtual bool IsContainer(const wxDataViewItem &item) const override;
@ -394,8 +459,35 @@ public:
// Is the container just a header or an item with all columns
// In our case it is an item with all columns
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
wxDataViewItem HasSettings(const wxDataViewItem &item) const;
bool IsSettingsItem(const wxDataViewItem &item) const;
void UpdateSettingsDigest(const wxDataViewItem &item, const std::vector<std::string>& categories);
};
// ----------------------------------------------------------------------------
// PrusaBitmapTextRenderer
// ----------------------------------------------------------------------------
class PrusaBitmapTextRenderer : public wxDataViewCustomRenderer
{
public:
PrusaBitmapTextRenderer( wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT,
int align = wxDVR_DEFAULT_ALIGNMENT):
wxDataViewCustomRenderer(wxT("wxObject"), mode, align) {}
bool SetValue(const wxVariant &value);
bool GetValue(wxVariant &value) const;
virtual bool Render(wxRect cell, wxDC *dc, int state);
virtual wxSize GetSize() const;
virtual bool HasEditorCtrl() const { return false; }
private:
// wxDataViewIconText m_value;
PrusaDataViewBitmapText m_value;
};
// ----------------------------------------------------------------------------
@ -516,7 +608,7 @@ public:
int maxValue,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSL_HORIZONTAL,
long style = wxSL_VERTICAL,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxEmptyString);
~PrusaDoubleSlider(){}
@ -528,6 +620,8 @@ public:
return m_higher_value;
}
int GetActiveValue() const;
double GetLowerValueD() const { return get_double_value(ssLower); }
double GetHigherValueD() const { return get_double_value(ssHigher); }
wxSize DoGetBestSize() const override;
void SetLowerValue(const int lower_val);
void SetHigherValue(const int higher_val);
@ -538,6 +632,7 @@ public:
void SetSliderValues(const std::vector<std::pair<int, double>>& values) {
m_values = values;
}
void ChangeOneLayerLock();
void OnPaint(wxPaintEvent& ){ render();}
void OnLeftDown(wxMouseEvent& event);
@ -583,6 +678,7 @@ protected:
wxCoord get_position_from_value(const int value);
wxSize get_size();
void get_size(int *w, int *h);
double get_double_value(const SelectedSlider& selection) const;
private:
int m_min_value;