mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 20:51:12 -06:00 
			
		
		
		
	Emulation of kill focus event on object manipulator fields when changing selection into objects list [WIN+LINUX]
This commit is contained in:
		
							parent
							
								
									5fa5d495bb
								
							
						
					
					
						commit
						8076b39c4b
					
				
					 3 changed files with 121 additions and 74 deletions
				
			
		|  | @ -66,9 +66,12 @@ ObjectList::ObjectList(wxWindow* parent) : | |||
| 
 | ||||
|     // describe control behavior 
 | ||||
|     Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { | ||||
| //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 | ||||
|         std::cout << "SELECTION_CHANGED" << std::endl; | ||||
| //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 | ||||
| #ifndef __APPLE__ | ||||
|         // On Windows and Linux, forces a kill focus emulation on the object manipulator fields because this event handler is called
 | ||||
|         // before the kill focus event handler on the object manipulator when changing selection in the list, invalidating the object
 | ||||
|         // manipulator cache with the following call to selection_changed()
 | ||||
|         wxGetApp().obj_manipul()->emulate_kill_focus(); | ||||
| #endif // __APPLE__
 | ||||
|         selection_changed(); | ||||
| #ifndef __WXMSW__ | ||||
|         set_tooltip_for_item(get_mouse_position_in_control()); | ||||
|  |  | |||
|  | @ -17,85 +17,23 @@ namespace GUI | |||
| 
 | ||||
| ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||
|     OG_Settings(parent, true) | ||||
| #ifndef __APPLE__ | ||||
|     , m_focused_option("") | ||||
| #endif // __APPLE__
 | ||||
| { | ||||
|     m_og->set_name(_(L("Object Manipulation"))); | ||||
|     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) { | ||||
|         // needed to hide the visual hints in 3D scene
 | ||||
|         wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); | ||||
| 
 | ||||
| //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 | ||||
|         std::cout << "KILL_FOCUS" << std::endl; | ||||
| //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 | ||||
| 
 | ||||
|         if (!m_cache.is_valid()) | ||||
|             return; | ||||
| 
 | ||||
|         std::vector<std::string> axes{ "_x", "_y", "_z" }; | ||||
| 
 | ||||
|         std::string param;  | ||||
|         std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); | ||||
| 
 | ||||
|         size_t i = 0; | ||||
|         Vec3d new_value; | ||||
|         for (auto axis : axes) | ||||
|             new_value(i++) = boost::any_cast<double>(m_og->get_value(param+axis)); | ||||
| 
 | ||||
|         if (param == "position") | ||||
|             change_position_value(new_value); | ||||
|         else if (param == "rotation") | ||||
|             change_rotation_value(new_value); | ||||
|         else if (param == "scale") | ||||
|             change_scale_value(new_value); | ||||
|         else if (param == "size") | ||||
|             change_size_value(new_value); | ||||
|     }; | ||||
| 
 | ||||
|     m_og->m_fill_empty_value = [this](const std::string& opt_key) | ||||
|     { | ||||
|         // needed to hide the visual hints in 3D scene
 | ||||
|         wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); | ||||
| 
 | ||||
|         if (!m_cache.is_valid()) | ||||
|             return; | ||||
| 
 | ||||
|         std::string param; | ||||
|         std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));  | ||||
| 
 | ||||
|         double value = 0.0; | ||||
| 
 | ||||
|         if (param == "position") { | ||||
|             int axis = opt_key.back() == 'x' ? 0 : | ||||
|                        opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|             value = m_cache.position(axis); | ||||
|         } | ||||
|         else if (param == "rotation") { | ||||
|             int axis = opt_key.back() == 'x' ? 0 : | ||||
|                 opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|             value = m_cache.rotation(axis); | ||||
|         } | ||||
|         else if (param == "scale") { | ||||
|             int axis = opt_key.back() == 'x' ? 0 : | ||||
|                 opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|             value = m_cache.scale(axis); | ||||
|         } | ||||
|         else if (param == "size") { | ||||
|             int axis = opt_key.back() == 'x' ? 0 : | ||||
|                 opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|             value = m_cache.size(axis); | ||||
|         } | ||||
| 
 | ||||
|         m_og->set_value(opt_key, double_to_string(value)); | ||||
|     }; | ||||
|     m_og->m_on_change = std::bind(&ObjectManipulation::on_change, this, std::placeholders::_1, std::placeholders::_2); | ||||
|     m_og->m_fill_empty_value = std::bind(&ObjectManipulation::on_fill_empty_value, this, std::placeholders::_1); | ||||
| 
 | ||||
|     m_og->m_set_focus = [this](const std::string& opt_key) | ||||
|     { | ||||
| #ifndef __APPLE__ | ||||
|         m_focused_option = opt_key; | ||||
| #endif // __APPLE__
 | ||||
| 
 | ||||
|         // needed to show the visual hints in 3D scene
 | ||||
|         wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, true); | ||||
|     }; | ||||
|  | @ -383,6 +321,23 @@ void ObjectManipulation::update_if_dirty() | |||
|     m_dirty = false; | ||||
| } | ||||
| 
 | ||||
| #ifndef __APPLE__ | ||||
| void ObjectManipulation::emulate_kill_focus() | ||||
| { | ||||
|     if (m_focused_option.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     // we need to use a copy because the value of m_focused_option is modified inside on_change() and on_fill_empty_value()
 | ||||
|     std::string option = m_focused_option; | ||||
| 
 | ||||
|     // see TextCtrl::propagate_value()
 | ||||
|     if (static_cast<wxTextCtrl*>(m_og->get_fieldc(option, 0)->getWindow())->GetValue().empty()) | ||||
|         on_fill_empty_value(option); | ||||
|     else | ||||
|         on_change(option, 0); | ||||
| } | ||||
| #endif // __APPLE__
 | ||||
| 
 | ||||
| void ObjectManipulation::reset_settings_value() | ||||
| { | ||||
|     m_new_position = Vec3d::Zero(); | ||||
|  | @ -504,5 +459,80 @@ void ObjectManipulation::change_size_value(const Vec3d& size) | |||
|     m_cache.size = size; | ||||
| } | ||||
| 
 | ||||
| void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boost::any& value) | ||||
| { | ||||
|     // needed to hide the visual hints in 3D scene
 | ||||
|     wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); | ||||
| #ifndef __APPLE__ | ||||
|     m_focused_option = ""; | ||||
| #endif // __APPLE__
 | ||||
| 
 | ||||
|     if (!m_cache.is_valid()) | ||||
|         return; | ||||
| 
 | ||||
|     std::vector<std::string> axes{ "_x", "_y", "_z" }; | ||||
| 
 | ||||
|     std::string param; | ||||
|     std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); | ||||
| 
 | ||||
|     size_t i = 0; | ||||
|     Vec3d new_value; | ||||
|     for (auto axis : axes) | ||||
|         new_value(i++) = boost::any_cast<double>(m_og->get_value(param + axis)); | ||||
| 
 | ||||
|     if (param == "position") | ||||
|         change_position_value(new_value); | ||||
|     else if (param == "rotation") | ||||
|         change_rotation_value(new_value); | ||||
|     else if (param == "scale") | ||||
|         change_scale_value(new_value); | ||||
|     else if (param == "size") | ||||
|         change_size_value(new_value); | ||||
| } | ||||
| 
 | ||||
| void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) | ||||
| { | ||||
|     // needed to hide the visual hints in 3D scene
 | ||||
|     wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); | ||||
| #ifndef __APPLE__ | ||||
|     m_focused_option = ""; | ||||
| #endif // __APPLE__
 | ||||
| 
 | ||||
|     if (!m_cache.is_valid()) | ||||
|         return; | ||||
| 
 | ||||
|     std::string param; | ||||
|     std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); | ||||
| 
 | ||||
|     double value = 0.0; | ||||
| 
 | ||||
|     if (param == "position") { | ||||
|         int axis = opt_key.back() == 'x' ? 0 : | ||||
|             opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|         value = m_cache.position(axis); | ||||
|     } | ||||
|     else if (param == "rotation") { | ||||
|         int axis = opt_key.back() == 'x' ? 0 : | ||||
|             opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|         value = m_cache.rotation(axis); | ||||
|     } | ||||
|     else if (param == "scale") { | ||||
|         int axis = opt_key.back() == 'x' ? 0 : | ||||
|             opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|         value = m_cache.scale(axis); | ||||
|     } | ||||
|     else if (param == "size") { | ||||
|         int axis = opt_key.back() == 'x' ? 0 : | ||||
|             opt_key.back() == 'y' ? 1 : 2; | ||||
| 
 | ||||
|         value = m_cache.size(axis); | ||||
|     } | ||||
| 
 | ||||
|     m_og->set_value(opt_key, double_to_string(value)); | ||||
| } | ||||
| 
 | ||||
| } //namespace GUI
 | ||||
| } //namespace Slic3r 
 | ||||
|  | @ -77,6 +77,11 @@ class ObjectManipulation : public OG_Settings | |||
|     bool            m_uniform_scale {true}; | ||||
|     PrusaLockButton* m_lock_bnt{ nullptr }; | ||||
| 
 | ||||
| #ifndef __APPLE__ | ||||
|     // Currently focused option name (empty if none)
 | ||||
|     std::string     m_focused_option; | ||||
| #endif // __APPLE__
 | ||||
| 
 | ||||
| public: | ||||
|     ObjectManipulation(wxWindow* parent); | ||||
|     ~ObjectManipulation() {} | ||||
|  | @ -94,6 +99,12 @@ public: | |||
|     bool        get_uniform_scaling() const { return m_uniform_scale; } | ||||
| 
 | ||||
|     void reset_cache() { m_cache.reset(); } | ||||
| #ifndef __APPLE__ | ||||
|     // On Windows and Linux, emulates a kill focus event on the currently focused option (if any)
 | ||||
|     // Used only in ObjectList wxEVT_DATAVIEW_SELECTION_CHANGED handler which is called before the regular kill focus event
 | ||||
|     // bound to this class when changing selection in the objects list
 | ||||
|     void emulate_kill_focus(); | ||||
| #endif // __APPLE__
 | ||||
| 
 | ||||
| private: | ||||
|     void reset_settings_value(); | ||||
|  | @ -108,6 +119,9 @@ private: | |||
|     void    change_rotation_value(const Vec3d& rotation); | ||||
|     void    change_scale_value(const Vec3d& scale); | ||||
|     void    change_size_value(const Vec3d& size); | ||||
| 
 | ||||
|     void on_change(const t_config_option_key& opt_key, const boost::any& value); | ||||
|     void on_fill_empty_value(const std::string& opt_key); | ||||
| }; | ||||
| 
 | ||||
| }} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri