1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4
5 #include "uibitmapscontroller.h"
6
7 #if VSTGUI_LIVE_EDITING
8
9 #include "uibasedatasource.h"
10 #include "uieditcontroller.h"
11 #include "uidialogcontroller.h"
12 #include "uiviewcreatecontroller.h"
13 #include "../cstream.h"
14 #include "../detail/uiviewcreatorattributes.h"
15 #include "../../lib/cbitmap.h"
16 #include "../../lib/cbitmapfilter.h"
17 #include "../../lib/cdropsource.h"
18 #include "../../lib/cfileselector.h"
19 #include "../../lib/idatapackage.h"
20 #include "../../lib/dragging.h"
21 #include "../../lib/cvstguitimer.h"
22 #include "../../lib/controls/ccolorchooser.h"
23 #include "../../lib/controls/ctextedit.h"
24 #include "../../lib/controls/csearchtextedit.h"
25 #include "../../lib/platform/iplatformbitmap.h"
26
27 namespace VSTGUI {
28 //----------------------------------------------------------------------------------------------------
29 class UIBitmapView : public CView
30 {
31 public:
UIBitmapView(CBitmap * bitmap=nullptr)32 UIBitmapView (CBitmap* bitmap = nullptr)
33 : CView (CRect (0, 0, 0, 0))
34 , zoom (1.)
35 {
36 setBackground (bitmap);
37 }
38
draw(CDrawContext * context)39 void draw (CDrawContext* context) override
40 {
41 if (CBitmap* bitmap = getBackground ())
42 {
43 CGraphicsTransform matrix;
44 matrix.scale (zoom, zoom);
45 CDrawContext::Transform transform (*context, matrix);
46 CRect r (getViewSize ());
47 matrix.inverse ().transform (r);
48 bitmap->CBitmap::draw (context, r);
49 auto* nptBitmap = dynamic_cast<CNinePartTiledBitmap*>(bitmap);
50 if (nptBitmap)
51 {
52 static const CCoord kDefaultOnOffDashLength2[] = {2, 2};
53 const CLineStyle kLineOnOffDash2 (CLineStyle::kLineCapButt, CLineStyle::kLineJoinMiter, 0, 2, kDefaultOnOffDashLength2);
54
55 const CNinePartTiledDescription& offsets = nptBitmap->getPartOffsets ();
56
57 CRect r2;
58 r2.setWidth (nptBitmap->getWidth());
59 r2.setHeight (nptBitmap->getHeight());
60 CPoint p = getViewSize ().getTopLeft ();
61 matrix.inverse ().transform (p);
62 r2.offset (p.x, p.y);
63
64 context->setDrawMode (kAntiAliasing);
65 context->setFrameColor (kBlueCColor);
66 context->setLineWidth (1);
67 context->setLineStyle (kLineSolid);
68
69 context->drawLine (CPoint (r2.left, r2.top + offsets.top), CPoint (r2.right, r2.top + offsets.top));
70 context->drawLine (CPoint (r2.left, r2.bottom - offsets.bottom), CPoint (r2.right, r2.bottom - offsets.bottom));
71 context->drawLine (CPoint (r2.left + offsets.left, r2.top), CPoint (r2.left + offsets.left, r2.bottom));
72 context->drawLine (CPoint (r2.right - offsets.right, r2.top), CPoint (r2.right - offsets.right, r2.bottom));
73
74 context->setFrameColor (kRedCColor);
75 context->setLineWidth (1);
76 context->setLineStyle (kLineOnOffDash2);
77
78 context->drawLine (CPoint (r2.left, r2.top + offsets.top), CPoint (r2.right, r2.top + offsets.top));
79 context->drawLine (CPoint (r2.left, r2.bottom - offsets.bottom), CPoint (r2.right, r2.bottom - offsets.bottom));
80 context->drawLine (CPoint (r2.left + offsets.left, r2.top), CPoint (r2.left + offsets.left, r2.bottom));
81 context->drawLine (CPoint (r2.right - offsets.right, r2.top), CPoint (r2.right - offsets.right, r2.bottom));
82 }
83 }
84 }
85
setZoom(CCoord factor)86 void setZoom (CCoord factor)
87 {
88 if (factor <= 0. || factor == zoom)
89 return;
90 zoom = factor;
91 updateSize ();
92 }
93
updateSize()94 void updateSize ()
95 {
96 if (CBitmap* bitmap = getBackground ())
97 {
98 CCoord width = bitmap ? bitmap->getWidth () : 0;
99 CCoord height = bitmap ? bitmap->getHeight () : 0;
100 CRect r (getViewSize ());
101
102 CGraphicsTransform ().scale (zoom, zoom).transform (width, height);
103 width = std::floor (width + 0.5);
104 height = std::floor (height + 0.5);
105 r.setWidth (width);
106 r.setHeight (height);
107
108 if (getViewSize () != r)
109 {
110 setViewSize (r);
111 setMouseableArea (r);
112 }
113 }
114 }
115
setBackground(CBitmap * background)116 void setBackground (CBitmap *background) override
117 {
118 auto platformBitmap = background ? background->getPlatformBitmap () : nullptr;
119 if (platformBitmap && platformBitmap->getScaleFactor () != 1.)
120 {
121 // get rid of the scale factor
122 auto buffer = IPlatformBitmap::createMemoryPNGRepresentation (platformBitmap);
123 if (!buffer.empty ())
124 {
125 auto newPlatformBitmap = IPlatformBitmap::createFromMemory (buffer.data (), static_cast<uint32_t> (buffer.size ()));
126 CView::setBackground (makeOwned<CBitmap> (newPlatformBitmap));
127 }
128 }
129 else
130 CView::setBackground (background);
131 updateSize ();
132 }
133
134 protected:
135 CCoord zoom;
136 };
137
138 //----------------------------------------------------------------------------------------------------
139 class UIBitmapsDataSource : public UIBaseDataSource
140 {
141 public:
142 UIBitmapsDataSource (UIDescription* description, IActionPerformer* actionPerformer, GenericStringListDataBrowserSourceSelectionChanged* delegate);
143
144 CBitmap* getSelectedBitmap ();
145 UTF8StringPtr getSelectedBitmapName ();
146
147 bool add () override;
148 protected:
149 void onUIDescBitmapChanged (UIDescription* desc) override;
150 void getNames (std::list<const std::string*>& names) override;
151 bool addItem (UTF8StringPtr name) override;
152 bool removeItem (UTF8StringPtr name) override;
153 bool performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) override;
getDefaultsName()154 UTF8StringPtr getDefaultsName () override { return "UIBitmapsDataSource"; }
155
156 bool addBitmap (UTF8StringPtr path, std::string& outName);
157
158 void dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser) override;
159 void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser) override;
160 void dbOnDragEnterBrowser (IDataPackage* drag, CDataBrowser* browser) override;
161 void dbOnDragExitBrowser (IDataPackage* drag, CDataBrowser* browser) override;
162 DragOperation dbOnDragEnterCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser) override;
163 void dbOnDragExitCell (int32_t row, int32_t column, IDataPackage* drag, CDataBrowser* browser) override;
164 bool dbOnDropInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser) override;
165
166 CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override;
167 CMouseEventResult dbOnMouseMoved (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override;
168
169 SharedPointer<CColorChooser> colorChooser;
170 DragStartMouseObserver dragStartMouseObserver;
171 bool dragContainsBitmaps;
172 };
173
174 //----------------------------------------------------------------------------------------------------
UIBitmapsDataSource(UIDescription * description,IActionPerformer * actionPerformer,GenericStringListDataBrowserSourceSelectionChanged * delegate)175 UIBitmapsDataSource::UIBitmapsDataSource (UIDescription* description, IActionPerformer* actionPerformer, GenericStringListDataBrowserSourceSelectionChanged* delegate)
176 : UIBaseDataSource (description, actionPerformer, delegate)
177 , dragContainsBitmaps (false)
178 {
179 }
180
181 //----------------------------------------------------------------------------------------------------
onUIDescBitmapChanged(UIDescription * desc)182 void UIBitmapsDataSource::onUIDescBitmapChanged (UIDescription* desc)
183 {
184 onUIDescriptionUpdate ();
185 }
186
187 //----------------------------------------------------------------------------------------------------
dbDrawCell(CDrawContext * context,const CRect & size,int32_t row,int32_t column,int32_t flags,CDataBrowser * browser)188 void UIBitmapsDataSource::dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser)
189 {
190 auto drawWidth = size.getHeight ();
191 GenericStringListDataBrowserSource::drawRowBackground (context, size, row, flags, browser);
192 CRect r (size);
193 r.right -= drawWidth;
194 GenericStringListDataBrowserSource::drawRowString (context, r, row, flags, browser);
195 if (auto bitmap = description->getBitmap (names.at (static_cast<uint32_t> (row)).data ()))
196 {
197 r = size;
198 r.left = r.right - drawWidth;
199 r.inset (2, 2);
200 auto bitmapSize = bitmap->getSize ();
201 auto scaleX = r.getWidth () / bitmapSize.x;
202 auto scaleY = r.getHeight () / bitmapSize.y;
203 CGraphicsTransform matrix;
204 matrix.scale (scaleX, scaleY);
205 CDrawContext::Transform t (*context, matrix);
206 matrix.inverse ().transform (r);
207 bitmap->CBitmap::draw (context, r);
208 }
209 }
210
211 //----------------------------------------------------------------------------------------------------
dbCellSetupTextEdit(int32_t row,int32_t column,CTextEdit * control,CDataBrowser * browser)212 void UIBitmapsDataSource::dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser)
213 {
214 UIBaseDataSource::dbCellSetupTextEdit (row, column, control, browser);
215 CRect r (control->getViewSize ());
216 auto drawWidth = r.getHeight ();
217 r.right -= drawWidth;
218 control->setViewSize (r);
219 }
220
221 //----------------------------------------------------------------------------------------------------
dbOnMouseDown(const CPoint & where,const CButtonState & buttons,int32_t row,int32_t column,CDataBrowser * browser)222 CMouseEventResult UIBitmapsDataSource::dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser)
223 {
224 if (buttons.isDoubleClick () && row >= 0 && row < static_cast<int32_t> (names.size ()))
225 {
226 auto r = browser->getCellBounds ({row, column});
227 auto drawWidth = r.getHeight ();
228 r.left = r.right - drawWidth;
229 if (r.pointInside (where))
230 {
231 delegate->dbRowDoubleClick (row, this);
232 return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
233 }
234 }
235 dragStartMouseObserver.init (where);
236 UIBaseDataSource::dbOnMouseDown (where, buttons, row, column, browser);
237 return kMouseEventHandled;
238 }
239
240 //----------------------------------------------------------------------------------------------------
dbOnMouseMoved(const CPoint & where,const CButtonState & buttons,int32_t row,int32_t column,CDataBrowser * browser)241 CMouseEventResult UIBitmapsDataSource::dbOnMouseMoved (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser)
242 {
243 if (buttons.isLeftButton () && dragStartMouseObserver.shouldStartDrag (where))
244 {
245 if (auto bitmap = getSelectedBitmap ())
246 {
247 UIAttributes attr;
248 attr.setAttribute (UIViewCreator::kAttrBitmap, getSelectedBitmapName ());
249 attr.setPointAttribute (UIViewCreator::kAttrSize, bitmap->getSize ());
250 const auto factory =
251 dynamic_cast<const UIViewFactory*> (description->getViewFactory ());
252 if (auto selection = createSelectionFromViewName (UIViewCreator::kCView, factory,
253 description, &attr))
254 {
255 CMemoryStream stream (1024, 1024, false);
256 if (selection->store (stream, description))
257 {
258 stream.end ();
259 auto dropSource = CDropSource::create (stream.getBuffer (),
260 static_cast<uint32_t> (stream.tell ()),
261 CDropSource::kText);
262 browser->doDrag (DragDescription (dropSource, {}, bitmap));
263 return kMouseMoveEventHandledButDontNeedMoreEvents;
264 }
265 }
266 }
267 }
268 return kMouseEventHandled;
269 }
270
271 //----------------------------------------------------------------------------------------------------
dbOnDragEnterBrowser(IDataPackage * drag,CDataBrowser * browser)272 void UIBitmapsDataSource::dbOnDragEnterBrowser (IDataPackage* drag, CDataBrowser* browser)
273 {
274 uint32_t index = 0;
275 IDataPackage::Type type;
276 const void* item = nullptr;
277 while (drag->getData (index, item, type) > 0)
278 {
279 if (type == IDataPackage::kFilePath)
280 {
281 const char* ext = strrchr (static_cast<const char*> (item), '.');
282 if (ext)
283 {
284 std::string extStr (ext);
285 std::transform (extStr.begin (), extStr.end (), extStr.begin (), ::tolower);
286 if (extStr == ".png" || extStr == ".bmp" || extStr == ".jpg" || extStr == ".jpeg")
287 {
288 dragContainsBitmaps = true;
289 break;
290 }
291 }
292 }
293 index++;
294 }
295 if (dragContainsBitmaps)
296 browser->getFrame ()->setCursor (kCursorCopy);
297 }
298
299 //----------------------------------------------------------------------------------------------------
dbOnDragExitBrowser(IDataPackage * drag,CDataBrowser * browser)300 void UIBitmapsDataSource::dbOnDragExitBrowser (IDataPackage* drag, CDataBrowser* browser)
301 {
302 if (dragContainsBitmaps)
303 browser->getFrame ()->setCursor (kCursorNotAllowed);
304 }
305
306 //----------------------------------------------------------------------------------------------------
dbOnDragEnterCell(int32_t row,int32_t column,const CPoint & where,IDataPackage * drag,CDataBrowser * browser)307 DragOperation UIBitmapsDataSource::dbOnDragEnterCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser)
308 {
309 return dragContainsBitmaps ? DragOperation::Copy : DragOperation::None;
310 }
311
312 //----------------------------------------------------------------------------------------------------
dbOnDragExitCell(int32_t row,int32_t column,IDataPackage * drag,CDataBrowser * browser)313 void UIBitmapsDataSource::dbOnDragExitCell (int32_t row, int32_t column, IDataPackage* drag, CDataBrowser* browser)
314 {
315 }
316
317 //----------------------------------------------------------------------------------------------------
dbOnDropInCell(int32_t row,int32_t column,const CPoint & where,IDataPackage * drag,CDataBrowser * browser)318 bool UIBitmapsDataSource::dbOnDropInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser)
319 {
320 if (!dragContainsBitmaps)
321 return false;
322
323 bool didBeganGroupAction = false;
324 uint32_t index = 0;
325 IDataPackage::Type type;
326 const void* item = nullptr;
327 UTF8String firstNewBitmapName;
328 while (drag->getData (index++, item, type) > 0)
329 {
330 if (type == IDataPackage::kFilePath)
331 {
332 auto path = static_cast<UTF8StringPtr> (item);
333 const char* ext = strrchr (path, '.');
334 if (ext)
335 {
336 std::string extStr (ext);
337 std::transform (extStr.begin (), extStr.end (), extStr.begin (), ::tolower);
338 if (extStr == ".png" || extStr == ".bmp" || extStr == ".jpg" || extStr == ".jpeg")
339 {
340 if (!didBeganGroupAction)
341 {
342 actionPerformer->beginGroupAction ("Add Bitmaps");
343 didBeganGroupAction = true;
344 }
345 std::string name;
346 addBitmap (path, name);
347 if (firstNewBitmapName.empty ())
348 firstNewBitmapName = name;
349 }
350 }
351 }
352 }
353 if (didBeganGroupAction)
354 {
355 actionPerformer->finishGroupAction ();
356 vstgui_assert (!firstNewBitmapName.empty ());
357 selectName (firstNewBitmapName);
358 }
359 dragContainsBitmaps = false;
360 return true;
361 }
362
363 //----------------------------------------------------------------------------------------------------
getNames(std::list<const std::string * > & names)364 void UIBitmapsDataSource::getNames (std::list<const std::string*>& names)
365 {
366 description->collectBitmapNames (names);
367 }
368
369 //----------------------------------------------------------------------------------------------------
addItem(UTF8StringPtr name)370 bool UIBitmapsDataSource::addItem (UTF8StringPtr name)
371 {
372 actionPerformer->performBitmapChange (name, nullptr);
373 return true;
374 }
375
376 //----------------------------------------------------------------------------------------------------
removeItem(UTF8StringPtr name)377 bool UIBitmapsDataSource::removeItem (UTF8StringPtr name)
378 {
379 actionPerformer->performBitmapChange (name, nullptr, true);
380 return true;
381 }
382
383 //----------------------------------------------------------------------------------------------------
performNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)384 bool UIBitmapsDataSource::performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
385 {
386 actionPerformer->performBitmapNameChange (oldName, newName);
387 return true;
388 }
389
390 //----------------------------------------------------------------------------------------------------
getSelectedBitmap()391 CBitmap* UIBitmapsDataSource::getSelectedBitmap ()
392 {
393 int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow() : CDataBrowser::kNoSelection;
394 if (selectedRow != CDataBrowser::kNoSelection && selectedRow < (int32_t)names.size ())
395 return description->getBitmap (names.at (static_cast<uint32_t> (selectedRow)).data ());
396 return nullptr;
397 }
398
399 //----------------------------------------------------------------------------------------------------
getSelectedBitmapName()400 UTF8StringPtr UIBitmapsDataSource::getSelectedBitmapName ()
401 {
402 int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow() : CDataBrowser::kNoSelection;
403 if (selectedRow != CDataBrowser::kNoSelection && selectedRow < (int32_t)names.size ())
404 return names.at (static_cast<uint32_t> (selectedRow)).data ();
405 return nullptr;
406 }
407
408 //----------------------------------------------------------------------------------------------------
addBitmap(UTF8StringPtr path,std::string & outName)409 bool UIBitmapsDataSource::addBitmap (UTF8StringPtr path, std::string& outName)
410 {
411 bool result = false;
412 outName = path;
413 unixfyPath (outName);
414 size_t index = outName.find_last_of (unixPathSeparator);
415 outName.erase (0, index+1);
416 index = outName.find_last_of ('.');
417 if (index == std::string::npos)
418 return false;
419
420 outName.erase (index);
421 if (createUniqueName (outName))
422 {
423 std::string pathStr (path);
424 UTF8StringPtr descPath = description->getFilePath ();
425 if (descPath && descPath[0] != 0)
426 {
427 std::string descPathStr (descPath);
428 unixfyPath (descPathStr);
429 if (removeLastPathComponent (descPathStr))
430 {
431 if (pathStr.find (descPathStr) == 0)
432 {
433 pathStr.erase (0, descPathStr.length () + 1);
434 }
435 }
436 }
437 actionPerformer->performBitmapChange (outName.data (), pathStr.data ());
438 result = true;
439 }
440 return result;
441 }
442
443 //----------------------------------------------------------------------------------------------------
add()444 bool UIBitmapsDataSource::add ()
445 {
446 bool result = false;
447 auto fs = owned (CNewFileSelector::create (dataBrowser->getFrame ()));
448 if (fs)
449 {
450 fs->addFileExtension (CFileExtension ("PNG", "PNG", "image/png"));
451 fs->setAllowMultiFileSelection (true);
452 if (fs->runModal ())
453 {
454 auto numFiles = static_cast<uint32_t> (fs->getNumSelectedFiles ());
455 if (numFiles > 1)
456 actionPerformer->beginGroupAction ("Add Bitmaps");
457 for (uint32_t i = 0; i < numFiles; i++)
458 {
459 UTF8StringPtr path = fs->getSelectedFile (i);
460 if (path)
461 {
462 std::string newName;
463 if (addBitmap (path, newName) && i == numFiles - 1)
464 {
465 int32_t row = selectName (newName.data ());
466 if (row != -1)
467 dbOnMouseDown (CPoint (0, 0), CButtonState (kLButton|kDoubleClick), row, 0, dataBrowser);
468 result = true;
469 }
470 }
471 }
472 if (numFiles > 1)
473 actionPerformer->finishGroupAction ();
474 }
475 }
476 return result;
477 }
478
479 //----------------------------------------------------------------------------------------------------
480 //----------------------------------------------------------------------------------------------------
481 //----------------------------------------------------------------------------------------------------
482 class UIBitmapSettingsController : public NonAtomicReferenceCounted,
483 public IDialogController,
484 public IController
485 {
486 public:
487 UIBitmapSettingsController (CBitmap* bitmap, const std::string& bitmapName, UIDescription* description, IActionPerformer* actionPerformer);
488 ~UIBitmapSettingsController () noexcept override = default;
489
490 CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
491 CView* createView (const UIAttributes& attributes, const IUIDescription* description) override;
492 void valueChanged (CControl* pControl) override;
493 void controlBeginEdit (CControl* pControl) override;
494 void controlEndEdit (CControl* pControl) override;
495
496 void onDialogButton1Clicked (UIDialogController*) override;
497 void onDialogButton2Clicked (UIDialogController*) override;
498 void onDialogShow (UIDialogController*) override;
499 protected:
500 void updateNinePartTiledControls ();
501 static bool stringToValue (UTF8StringPtr txt, float& result, CTextEdit::StringToValueUserData* userData);
502 static bool valueToString (float value, char utf8String[256], CParamDisplay::ValueToStringUserData* userData);
503
504 SharedPointer<CBitmap> bitmap;
505 SharedPointer<UIDescription> editDescription;
506 SharedPointer<UIBitmapView> bitmapView;
507 IActionPerformer* actionPerformer;
508 std::string bitmapName;
509 CRect origOffsets;
510
511 enum {
512 kBitmapPathTag,
513 kBitmapWidthTag,
514 kBitmapHeightTag,
515 kNinePartTiledTag,
516 kNinePartTiledLeftTag,
517 kNinePartTiledTopTag,
518 kNinePartTiledRightTag,
519 kNinePartTiledBottomTag,
520 kZoomTag,
521 kZoomTextTag,
522 kNumTags
523 };
524 CControl* controls[kNumTags];
525 };
526
527 //----------------------------------------------------------------------------------------------------
UIBitmapSettingsController(CBitmap * bitmap,const std::string & bitmapName,UIDescription * description,IActionPerformer * actionPerformer)528 UIBitmapSettingsController::UIBitmapSettingsController (CBitmap* bitmap, const std::string& bitmapName, UIDescription* description, IActionPerformer* actionPerformer)
529 : bitmap (bitmap)
530 , editDescription (description)
531 , actionPerformer (actionPerformer)
532 , bitmapName (bitmapName)
533 , origOffsets (10, 10, 10, 10)
534 {
535 for (auto& control : controls)
536 control = nullptr;
537 }
538
539 //----------------------------------------------------------------------------------------------------
updateNinePartTiledControls()540 void UIBitmapSettingsController::updateNinePartTiledControls ()
541 {
542 auto* nptb = bitmap.cast<CNinePartTiledBitmap> ();
543 if (nptb)
544 {
545 controls[kNinePartTiledTag]->setValueNormalized (1);
546 const CNinePartTiledDescription& offsets = nptb->getPartOffsets ();
547 controls[kNinePartTiledLeftTag]->setValue ((float)offsets.left);
548 controls[kNinePartTiledTopTag]->setValue ((float)offsets.top);
549 controls[kNinePartTiledRightTag]->setValue ((float)offsets.right);
550 controls[kNinePartTiledBottomTag]->setValue ((float)offsets.bottom);
551 }
552 else
553 {
554 controls[kNinePartTiledTag]->setValueNormalized (0.);
555 for (int32_t i = kNinePartTiledLeftTag; i <= kNinePartTiledBottomTag; i++)
556 {
557 auto* label = dynamic_cast<CTextLabel*>(controls[i]);
558 if (label)
559 label->setText ("");
560 }
561 }
562 for (int32_t i = kNinePartTiledLeftTag; i <= kNinePartTiledBottomTag; i++)
563 {
564 controls[i]->setMouseEnabled (nptb ? true : false);
565 }
566 }
567
568 //----------------------------------------------------------------------------------------------------
valueChanged(CControl * control)569 void UIBitmapSettingsController::valueChanged (CControl* control)
570 {
571 switch (control->getTag ())
572 {
573 case kBitmapPathTag:
574 {
575 auto* edit = dynamic_cast<CTextEdit*>(control);
576 if (edit)
577 {
578 actionPerformer->performBitmapChange (bitmapName.data (), edit->getText ());
579 bitmap = editDescription->getBitmap (bitmapName.data ());
580 bitmapView->setBackground (bitmap);
581 updateNinePartTiledControls ();
582 }
583 break;
584 }
585 case kNinePartTiledTag:
586 {
587 auto* nptb = bitmap.cast<CNinePartTiledBitmap> ();
588 if (nptb)
589 {
590 origOffsets.left = nptb->getPartOffsets ().left;
591 origOffsets.top = nptb->getPartOffsets ().top;
592 origOffsets.right = nptb->getPartOffsets ().right;
593 origOffsets.bottom = nptb->getPartOffsets ().bottom;
594 }
595 bool checked = control->getValue () == control->getMax ();
596 actionPerformer->performBitmapNinePartTiledChange (bitmapName.data (), checked ? &origOffsets : nullptr);
597 bitmap = editDescription->getBitmap (bitmapName.data ());
598 bitmapView->setBackground (bitmap);
599 updateNinePartTiledControls ();
600 break;
601 }
602 case kNinePartTiledLeftTag:
603 case kNinePartTiledTopTag:
604 case kNinePartTiledRightTag:
605 case kNinePartTiledBottomTag:
606 {
607 CRect r;
608 r.left = controls[kNinePartTiledLeftTag]->getValue ();
609 r.top = controls[kNinePartTiledTopTag]->getValue ();
610 r.right = controls[kNinePartTiledRightTag]->getValue ();
611 r.bottom = controls[kNinePartTiledBottomTag]->getValue ();
612 actionPerformer->performBitmapNinePartTiledChange (bitmapName.data (), &r);
613 bitmap = editDescription->getBitmap (bitmapName.data ());
614 bitmapView->setBackground (bitmap);
615 updateNinePartTiledControls ();
616 SharedPointer<CTextEdit> textEdit = SharedPointer<CControl> (control).cast<CTextEdit> ();
617 if (textEdit && textEdit->bWasReturnPressed)
618 {
619 textEdit->getFrame ()->doAfterEventProcessing ([=] () {
620 textEdit->takeFocus ();
621 });
622 }
623 break;
624 }
625 case kZoomTag:
626 {
627 CCoord zoom = floor (control->getValue () / 10. + 0.5);
628 control->setValue ((float)zoom * 10.f);
629 controls[kZoomTextTag]->setValue ((float)zoom * 10.f);
630 bitmapView->setZoom (zoom / 10.);
631 controls[kZoomTextTag]->invalid ();
632 control->invalid ();
633 break;
634 }
635 }
636 }
637
638 //----------------------------------------------------------------------------------------------------
controlBeginEdit(CControl * control)639 void UIBitmapSettingsController::controlBeginEdit (CControl* control)
640 {
641 }
642
643 //----------------------------------------------------------------------------------------------------
controlEndEdit(CControl * control)644 void UIBitmapSettingsController::controlEndEdit (CControl* control)
645 {
646 }
647
648 //----------------------------------------------------------------------------------------------------
onDialogButton1Clicked(UIDialogController *)649 void UIBitmapSettingsController::onDialogButton1Clicked (UIDialogController*)
650 {
651 }
652
653 //----------------------------------------------------------------------------------------------------
onDialogButton2Clicked(UIDialogController *)654 void UIBitmapSettingsController::onDialogButton2Clicked (UIDialogController*)
655 {
656 }
657
658 //----------------------------------------------------------------------------------------------------
onDialogShow(UIDialogController *)659 void UIBitmapSettingsController::onDialogShow (UIDialogController*)
660 {
661 bitmapView->setBackground (bitmap);
662 updateNinePartTiledControls ();
663 }
664
665 //----------------------------------------------------------------------------------------------------
verifyView(CView * view,const UIAttributes & attributes,const IUIDescription * description)666 CView* UIBitmapSettingsController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
667 {
668 auto* control = dynamic_cast<CControl*>(view);
669 if (control && control->getTag () >= 0 && control->getTag () < kNumTags)
670 {
671 controls[control->getTag ()] = control;
672 switch (control->getTag ())
673 {
674 case kBitmapPathTag:
675 {
676 auto* bitmapPathEdit = dynamic_cast<CTextEdit*> (control);
677 if (bitmapPathEdit)
678 bitmapPathEdit->setText (bitmap->getResourceDescription ().u.name);
679 break;
680 }
681 case kBitmapWidthTag:
682 {
683 auto* label = dynamic_cast<CTextLabel*>(control);
684 if (label)
685 {
686 float width = bitmap->getPlatformBitmap () ? (float)bitmap->getPlatformBitmap ()->getSize ().x : 0.f;
687 label->setPrecision (0);
688 label->setMax (width);
689 label->setValue (width);
690 label->sizeToFit ();
691 }
692 break;
693 }
694 case kBitmapHeightTag:
695 {
696 auto* label = dynamic_cast<CTextLabel*>(control);
697 if (label)
698 {
699 float height = bitmap->getPlatformBitmap () ? (float)bitmap->getPlatformBitmap ()->getSize ().y : 0.f;
700 label->setPrecision (0);
701 label->setMax (height);
702 label->setValue (height);
703 label->sizeToFit ();
704 if (controls[kBitmapWidthTag])
705 {
706 CRect r = control->getViewSize ();
707 if (controls[kBitmapWidthTag]->getWidth () > r.getWidth ())
708 {
709 r.setWidth (controls[kBitmapWidthTag]->getWidth ());
710 control->setViewSize (r);
711 }
712 else
713 {
714 r = controls[kBitmapWidthTag]->getViewSize ();
715 r.setWidth (control->getWidth ());
716 controls[kBitmapWidthTag]->setViewSize (r);
717 }
718 }
719 }
720 break;
721 }
722 case kNinePartTiledLeftTag:
723 case kNinePartTiledRightTag:
724 {
725 auto* textEdit = dynamic_cast<CTextEdit*>(control);
726 if (textEdit)
727 {
728 textEdit->setPrecision (0);
729 textEdit->setStringToValueFunction (stringToValue);
730 }
731 control->setMax ((float)bitmap->getWidth ());
732 break;
733 }
734 case kNinePartTiledTopTag:
735 case kNinePartTiledBottomTag:
736 {
737 auto* textEdit = dynamic_cast<CTextEdit*>(control);
738 if (textEdit)
739 {
740 textEdit->setPrecision (0);
741 textEdit->setStringToValueFunction (stringToValue);
742 }
743 control->setMax ((float)bitmap->getHeight ());
744 break;
745 }
746 case kZoomTag:
747 {
748 control->setValue (100);
749 break;
750 }
751 case kZoomTextTag:
752 {
753 auto* label = dynamic_cast<CTextLabel*>(control);
754 if (label)
755 {
756 label->setValueToStringFunction (valueToString);
757 }
758 control->setValue (100);
759 }
760 }
761 }
762 return view;
763 }
764
765 //----------------------------------------------------------------------------------------------------
createView(const UIAttributes & attributes,const IUIDescription * description)766 CView* UIBitmapSettingsController::createView (const UIAttributes& attributes, const IUIDescription* description)
767 {
768 const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
769 if (name)
770 {
771 if (*name == "BitmapView")
772 {
773 bitmapView = new UIBitmapView ();
774 return bitmapView;
775 }
776 }
777 return nullptr;
778 }
779
780 //----------------------------------------------------------------------------------------------------
valueToString(float value,char utf8String[256],CParamDisplay::ValueToStringUserData * userData)781 bool UIBitmapSettingsController::valueToString (float value, char utf8String[256], CParamDisplay::ValueToStringUserData* userData)
782 {
783 auto intValue = (int32_t)value;
784 std::stringstream str;
785 str << intValue;
786 str << "%";
787 std::strcpy (utf8String, str.str ().data ());
788 return true;
789 }
790
791
792 //----------------------------------------------------------------------------------------------------
stringToValue(UTF8StringPtr txt,float & result,CTextEdit::StringToValueUserData * userData)793 bool UIBitmapSettingsController::stringToValue (UTF8StringPtr txt, float& result, CTextEdit::StringToValueUserData* userData)
794 {
795 int32_t value = txt ? (int32_t)strtol (txt, nullptr, 10) : 0;
796 result = (float)value;
797 return true;
798 }
799
800 //----------------------------------------------------------------------------------------------------
801 //----------------------------------------------------------------------------------------------------
802 //----------------------------------------------------------------------------------------------------
UIBitmapsController(IController * baseController,UIDescription * description,IActionPerformer * actionPerformer)803 UIBitmapsController::UIBitmapsController (IController* baseController, UIDescription* description, IActionPerformer* actionPerformer)
804 : DelegationController (baseController)
805 , editDescription (description)
806 , actionPerformer (actionPerformer)
807 , dataSource (nullptr)
808 {
809 dataSource = new UIBitmapsDataSource (editDescription, actionPerformer, this);
810 UIEditController::setupDataSource (dataSource);
811 }
812
813 //----------------------------------------------------------------------------------------------------
~UIBitmapsController()814 UIBitmapsController::~UIBitmapsController ()
815 {
816 dataSource->forget ();
817 }
818
819 //----------------------------------------------------------------------------------------------------
showSettingsDialog()820 void UIBitmapsController::showSettingsDialog ()
821 {
822 auto* dc = new UIDialogController (this, bitmapPathEdit->getFrame ());
823 auto fsController = makeOwned<UIBitmapSettingsController> (dataSource->getSelectedBitmap (),
824 dataSource->getSelectedBitmapName (),
825 editDescription, actionPerformer);
826 dc->run ("bitmap.settings", "Bitmap Settings", "Close", nullptr, fsController,
827 UIEditController::getEditorDescription ());
828 }
829
830 //----------------------------------------------------------------------------------------------------
createView(const UIAttributes & attributes,const IUIDescription * description)831 CView* UIBitmapsController::createView (const UIAttributes& attributes, const IUIDescription* description)
832 {
833 const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
834 if (name)
835 {
836 if (*name == "BitmapsBrowser")
837 {
838 CDataBrowser* dataBrowser = new CDataBrowser (CRect (0, 0, 0, 0), dataSource, CDataBrowser::kDrawRowLines|CScrollView::kHorizontalScrollbar | CScrollView::kVerticalScrollbar);
839 return dataBrowser;
840 }
841 else if (*name == "BitmapView")
842 {
843 bitmapView = new UIBitmapView ();
844 return bitmapView;
845 }
846 }
847 return DelegationController::createView (attributes, description);
848 }
849
850 //----------------------------------------------------------------------------------------------------
verifyView(CView * view,const UIAttributes & attributes,const IUIDescription * description)851 CView* UIBitmapsController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
852 {
853 auto searchField = dynamic_cast<CSearchTextEdit*>(view);
854 if (searchField && searchField->getTag () == kSearchTag)
855 {
856 dataSource->setSearchFieldControl (searchField);
857 return searchField;
858 }
859 auto* textEdit = dynamic_cast<CTextEdit*>(view);
860 if (textEdit)
861 {
862 switch (textEdit->getTag ())
863 {
864 case kBitmapPathTag:
865 {
866 bitmapPathEdit = textEdit;
867 textEdit->setMouseEnabled (false);
868 break;
869 }
870 }
871 }
872 else
873 {
874 auto* control = dynamic_cast<CControl*> (view);
875 if (control)
876 {
877 if (control->getTag () == kSettingsTag)
878 {
879 settingButton = control;
880 settingButton->setMouseEnabled (false);
881 }
882 }
883 }
884 return DelegationController::verifyView (view, attributes, description);
885 }
886
887 //----------------------------------------------------------------------------------------------------
getControlListener(UTF8StringPtr name)888 IControlListener* UIBitmapsController::getControlListener (UTF8StringPtr name)
889 {
890 return this;
891 }
892
893 //----------------------------------------------------------------------------------------------------
valueChanged(CControl * pControl)894 void UIBitmapsController::valueChanged (CControl* pControl)
895 {
896 switch (pControl->getTag ())
897 {
898 case kAddTag:
899 {
900 if (pControl->getValue () == pControl->getMax ())
901 {
902 dataSource->add ();
903 }
904 break;
905 }
906 case kRemoveTag:
907 {
908 if (pControl->getValue () == pControl->getMax ())
909 {
910 dataSource->remove ();
911 }
912 break;
913 }
914 case kBitmapPathTag:
915 {
916 UTF8StringPtr bitmapName = dataSource->getSelectedBitmapName ();
917 if (bitmapName)
918 {
919 auto* edit = dynamic_cast<CTextEdit*>(pControl);
920 if (edit)
921 actionPerformer->performBitmapChange (bitmapName, edit->getText ());
922 }
923 break;
924 }
925 case kSettingsTag:
926 {
927 if (pControl->getValue () == pControl->getMax ())
928 {
929 showSettingsDialog ();
930 }
931 break;
932 }
933 }
934 }
935
936 //----------------------------------------------------------------------------------------------------
dbSelectionChanged(int32_t selectedRow,GenericStringListDataBrowserSource * source)937 void UIBitmapsController::dbSelectionChanged (int32_t selectedRow, GenericStringListDataBrowserSource* source)
938 {
939 if (dataSource)
940 {
941 CBitmap* bitmap = dataSource->getSelectedBitmap ();
942 UTF8StringPtr selectedBitmapName = dataSource->getSelectedBitmapName ();
943 if (bitmapView)
944 {
945 bitmapView->setBackground (bitmap);
946 if (bitmapView->getParentView ())
947 bitmapView->getParentView ()->invalid ();
948 }
949 if (bitmapPathEdit)
950 {
951 bitmapPathEdit->setText (bitmap ? bitmap->getResourceDescription ().u.name : nullptr);
952 bitmapPathEdit->setMouseEnabled (selectedBitmapName ? true : false);
953 }
954 if (settingButton)
955 {
956 settingButton->setMouseEnabled (selectedBitmapName ? true : false);
957 }
958 }
959 }
960
961 //----------------------------------------------------------------------------------------------------
dbRowDoubleClick(int32_t row,GenericStringListDataBrowserSource * source)962 void UIBitmapsController::dbRowDoubleClick (int32_t row, GenericStringListDataBrowserSource* source)
963 {
964 showSettingsDialog ();
965 }
966
967 //----------------------------------------------------------------------------------------------------
valueToString(float value,char utf8String[256],void * userData)968 bool UIBitmapsController::valueToString (float value, char utf8String[256], void* userData)
969 {
970 auto intValue = (int32_t)value;
971 std::stringstream str;
972 str << intValue;
973 std::strcpy (utf8String, str.str ().data ());
974 return true;
975 }
976
977 //----------------------------------------------------------------------------------------------------
stringToValue(UTF8StringPtr txt,float & result,void * userData)978 bool UIBitmapsController::stringToValue (UTF8StringPtr txt, float& result, void* userData)
979 {
980 int32_t value = txt ? (int32_t)strtol (txt, nullptr, 10) : 0;
981 result = (float)value;
982 return true;
983 }
984
985 } // VSTGUI
986
987 #endif // VSTGUI_LIVE_EDITING
988