ASPiK SDK
uibasedatasource.h
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 #ifndef __uibasedatasource__
6 #define __uibasedatasource__
7 
8 #include "../iuidescription.h"
9 
10 #if VSTGUI_LIVE_EDITING
11 
12 #include "../uiattributes.h"
13 #include "../../lib/cdatabrowser.h"
14 #include "../../lib/controls/csearchtextedit.h"
15 #include "../../lib/controls/cscrollbar.h"
16 #include <sstream>
17 #include <algorithm>
18 
19 namespace VSTGUI {
20 
21 //----------------------------------------------------------------------------------------------------
22 class UIBaseDataSource : public GenericStringListDataBrowserSource, public IControlListener
23 {
24 public:
25  using StringVector = GenericStringListDataBrowserSource::StringVector;
26 
27  UIBaseDataSource (UIDescription* description, IActionPerformer* actionPerformer, IdStringPtr descriptionMessage, IGenericStringListDataBrowserSourceSelectionChanged* delegate = nullptr)
28  : GenericStringListDataBrowserSource (0, delegate) , description (description), actionPerformer (actionPerformer), descriptionMessage (descriptionMessage)
29  {
30  description->addDependency (this);
31  textInset.x = 4;
32  }
33 
34  ~UIBaseDataSource () override
35  {
36  description->removeDependency (this);
37  }
38 
39  void setSearchFieldControl (CSearchTextEdit* searchControl)
40  {
41  searchField = searchControl;
42  searchField->setListener (this);
43  }
44 
45  virtual bool add ()
46  {
47  if (dataBrowser && actionPerformer)
48  {
49  std::string newName (filterString.empty () ? "New" : filterString);
50  if (createUniqueName (newName))
51  {
52  addItem (newName.data ());
53  int32_t row = selectName (newName.data ());
54  if (row != -1)
55  {
56  dbOnMouseDown (CPoint (0, 0), CButtonState (kLButton|kDoubleClick), row, 0, dataBrowser);
57  return true;
58  }
59  }
60  }
61  return false;
62  }
63 
64  virtual bool remove ()
65  {
66  if (dataBrowser && actionPerformer)
67  {
68  int32_t selectedRow = dataBrowser->getSelectedRow ();
69  if (selectedRow != CDataBrowser::kNoSelection)
70  {
71  removeItem (names.at (static_cast<uint32_t> (selectedRow)).data ());
72  dbSelectionChanged (dataBrowser);
73  dataBrowser->setSelectedRow (selectedRow);
74  return true;
75  }
76  }
77  return false;
78  }
79 
80  virtual void setFilter (const UTF8String& filter)
81  {
82  if (filterString != filter)
83  {
84  filterString = filter;
85  int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow () : CDataBrowser::kNoSelection;
86  std::string selectedName;
87  if (selectedRow != CDataBrowser::kNoSelection)
88  selectedName = names.at (static_cast<uint32_t> (selectedRow));
89  update ();
90  if (selectedRow != CDataBrowser::kNoSelection)
91  selectName (selectedName.data ());
92  }
93  }
94 
95  virtual int32_t selectName (UTF8StringPtr name)
96  {
97  int32_t index = 0;
98  for (auto& it : names)
99  {
100  if (it == name)
101  {
102  dataBrowser->setSelectedRow (index, true);
103  if (delegate)
104  delegate->dbSelectionChanged (index, this);
105  return index;
106  }
107  ++index;
108  }
109  return -1;
110  }
111 protected:
112  virtual void getNames (std::list<const std::string*>& names) = 0;
113  virtual bool addItem (UTF8StringPtr name) = 0;
114  virtual bool removeItem (UTF8StringPtr name) = 0;
115  virtual bool performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
116  virtual UTF8StringPtr getDefaultsName () = 0;
117 
118  virtual void update ()
119  {
120  if (textEditControl)
121  textEditControl->looseFocus ();
122  names.clear ();
123  std::list<const std::string*> tmpNames;
124  getNames (tmpNames);
125 
126  std::string filter = filterString.getString ();
127  std::transform (filter.begin (), filter.end (), filter.begin (), ::tolower);
128 
129  for (auto& name : tmpNames)
130  {
131  if (!filter.empty ())
132  {
133  std::string tmp (*name);
134  std::transform (tmp.begin (), tmp.end (), tmp.begin (), ::tolower);
135  if (tmp.find (filter) == std::string::npos)
136  continue;
137  }
138  if (name->find ("~ ") == 0)
139  continue; // don't show static items
140  names.emplace_back (UTF8String (*name));
141  }
142  bool vsbIsVisible = false;
143  if (dataBrowser)
144  {
145  if (auto vsb = dataBrowser->getVerticalScrollbar ())
146  vsbIsVisible = vsb->isVisible ();
147  }
148  setStringList (&names);
149  if (dataBrowser)
150  {
151  if (auto vsb = dataBrowser->getVerticalScrollbar ())
152  {
153  if (vsb->isVisible() != vsbIsVisible)
154  dataBrowser->recalculateLayout ();
155  }
156  }
157  }
158 
159  CMessageResult notify (CBaseObject* sender, IdStringPtr message) override
160  {
161  if (message == descriptionMessage)
162  {
163  int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow () : CDataBrowser::kNoSelection;
164  std::string selectedName;
165  if (selectedRow != CDataBrowser::kNoSelection)
166  selectedName = names.at (static_cast<uint32_t> (selectedRow));
167  update ();
168  if (selectedRow != CDataBrowser::kNoSelection)
169  selectName (selectedName.data ());
170  return kMessageNotified;
171  }
172  else if (message == UIDescription::kMessageBeforeSave)
173  {
174  saveDefaults ();
175  return kMessageNotified;
176  }
177  return kMessageUnknown;
178  }
179 
180  virtual void saveDefaults ()
181  {
182  UTF8StringPtr name = getDefaultsName ();
183  if (name)
184  {
185  UIAttributes* attributes = description->getCustomAttributes (name, true);
186  if (attributes)
187  {
188  attributes->setAttribute ("FilterString", filterString.getString ());
189  if (dataBrowser)
190  {
191  int32_t selectedRow = dataBrowser->getSelectedRow ();
192  attributes->setIntegerAttribute ("SelectedRow", selectedRow);
193  }
194  }
195  }
196  }
197 
198  virtual void loadDefaults ()
199  {
200  UTF8StringPtr name = getDefaultsName ();
201  if (name)
202  {
203  UIAttributes* attributes = description->getCustomAttributes (name, true);
204  if (attributes)
205  {
206  const std::string* str = attributes->getAttributeValue ("FilterString");
207  if (str)
208  setFilter (str->data ());
209  if (dataBrowser)
210  {
211  int32_t selectedRow;
212  if (attributes->getIntegerAttribute("SelectedRow", selectedRow))
213  dataBrowser->setSelectedRow (selectedRow, true);
214  }
215  }
216  }
217  }
218 
219  void dbAttached (CDataBrowser* browser) override
220  {
222  update ();
223  loadDefaults ();
224  if (searchField)
225  searchField->setText (filterString);
226  }
227 
228  void dbRemoved (CDataBrowser* browser) override
229  {
230  saveDefaults ();
232  }
233 
234  void valueChanged (CControl* control) override
235  {
236  CTextEdit* edit = dynamic_cast<CTextEdit*>(control);
237  if (edit)
238  setFilter (edit->getText ());
239  }
240 
241  bool createUniqueName (std::string& name, int32_t count = 0)
242  {
243  std::stringstream str;
244  str << name;
245  if (count)
246  {
247  str << ' ';
248  str << count;
249  }
250  for (auto& it : names)
251  {
252  if (it == str.str ())
253  return createUniqueName (name, count+1);
254  }
255  name = str.str ();
256  return true;
257  }
258 
259  CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override
260  {
261  if (buttons.isLeftButton () && buttons.isDoubleClick ())
262  {
263  browser->beginTextEdit (CDataBrowser::Cell (row, column), names.at (static_cast<uint32_t> (row)).data ());
264  }
265  return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
266  }
267 
268  void dbCellTextChanged (int32_t _row, int32_t column, UTF8StringPtr newText, CDataBrowser* browser) override
269  {
270  textEditControl = nullptr;
271  if (_row < 0 || _row >= static_cast<int32_t> (names.size ()))
272  return;
273  auto row = static_cast<size_t> (_row);
274  for (auto& name : names)
275  {
276  if (name == newText)
277  return;
278  }
279  auto& currentName = names.at (row);
280  if (performNameChange (currentName.data (), newText))
281  {
282  if (selectName (newText) == -1 && row < names.size ())
283  selectName (names.at (row).data ());
284  }
285  }
286 
287  void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser) override
288  {
289  textEditControl = control;
290  textEditControl->setBackColor (kWhiteCColor);
291  textEditControl->setFontColor (fontColor);
292  textEditControl->setFont (drawFont);
293  textEditControl->setHoriAlign (textAlignment);
294  textEditControl->setTextInset (textInset);
295  }
296 
297  SharedPointer<UIDescription> description;
298  SharedPointer<CSearchTextEdit> searchField;
299  SharedPointer<CTextEdit> textEditControl;
300  IActionPerformer* actionPerformer;
301  IdStringPtr descriptionMessage;
302 
303  StringVector names;
304  UTF8String filterString;
305 };
306 
307 } // namespace
308 
309 #endif // VSTGUI_LIVE_EDITING
310 
311 #endif // __uibasedatasource__
void dbAttached(CDataBrowser *browser) override
databrowser view was attached to a parent
Definition: cdatabrowser.cpp:1146
void dbRemoved(CDataBrowser *browser) override
databrowser view will be removed from its parent
Definition: cdatabrowser.cpp:1152
Definition: customcontrols.cpp:8