1 #include "ExtraRenderers.hpp"
2 #include "wxExtensions.hpp"
3 #include "GUI.hpp"
4 #include "I18N.hpp"
5 
6 #include <wx/dc.h>
7 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
8 #include "wx/generic/private/markuptext.h"
9 #include "wx/generic/private/rowheightcache.h"
10 #include "wx/generic/private/widthcalc.h"
11 #endif
12 /*
13 #ifdef __WXGTK__
14 #include "wx/gtk/private.h"
15 #include "wx/gtk/private/value.h"
16 #endif
17 */
18 #if wxUSE_ACCESSIBILITY
19 #include "wx/private/markupparser.h"
20 #endif // wxUSE_ACCESSIBILITY
21 
22 using Slic3r::GUI::from_u8;
23 using Slic3r::GUI::into_u8;
24 
25 
26 //-----------------------------------------------------------------------------
27 // DataViewBitmapText
28 //-----------------------------------------------------------------------------
29 
wxIMPLEMENT_DYNAMIC_CLASS(DataViewBitmapText,wxObject)30 wxIMPLEMENT_DYNAMIC_CLASS(DataViewBitmapText, wxObject)
31 
32 IMPLEMENT_VARIANT_OBJECT(DataViewBitmapText)
33 
34 // ---------------------------------------------------------
35 // BitmapTextRenderer
36 // ---------------------------------------------------------
37 
38 #if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
39 BitmapTextRenderer::BitmapTextRenderer(wxDataViewCellMode mode /*= wxDATAVIEW_CELL_EDITABLE*/,
40                                                  int align /*= wxDVR_DEFAULT_ALIGNMENT*/):
41 wxDataViewRenderer(wxT("PrusaDataViewBitmapText"), mode, align)
42 {
43     SetMode(mode);
44     SetAlignment(align);
45 }
46 #endif // ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
47 
~BitmapTextRenderer()48 BitmapTextRenderer::~BitmapTextRenderer()
49 {
50 #ifdef SUPPORTS_MARKUP
51     #ifdef wxHAS_GENERIC_DATAVIEWCTRL
52     if (m_markupText)
53         delete m_markupText;
54     #endif //wxHAS_GENERIC_DATAVIEWCTRL
55 #endif // SUPPORTS_MARKUP
56 }
57 
EnableMarkup(bool enable)58 void BitmapTextRenderer::EnableMarkup(bool enable)
59 {
60 #ifdef SUPPORTS_MARKUP
61 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
62     if (enable) {
63         if (!m_markupText)
64             m_markupText = new wxItemMarkupText(wxString());
65     }
66     else {
67         if (m_markupText) {
68             delete m_markupText;
69             m_markupText = nullptr;
70         }
71     }
72 #else
73     is_markupText = enable;
74 #endif //wxHAS_GENERIC_DATAVIEWCTRL
75 #endif // SUPPORTS_MARKUP
76 }
77 
SetValue(const wxVariant & value)78 bool BitmapTextRenderer::SetValue(const wxVariant &value)
79 {
80     m_value << value;
81 
82 #ifdef SUPPORTS_MARKUP
83 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
84     if (m_markupText)
85         m_markupText->SetMarkup(m_value.GetText());
86     /*
87 #else
88 #if defined(__WXGTK__)
89    GValue gvalue = G_VALUE_INIT;
90     g_value_init(&gvalue, G_TYPE_STRING);
91     g_value_set_string(&gvalue, wxGTK_CONV_FONT(str.GetText(), GetOwner()->GetOwner()->GetFont()));
92     g_object_set_property(G_OBJECT(m_renderer/ *.GetText()* /), is_markupText ? "markup" : "text", &gvalue);
93     g_value_unset(&gvalue);
94 #endif // __WXGTK__
95     */
96 #endif // wxHAS_GENERIC_DATAVIEWCTRL
97 #endif // SUPPORTS_MARKUP
98 
99     return true;
100 }
101 
GetValue(wxVariant & WXUNUSED (value)) const102 bool BitmapTextRenderer::GetValue(wxVariant& WXUNUSED(value)) const
103 {
104     return false;
105 }
106 
107 #if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY
GetAccessibleDescription() const108 wxString BitmapTextRenderer::GetAccessibleDescription() const
109 {
110 #ifdef SUPPORTS_MARKUP
111     if (m_markupText)
112         return wxMarkupParser::Strip(m_text);
113 #endif // SUPPORTS_MARKUP
114 
115     return m_value.GetText();
116 }
117 #endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
118 
Render(wxRect rect,wxDC * dc,int state)119 bool BitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state)
120 {
121     int xoffset = 0;
122 
123     const wxBitmap& icon = m_value.GetBitmap();
124     if (icon.IsOk())
125     {
126 #ifdef __APPLE__
127         wxSize icon_sz = icon.GetScaledSize();
128 #else
129         wxSize icon_sz = icon.GetSize();
130 #endif
131         dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon_sz.y) / 2);
132         xoffset = icon_sz.x + 4;
133     }
134 
135 #if defined(SUPPORTS_MARKUP) && defined(wxHAS_GENERIC_DATAVIEWCTRL)
136     if (m_markupText)
137     {
138         rect.x += xoffset;
139         m_markupText->Render(GetView(), *dc, rect, 0, GetEllipsizeMode());
140     }
141     else
142 #endif // SUPPORTS_MARKUP && wxHAS_GENERIC_DATAVIEWCTRL
143         RenderText(m_value.GetText(), xoffset, rect, dc, state);
144 
145     return true;
146 }
147 
GetSize() const148 wxSize BitmapTextRenderer::GetSize() const
149 {
150     if (!m_value.GetText().empty())
151     {
152         wxSize size;
153 #if defined(SUPPORTS_MARKUP) && defined(wxHAS_GENERIC_DATAVIEWCTRL)
154         if (m_markupText)
155         {
156             wxDataViewCtrl* const view = GetView();
157             wxClientDC dc(view);
158             if (GetAttr().HasFont())
159                 dc.SetFont(GetAttr().GetEffectiveFont(view->GetFont()));
160 
161             size = m_markupText->Measure(dc);
162 
163             int lines = m_value.GetText().Freq('\n') + 1;
164             size.SetHeight(size.GetHeight() * lines);
165         }
166         else
167 #endif // SUPPORTS_MARKUP && wxHAS_GENERIC_DATAVIEWCTRL
168             size = GetTextExtent(m_value.GetText());
169 
170         if (m_value.GetBitmap().IsOk())
171             size.x += m_value.GetBitmap().GetWidth() + 4;
172         return size;
173     }
174     return wxSize(80, 20);
175 }
176 
177 
CreateEditorCtrl(wxWindow * parent,wxRect labelRect,const wxVariant & value)178 wxWindow* BitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRect, const wxVariant& value)
179 {
180     if (can_create_editor_ctrl && !can_create_editor_ctrl())
181         return nullptr;
182 
183     DataViewBitmapText data;
184     data << value;
185 
186     m_was_unusable_symbol = false;
187 
188     wxPoint position = labelRect.GetPosition();
189     if (data.GetBitmap().IsOk()) {
190         const int bmp_width = data.GetBitmap().GetWidth();
191         position.x += bmp_width;
192         labelRect.SetWidth(labelRect.GetWidth() - bmp_width);
193     }
194 
195     wxTextCtrl* text_editor = new wxTextCtrl(parent, wxID_ANY, data.GetText(),
196                                              position, labelRect.GetSize(), wxTE_PROCESS_ENTER);
197     text_editor->SetInsertionPointEnd();
198     text_editor->SelectAll();
199 
200     return text_editor;
201 }
202 
GetValueFromEditorCtrl(wxWindow * ctrl,wxVariant & value)203 bool BitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value)
204 {
205     wxTextCtrl* text_editor = wxDynamicCast(ctrl, wxTextCtrl);
206     if (!text_editor || text_editor->GetValue().IsEmpty())
207         return false;
208 
209     std::string chosen_name = into_u8(text_editor->GetValue());
210     const char* unusable_symbols = "<>:/\\|?*\"";
211     for (size_t i = 0; i < std::strlen(unusable_symbols); i++) {
212         if (chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
213             m_was_unusable_symbol = true;
214             return false;
215         }
216     }
217 
218     // The icon can't be edited so get its old value and reuse it.
219     wxVariant valueOld;
220     GetView()->GetModel()->GetValue(valueOld, m_item, /*colName*/0);
221 
222     DataViewBitmapText bmpText;
223     bmpText << valueOld;
224 
225     // But replace the text with the value entered by user.
226     bmpText.SetText(text_editor->GetValue());
227 
228     value << bmpText;
229     return true;
230 }
231 
232 // ----------------------------------------------------------------------------
233 // BitmapChoiceRenderer
234 // ----------------------------------------------------------------------------
235 
SetValue(const wxVariant & value)236 bool BitmapChoiceRenderer::SetValue(const wxVariant& value)
237 {
238     m_value << value;
239     return true;
240 }
241 
GetValue(wxVariant & value) const242 bool BitmapChoiceRenderer::GetValue(wxVariant& value) const
243 {
244     value << m_value;
245     return true;
246 }
247 
Render(wxRect rect,wxDC * dc,int state)248 bool BitmapChoiceRenderer::Render(wxRect rect, wxDC* dc, int state)
249 {
250     int xoffset = 0;
251 
252     const wxBitmap& icon = m_value.GetBitmap();
253     if (icon.IsOk())
254     {
255         dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon.GetHeight()) / 2);
256         xoffset = icon.GetWidth() + 4;
257 
258         if (rect.height==0)
259           rect.height= icon.GetHeight();
260     }
261 
262     RenderText(m_value.GetText(), xoffset, rect, dc, state);
263 
264     return true;
265 }
266 
GetSize() const267 wxSize BitmapChoiceRenderer::GetSize() const
268 {
269     wxSize sz = GetTextExtent(m_value.GetText());
270 
271     if (m_value.GetBitmap().IsOk())
272         sz.x += m_value.GetBitmap().GetWidth() + 4;
273 
274     return sz;
275 }
276 
277 
CreateEditorCtrl(wxWindow * parent,wxRect labelRect,const wxVariant & value)278 wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRect, const wxVariant& value)
279 {
280     if (can_create_editor_ctrl && !can_create_editor_ctrl())
281         return nullptr;
282 
283     std::vector<wxBitmap*> icons = get_extruder_color_icons();
284     if (icons.empty())
285         return nullptr;
286 
287     DataViewBitmapText data;
288     data << value;
289 
290     auto c_editor = new wxBitmapComboBox(parent, wxID_ANY, wxEmptyString,
291         labelRect.GetTopLeft(), wxSize(labelRect.GetWidth(), -1),
292         0, nullptr , wxCB_READONLY);
293 
294     int i=0;
295     for (wxBitmap* bmp : icons) {
296         if (i==0) {
297             c_editor->Append(_L("default"), *bmp);
298             ++i;
299         }
300 
301         c_editor->Append(wxString::Format("%d", i), *bmp);
302         ++i;
303     }
304     c_editor->SetSelection(atoi(data.GetText().c_str()));
305 
306     // to avoid event propagation to other sidebar items
307     c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
308             evt.StopPropagation();
309 #ifdef __linux__
310             // FinishEditing grabs new selection and triggers config update. We better call
311             // it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
312             this->FinishEditing();
313 #endif
314     });
315 
316     return c_editor;
317 }
318 
GetValueFromEditorCtrl(wxWindow * ctrl,wxVariant & value)319 bool BitmapChoiceRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value)
320 {
321     wxBitmapComboBox* c = static_cast<wxBitmapComboBox*>(ctrl);
322     int selection = c->GetSelection();
323     if (selection < 0)
324         return false;
325 
326     DataViewBitmapText bmpText;
327 
328     bmpText.SetText(c->GetString(selection));
329     bmpText.SetBitmap(c->GetItemBitmap(selection));
330 
331     value << bmpText;
332     return true;
333 }
334 
335 
336