This commit is contained in:
bubnikv 2019-01-09 10:43:31 +01:00
commit 4a1f0eb05f
13 changed files with 287 additions and 140 deletions

View file

@ -66,12 +66,8 @@ void Field::PostInitialize()
BUILD();
}
void Field::on_kill_focus(wxEvent& event)
void Field::on_kill_focus()
{
// Without this, there will be nasty focus bugs on Windows.
// Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
// non-command events to allow the default handling to take place."
event.Skip();
// call the registered function if it is available
if (m_on_kill_focus!=nullptr)
m_on_kill_focus(m_opt_id);
@ -250,11 +246,23 @@ void TextCtrl::BUILD() {
break;
}
const long style = m_opt.multiline ? wxTE_MULTILINE : 0;
const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/;
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style);
temp->SetToolTip(get_tooltip_text(text_value));
if (style == wxTE_PROCESS_ENTER) {
temp->Bind(wxEVT_TEXT_ENTER, ([this, temp](wxEvent& e)
{
#if !defined(__WXGTK__)
e.Skip();
temp->GetToolTip()->Enable(true);
#endif // __WXGTK__
propagate_value();
bEnterPressed = true;
}), temp->GetId());
}
temp->Bind(wxEVT_SET_FOCUS, ([this](wxEvent& e) { on_set_focus(e); }), temp->GetId());
temp->Bind(wxEVT_LEFT_DOWN, ([temp](wxEvent& event)
@ -272,14 +280,15 @@ void TextCtrl::BUILD() {
temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e)
{
#if !defined(__WXGTK__)
e.Skip();
#if !defined(__WXGTK__)
temp->GetToolTip()->Enable(true);
#endif // __WXGTK__
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type))
on_change_field();
else
on_kill_focus(e);
if (bEnterPressed) {
bEnterPressed = false;
return;
}
propagate_value();
}), temp->GetId());
/*
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt)
@ -311,6 +320,14 @@ void TextCtrl::BUILD() {
window = dynamic_cast<wxWindow*>(temp);
}
void TextCtrl::propagate_value()
{
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type))
on_change_field();
else
on_kill_focus();
}
boost::any& TextCtrl::get_value()
{
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
@ -398,7 +415,7 @@ void SpinCtrl::BUILD() {
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
0, min_val, max_val, default_value);
0|wxTE_PROCESS_ENTER, min_val, max_val, default_value);
#ifndef __WXOSX__
// #ys_FIXME_KILL_FOCUS
@ -407,15 +424,23 @@ void SpinCtrl::BUILD() {
// and on TEXT event under OSX
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e)
{
if (tmp_value < 0)
on_kill_focus(e);
else {
e.Skip();
on_change_field();
e.Skip();
if (bEnterPressed) {
bEnterPressed = false;
return;
}
propagate_value();
}), temp->GetId());
temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e)
{
e.Skip();
propagate_value();
bEnterPressed = true;
}), temp->GetId());
#endif
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e)
@ -430,12 +455,7 @@ void SpinCtrl::BUILD() {
tmp_value = std::stoi(value);
else tmp_value = -9999;
#ifdef __WXOSX__
if (tmp_value < 0) {
if (m_on_kill_focus != nullptr)
m_on_kill_focus(m_opt_id);
}
else
on_change_field();
propagate_value();
#endif
}), temp->GetId());
@ -445,6 +465,14 @@ void SpinCtrl::BUILD() {
window = dynamic_cast<wxWindow*>(temp);
}
void SpinCtrl::propagate_value()
{
if (tmp_value < 0)
on_kill_focus();
else
on_change_field();
}
void Choice::BUILD() {
auto size = wxSize(wxDefaultSize);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
@ -483,7 +511,7 @@ void Choice::BUILD() {
on_change_field();
}
else
on_kill_focus(e);
on_kill_focus();
}), temp->GetId());
}
@ -755,8 +783,8 @@ void PointCtrl::BUILD()
val = default_pt(1);
wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size);
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size);
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, wxEVT_TEXT_ENTER);
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, wxEVT_TEXT_ENTER);
temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : "), 0, wxALIGN_CENTER_VERTICAL, 0);
temp->Add(x_textctrl);
@ -766,8 +794,11 @@ void PointCtrl::BUILD()
// x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId());
// y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId());
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), y_textctrl->GetId());
x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(y_textctrl); }), y_textctrl->GetId());
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(x_textctrl); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(y_textctrl); }), y_textctrl->GetId());
// // recast as a wxWindow to fit the calling convention
sizer = dynamic_cast<wxSizer*>(temp);
@ -776,14 +807,12 @@ void PointCtrl::BUILD()
y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y));
}
void PointCtrl::OnKillFocus(wxEvent& e, wxTextCtrl* win)
void PointCtrl::propagate_value(wxTextCtrl* win)
{
e.Skip();
if (!win->GetValue().empty()) {
if (!win->GetValue().empty())
on_change_field();
}
else
on_kill_focus(e);
on_kill_focus();
}
void PointCtrl::set_value(const Vec2d& value, bool change_event)

View file

@ -74,7 +74,7 @@ protected:
/// Call the attached on_kill_focus method.
//! It's important to use wxEvent instead of wxFocusEvent,
//! in another case we can't unfocused control at all
void on_kill_focus(wxEvent& event);
void on_kill_focus();
/// Call the attached on_change method.
void on_set_focus(wxEvent& event);
/// Call the attached on_change method.
@ -226,6 +226,8 @@ protected:
// current value
boost::any m_value;
bool bEnterPressed = false;
friend class OptionsGroup;
};
@ -252,6 +254,8 @@ public:
~TextCtrl() {}
void BUILD();
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value();
wxWindow* window {nullptr};
virtual void set_value(const std::string& value, bool change_event = false) {
@ -310,6 +314,8 @@ public:
wxWindow* window{ nullptr };
void BUILD() override;
/// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value() ;
void set_value(const std::string& value, bool change_event = false) {
m_disable_change_event = !change_event;
@ -393,8 +399,8 @@ public:
wxTextCtrl* y_textctrl{ nullptr };
void BUILD() override;
void OnKillFocus(wxEvent& e, wxTextCtrl* win);
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value(wxTextCtrl* win);
void set_value(const Vec2d& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false);
boost::any& get_value() override;

View file

@ -2039,11 +2039,17 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
const Vec3d& center = get_bounding_box().center();
if (is_single_full_instance())
{
::glTranslated(center(0), center(1), center(2));
if (boost::starts_with(sidebar_field, "scale"))
{
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
}
}
else if (is_single_volume() || is_single_modifier())
{
const GLVolume* volume = (*m_volumes)[*m_list.begin()];
Transform3d orient_matrix = volume->get_instance_transformation().get_matrix(true, false, true, true);
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
const Vec3d& offset = get_bounding_box().center();
::glTranslated(offset(0), offset(1), offset(2));
@ -2054,8 +2060,7 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
::glTranslated(center(0), center(1), center(2));
if (requires_local_axes())
{
const GLVolume* volume = (*m_volumes)[*m_list.begin()];
Transform3d orient_matrix = volume->get_instance_transformation().get_matrix(true, false, true, true);
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
}
}
@ -2513,7 +2518,9 @@ void GLCanvas3D::Selection::_render_sidebar_rotation_hints(const std::string& si
void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
{
if (boost::ends_with(sidebar_field, "x") || requires_uniform_scale())
bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
if (boost::ends_with(sidebar_field, "x") || uniform_scale)
{
::glPushMatrix();
::glRotated(-90.0, 0.0, 0.0, 1.0);
@ -2521,14 +2528,14 @@ void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sideb
::glPopMatrix();
}
if (boost::ends_with(sidebar_field, "y") || requires_uniform_scale())
if (boost::ends_with(sidebar_field, "y") || uniform_scale)
{
::glPushMatrix();
_render_sidebar_scale_hint(Y);
::glPopMatrix();
}
if (boost::ends_with(sidebar_field, "z") || requires_uniform_scale())
if (boost::ends_with(sidebar_field, "z") || uniform_scale)
{
::glPushMatrix();
::glRotated(90.0, 1.0, 0.0, 0.0);
@ -2559,7 +2566,7 @@ void GLCanvas3D::Selection::_render_sidebar_rotation_hint(Axis axis) const
void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const
{
m_arrow.set_color((requires_uniform_scale() ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
m_arrow.set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
::glTranslated(0.0, 5.0, 0.0);
m_arrow.render();

View file

@ -633,8 +633,10 @@ void ObjectList::get_settings_choice(const wxString& category_name)
// Add settings item for object
const auto item = GetSelection();
auto item = GetSelection();
if (item) {
if (m_objects_model->GetItemType(item) == itInstance)
item = m_objects_model->GetTopParent(item);
const auto settings_item = m_objects_model->IsSettingsItem(item) ? item : m_objects_model->GetSettingsItem(item);
select_item(settings_item ? settings_item :
m_objects_model->AddSettingsChild(item));
@ -849,7 +851,7 @@ void ObjectList::load_part( ModelObject* model_object,
new_volume->set_type(static_cast<ModelVolume::Type>(type));
new_volume->name = boost::filesystem::path(input_file).filename().string();
part_names.Add(new_volume->name);
part_names.Add(from_u8(new_volume->name));
// set a default extruder value, since user can't add it manually
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
@ -903,7 +905,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int
m_parts_changed = true;
parts_changed(obj_idx);
select_item(m_objects_model->AddVolumeChild(GetSelection(), name, type));
const auto object_item = m_objects_model->GetTopParent(GetSelection());
select_item(m_objects_model->AddVolumeChild(object_item, from_u8(name), type));
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
selection_changed();
#endif //no __WXOSX__ //__WXMSW__
@ -1031,7 +1034,7 @@ void ObjectList::split()
parent = item;
for (auto id = 0; id < model_object->volumes.size(); id++) {
const auto vol_item = m_objects_model->AddVolumeChild(parent, model_object->volumes[id]->name,
const auto vol_item = m_objects_model->AddVolumeChild(parent, from_u8(model_object->volumes[id]->name),
model_object->volumes[id]->is_modifier() ?
ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART,
model_object->volumes[id]->config.has("extruder") ?
@ -1156,6 +1159,10 @@ void ObjectList::part_selection_changed()
else if (m_objects_model->GetItemType(item) == itInstance) {
og_name = _(L("Instance manipulation"));
update_and_show_manipulations = true;
// fill m_config by object's values
const int obj_idx_ = m_objects_model->GetObjectIdByItem(item);
m_config = &(*m_objects)[obj_idx_]->config;
}
}
@ -1188,7 +1195,7 @@ void ObjectList::part_selection_changed()
void ObjectList::add_object_to_list(size_t obj_idx)
{
auto model_object = (*m_objects)[obj_idx];
wxString item_name = model_object->name;
wxString item_name = from_u8(model_object->name);
const auto item = m_objects_model->Add(item_name,
!model_object->config.has("extruder") ? 0 :
model_object->config.option<ConfigOptionInt>("extruder")->value);
@ -1207,8 +1214,8 @@ void ObjectList::add_object_to_list(size_t obj_idx)
if (model_object->volumes.size() > 1) {
for (auto id = 0; id < model_object->volumes.size(); id++) {
auto vol_item = m_objects_model->AddVolumeChild(item,
model_object->volumes[id]->name,
model_object->volumes[id]->type()/*ModelVolume::MODEL_PART*/,
from_u8(model_object->volumes[id]->name),
model_object->volumes[id]->type(),
!model_object->volumes[id]->config.has("extruder") ? 0 :
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
false);

View file

@ -19,7 +19,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
OG_Settings(parent, true)
{
m_og->set_name(_(L("Object Manipulation")));
m_og->label_width = 100;
m_og->label_width = 125;
m_og->set_grid_vgap(5);
m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) {
@ -150,7 +150,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
m_og->append_line(line);
auto add_og_to_object_settings = [](const std::string& option_name, const std::string& sidetext)
auto add_og_to_object_settings = [this](const std::string& option_name, const std::string& sidetext)
{
Line line = { _(option_name), "" };
ConfigOptionDef def;
@ -164,6 +164,27 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
def.max = 360;
}
// Add "uniform scaling" button in front of "Scale" option
else if (option_name == "Scale") {
line.near_label_widget = [this](wxWindow* parent) {
auto btn = new PrusaLockButton(parent, wxID_ANY);
btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){
event.Skip();
wxTheApp->CallAfter([btn, this]() { set_uniform_scaling(btn->IsLocked()); });
});
m_lock_bnt = btn;
return btn;
};
}
// Add empty bmp (Its size have to be equal to PrusaLockButton) in front of "Size" option to label alignment
else if (option_name == "Size") {
line.near_label_widget = [this](wxWindow* parent) {
return new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition,
wxBitmap(from_u8(var("one_layer_lock_on.png")), wxBITMAP_TYPE_PNG).GetSize());
};
}
const std::string lower_name = boost::algorithm::to_lower_copy(option_name);
std::vector<std::string> axes{ "x", "y", "z" };
@ -379,6 +400,15 @@ void ObjectManipulation::update_if_dirty()
m_cache.rotation = m_new_rotation;
if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) {
m_lock_bnt->SetLock(true);
m_lock_bnt->Disable();
}
else {
m_lock_bnt->SetLock(m_uniform_scale);
m_lock_bnt->Enable();
}
if (m_new_enabled)
m_og->enable();
else
@ -479,7 +509,7 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
{
Vec3d scaling_factor = scale;
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
if (selection.requires_uniform_scale())
if (m_uniform_scale || selection.requires_uniform_scale())
{
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
@ -535,7 +565,7 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
Vec3d scale = 100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2));
Vec3d scaling_factor = scale;
if (selection.requires_uniform_scale())
if (m_uniform_scale || selection.requires_uniform_scale())
{
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
double max_diff = abs_scale_diff(X);

View file

@ -7,6 +7,7 @@
#include "GLCanvas3D.hpp"
class wxStaticText;
class PrusaLockButton;
namespace Slic3r {
namespace GUI {
@ -74,6 +75,8 @@ class ObjectManipulation : public OG_Settings
Vec3d m_new_scale;
Vec3d m_new_size;
bool m_new_enabled;
bool m_uniform_scale {false};
PrusaLockButton* m_lock_bnt{ nullptr };
public:
ObjectManipulation(wxWindow* parent);
@ -88,6 +91,9 @@ public:
// Called from the App to update the UI if dirty.
void update_if_dirty();
void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;}
bool get_uniform_scaling() const { return m_uniform_scale; }
private:
void reset_settings_value();

View file

@ -2201,6 +2201,7 @@ PrusaLockButton::PrusaLockButton( wxWindow *parent,
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif // __WXMSW__
SetBitmap(m_bmp_unlock_on);
SetBitmapDisabled(m_bmp_lock_on);
//button events
Bind(wxEVT_BUTTON, &PrusaLockButton::OnButton, this);
@ -2216,6 +2217,12 @@ void PrusaLockButton::OnButton(wxCommandEvent& event)
event.Skip();
}
void PrusaLockButton::SetLock(bool lock)
{
m_is_pushed = lock;
enter_button(true);
}
void PrusaLockButton::enter_button(const bool enter)
{
wxBitmap* icon = m_is_pushed ?

View file

@ -851,6 +851,7 @@ public:
void OnLeaveBtn(wxMouseEvent& event) { enter_button(false); event.Skip(); }
bool IsLocked() const { return m_is_pushed; }
void SetLock(bool lock);
protected:
void enter_button(const bool enter);