1 #ifndef slic3r_GUI_ObjectDataViewModel_hpp_
2 #define slic3r_GUI_ObjectDataViewModel_hpp_
3 
4 #include <wx/dataview.h>
5 #include <vector>
6 
7 #include "ExtraRenderers.hpp"
8 
9 namespace Slic3r {
10 
11 enum class ModelVolumeType : int;
12 
13 namespace GUI {
14 
15 typedef double                          coordf_t;
16 typedef std::pair<coordf_t, coordf_t>   t_layer_height_range;
17 
18 // ----------------------------------------------------------------------------
19 // ObjectDataViewModelNode: a node inside ObjectDataViewModel
20 // ----------------------------------------------------------------------------
21 enum ItemType {
22     itUndef         = 0,
23     itObject        = 1,
24     itVolume        = 2,
25     itInstanceRoot  = 4,
26     itInstance      = 8,
27     itSettings      = 16,
28     itLayerRoot     = 32,
29     itLayer         = 64,
30 };
31 
32 enum ColumnNumber
33 {
34     colName         = 0,    // item name
35     colPrint           ,    // printable property
36     colExtruder        ,    // extruder selection
37     colEditing         ,    // item editing
38 };
39 
40 enum PrintIndicator
41 {
42     piUndef         = 0,    // no print indicator
43     piPrintable        ,    // printable
44     piUnprintable      ,    // unprintable
45 };
46 
47 class ObjectDataViewModelNode;
48 WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
49 
50 class ObjectDataViewModelNode
51 {
52     ObjectDataViewModelNode*	    m_parent;
53     MyObjectTreeModelNodePtrArray   m_children;
54     wxBitmap                        m_empty_bmp;
55     size_t                          m_volumes_cnt = 0;
56     std::vector< std::string >      m_opt_categories;
57     t_layer_height_range            m_layer_range = { 0.0f, 0.0f };
58 
59     wxString				        m_name;
60     wxBitmap&                       m_bmp = m_empty_bmp;
61     ItemType				        m_type;
62     int                             m_idx = -1;
63     bool					        m_container = false;
64     wxString				        m_extruder = "default";
65     wxBitmap                        m_extruder_bmp;
66     wxBitmap				        m_action_icon;
67     PrintIndicator                  m_printable {piUndef};
68     wxBitmap				        m_printable_icon;
69 
70     std::string                     m_action_icon_name = "";
71     ModelVolumeType                 m_volume_type;
72 
73 public:
ObjectDataViewModelNode(const wxString & name,const wxString & extruder)74     ObjectDataViewModelNode(const wxString& name,
75                             const wxString& extruder):
76         m_parent(NULL),
77         m_name(name),
78         m_type(itObject),
79         m_extruder(extruder)
80     {
81         set_action_and_extruder_icons();
82         init_container();
83 	}
84 
ObjectDataViewModelNode(ObjectDataViewModelNode * parent,const wxString & sub_obj_name,const wxBitmap & bmp,const wxString & extruder,const int idx=-1)85     ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
86                             const wxString& sub_obj_name,
87                             const wxBitmap& bmp,
88                             const wxString& extruder,
89                             const int idx = -1 ) :
90         m_parent	(parent),
91         m_name		(sub_obj_name),
92         m_type		(itVolume),
93         m_idx       (idx),
94         m_extruder  (extruder)
95     {
96         m_bmp = bmp;
97         set_action_and_extruder_icons();
98         init_container();
99     }
100 
101     ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
102                             const t_layer_height_range& layer_range,
103                             const int idx = -1,
104                             const wxString& extruder = wxEmptyString );
105 
106     ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type);
107 
~ObjectDataViewModelNode()108     ~ObjectDataViewModelNode()
109     {
110         // free all our children nodes
111         size_t count = m_children.GetCount();
112         for (size_t i = 0; i < count; i++)
113         {
114             ObjectDataViewModelNode *child = m_children[i];
115             delete child;
116         }
117 #ifndef NDEBUG
118         // Indicate that the object was deleted.
119         m_idx = -2;
120 #endif /* NDEBUG */
121     }
122 
123 	void init_container();
IsContainer() const124 	bool IsContainer() const
125 	{
126 		return m_container;
127 	}
128 
GetParent()129     ObjectDataViewModelNode* GetParent()
130     {
131         assert(m_parent == nullptr || m_parent->valid());
132         return m_parent;
133     }
GetChildren()134     MyObjectTreeModelNodePtrArray& GetChildren()
135     {
136         return m_children;
137     }
GetNthChild(unsigned int n)138     ObjectDataViewModelNode* GetNthChild(unsigned int n)
139     {
140         return m_children.Item(n);
141     }
Insert(ObjectDataViewModelNode * child,unsigned int n)142     void Insert(ObjectDataViewModelNode* child, unsigned int n)
143     {
144         if (!m_container)
145             m_container = true;
146         m_children.Insert(child, n);
147     }
Append(ObjectDataViewModelNode * child)148     void Append(ObjectDataViewModelNode* child)
149     {
150         if (!m_container)
151             m_container = true;
152         m_children.Add(child);
153     }
RemoveAllChildren()154     void RemoveAllChildren()
155     {
156         if (GetChildCount() == 0)
157             return;
158         for (int id = int(GetChildCount()) - 1; id >= 0; --id)
159         {
160             if (m_children.Item(id)->GetChildCount() > 0)
161                 m_children[id]->RemoveAllChildren();
162             auto node = m_children[id];
163             m_children.RemoveAt(id);
164             delete node;
165         }
166     }
167 
GetChildCount() const168     size_t GetChildCount() const
169     {
170         return m_children.GetCount();
171     }
172 
173     bool            SetValue(const wxVariant &variant, unsigned int col);
174 
SetBitmap(const wxBitmap & icon)175     void            SetBitmap(const wxBitmap &icon) { m_bmp = icon; }
GetBitmap() const176     const wxBitmap& GetBitmap() const               { return m_bmp; }
GetName() const177     const wxString& GetName() const                 { return m_name; }
GetType() const178     ItemType        GetType() const                 { return m_type; }
179 	void			SetIdx(const int& idx);
GetIdx() const180 	int             GetIdx() const                  { return m_idx; }
GetLayerRange() const181 	t_layer_height_range    GetLayerRange() const   { return m_layer_range; }
IsPrintable() const182     PrintIndicator  IsPrintable() const             { return m_printable; }
183 
184     // use this function only for childrens
AssignAllVal(ObjectDataViewModelNode & from_node)185     void AssignAllVal(ObjectDataViewModelNode& from_node)
186     {
187         // ! Don't overwrite other values because of equality of this values for all children --
188         m_name = from_node.m_name;
189         m_bmp = from_node.m_bmp;
190         m_idx = from_node.m_idx;
191         m_extruder = from_node.m_extruder;
192         m_type = from_node.m_type;
193     }
194 
SwapChildrens(int frst_id,int scnd_id)195     bool SwapChildrens(int frst_id, int scnd_id) {
196         if (GetChildCount() < 2 ||
197             frst_id < 0 || (size_t)frst_id >= GetChildCount() ||
198             scnd_id < 0 || (size_t)scnd_id >= GetChildCount())
199             return false;
200 
201         ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
202         ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
203 
204         new_scnd.m_idx = m_children.Item(scnd_id)->m_idx;
205         new_frst.m_idx = m_children.Item(frst_id)->m_idx;
206 
207         m_children.Item(frst_id)->AssignAllVal(new_frst);
208         m_children.Item(scnd_id)->AssignAllVal(new_scnd);
209         return true;
210     }
211 
212     // Set action and extruder(if any exist) icons for node
213     void        set_action_and_extruder_icons();
214     // set extruder icon for node
215     void        set_extruder_icon();
216 	// Set printable icon for node
217     void        set_printable_icon(PrintIndicator printable);
218 
219     void        update_settings_digest_bitmaps();
220     bool        update_settings_digest(const std::vector<std::string>& categories);
volume_type() const221     int         volume_type() const { return int(m_volume_type); }
222     void        msw_rescale();
223 
224 #ifndef NDEBUG
225     bool 		valid();
226 #endif /* NDEBUG */
invalid() const227     bool        invalid() const { return m_idx < -1; }
228 
229 private:
230     friend class ObjectDataViewModel;
231 };
232 
233 
234 // ----------------------------------------------------------------------------
235 // ObjectDataViewModel
236 // ----------------------------------------------------------------------------
237 
238 // custom message the model sends to associated control to notify a last volume deleted from the object:
239 wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent);
240 
241 class ObjectDataViewModel :public wxDataViewModel
242 {
243     std::vector<ObjectDataViewModelNode*>       m_objects;
244     std::vector<wxBitmap*>                      m_volume_bmps;
245     wxBitmap*                                   m_warning_bmp { nullptr };
246 
247     wxDataViewCtrl*                             m_ctrl { nullptr };
248 
249 public:
250     ObjectDataViewModel();
251     ~ObjectDataViewModel();
252 
253     wxDataViewItem Add( const wxString &name,
254                         const int extruder,
255                         const bool has_errors = false);
256     wxDataViewItem AddVolumeChild(  const wxDataViewItem &parent_item,
257                                     const wxString &name,
258                                     const Slic3r::ModelVolumeType volume_type,
259                                     const bool has_errors = false,
260                                     const int extruder = 0,
261                                     const bool create_frst_child = true);
262     wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
263     wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
264     wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, const std::vector<bool>& print_indicator);
265     wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item);
266     wxDataViewItem AddLayersChild(  const wxDataViewItem &parent_item,
267                                     const t_layer_height_range& layer_range,
268                                     const int extruder = 0,
269                                     const int index = -1);
270     wxDataViewItem Delete(const wxDataViewItem &item);
271     wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
272     void DeleteAll();
273     void DeleteChildren(wxDataViewItem& parent);
274     void DeleteVolumeChildren(wxDataViewItem& parent);
275     void DeleteSettings(const wxDataViewItem& parent);
276     wxDataViewItem GetItemById(int obj_idx);
277     wxDataViewItem GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type);
278     wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
279     wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx);
280     wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx);
281     wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
282     int  GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
283     int  GetIdByItem(const wxDataViewItem& item) const;
284     int  GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const;
285     int  GetObjectIdByItem(const wxDataViewItem& item) const;
286     int  GetVolumeIdByItem(const wxDataViewItem& item) const;
287     int  GetInstanceIdByItem(const wxDataViewItem& item) const;
288     int  GetLayerIdByItem(const wxDataViewItem& item) const;
289     void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
290     int  GetRowByItem(const wxDataViewItem& item) const;
IsEmpty()291     bool IsEmpty() { return m_objects.empty(); }
292     bool InvalidItem(const wxDataViewItem& item);
293 
294     // helper method for wxLog
295 
296     wxString    GetName(const wxDataViewItem &item) const;
297     wxBitmap&   GetBitmap(const wxDataViewItem &item) const;
298     wxString    GetExtruder(const wxDataViewItem &item) const;
299     int         GetExtruderNumber(const wxDataViewItem &item) const;
300 
301     // helper methods to change the model
302 
GetColumnCount() const303     unsigned int    GetColumnCount() const override { return 3;}
GetColumnType(unsigned int col) const304     wxString        GetColumnType(unsigned int col) const override{ return wxT("string"); }
305 
306     void GetValue(  wxVariant &variant,
307                     const wxDataViewItem &item,
308                     unsigned int col) const override;
309     bool SetValue(  const wxVariant &variant,
310                     const wxDataViewItem &item,
311                     unsigned int col) override;
312     bool SetValue(  const wxVariant &variant,
313                     const int item_idx,
314                     unsigned int col);
315 
316     void SetExtruder(const wxString& extruder, wxDataViewItem item);
317 
318     // For parent move child from cur_volume_id place to new_volume_id
319     // Remaining items will moved up/down accordingly
320     wxDataViewItem  ReorganizeChildren( const int cur_volume_id,
321                                         const int new_volume_id,
322                                         const wxDataViewItem &parent);
323     wxDataViewItem  ReorganizeObjects( int current_id, int new_id);
324 
325     bool    IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
326 
327     wxDataViewItem  GetParent(const wxDataViewItem &item) const override;
328     // get object item
329     wxDataViewItem          GetTopParent(const wxDataViewItem &item) const;
330     bool            IsContainer(const wxDataViewItem &item) const override;
331     unsigned int    GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const override;
332     void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
333     // Is the container just a header or an item with all columns
334     // In our case it is an item with all columns
HasContainerColumns(const wxDataViewItem & WXUNUSED (item)) const335     bool    HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override {	return true; }
336 
337     ItemType        GetItemType(const wxDataViewItem &item) const ;
338     wxDataViewItem  GetItemByType(  const wxDataViewItem &parent_item,
339                                     ItemType type) const;
340     wxDataViewItem  GetSettingsItem(const wxDataViewItem &item) const;
341     wxDataViewItem  GetInstanceRootItem(const wxDataViewItem &item) const;
342     wxDataViewItem  GetLayerRootItem(const wxDataViewItem &item) const;
343     bool    IsSettingsItem(const wxDataViewItem &item) const;
344     void    UpdateSettingsDigest(   const wxDataViewItem &item,
345                                     const std::vector<std::string>& categories);
346 
347     bool    IsPrintable(const wxDataViewItem &item) const;
348     void    UpdateObjectPrintable(wxDataViewItem parent_item);
349     void    UpdateInstancesPrintable(wxDataViewItem parent_item);
350 
SetVolumeBitmaps(const std::vector<wxBitmap * > & volume_bmps)351     void    SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; }
SetWarningBitmap(wxBitmap * bitmap)352     void    SetWarningBitmap(wxBitmap* bitmap)                          { m_warning_bmp = bitmap; }
353     void    SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type);
354     wxDataViewItem SetPrintableState( PrintIndicator printable, int obj_idx,
355                                       int subobj_idx = -1,
356                                       ItemType subobj_type = itInstance);
357     wxDataViewItem SetObjectPrintableState(PrintIndicator printable, wxDataViewItem obj_item);
358 
SetAssociatedControl(wxDataViewCtrl * ctrl)359     void    SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
360     // Rescale bitmaps for existing Items
361     void    Rescale();
362 
363     wxBitmap    GetVolumeIcon(const Slic3r::ModelVolumeType vol_type,
364                               const bool is_marked = false);
365     void        DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false);
366     t_layer_height_range    GetLayerRangeByItem(const wxDataViewItem& item) const;
367 
368     bool        UpdateColumValues(unsigned col);
369     void        UpdateExtruderBitmap(wxDataViewItem item);
370 
371 private:
372     wxDataViewItem  AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
373     wxDataViewItem  AddInstanceRoot(const wxDataViewItem& parent_item);
374     void            AddAllChildren(const wxDataViewItem& parent);
375 };
376 
377 
378 }
379 }
380 
381 
382 #endif // slic3r_GUI_ObjectDataViewModel_hpp_
383