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