GUIFramework 1.1.0
Framework for desktop GUI applications in C++.
Loading...
Searching...
No Matches
BaseComposite.cpp
Go to the documentation of this file.
1#include "BaseComposite.h"
2
4#include "GUIFramework.h"
5
8
9using namespace std;
10
11namespace gui_framework
12{
13 LRESULT BaseComposite::compositeWindowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool& isUsed)
14 {
15 if (message >= WM_CTLCOLOREDIT && message <= WM_CTLCOLORSTATIC)
16 {
17 BaseComponent* component = this->findChild(reinterpret_cast<HWND>(lparam));
18
19 if (component)
20 {
21 isUsed = true;
22
23 SetBkColor(reinterpret_cast<HDC>(wparam), component->getBackgroundColor());
24
25 SetTextColor(reinterpret_cast<HDC>(wparam), component->getTextColor());
26
27 return reinterpret_cast<LRESULT>(CreateSolidBrush(component->getBackgroundColor()));
28 }
29 }
30 else if (message == WM_MENUCOMMAND)
31 {
32 isUsed = true;
33
34 if (mainMenu->getHandle() == reinterpret_cast<HMENU>(lparam))
35 {
36 mainMenu->handleMessage(static_cast<uint32_t>(wparam));
37 }
38 else
39 {
40 popupMenus[reinterpret_cast<HMENU>(lparam)].handleMessage(static_cast<uint32_t>(wparam));
41 }
42
43 return 0;
44 }
45
46 isUsed = false;
47
48 return -1;
49 }
50
51 LRESULT BaseComposite::windowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool& isUsed)
52 {
53 LRESULT result = this->compositeWindowMessagesHandle(handle, message, wparam, lparam, isUsed);
54
55 if (isUsed)
56 {
57 return result;
58 }
59
60 result = BaseComponent::windowMessagesHandle(handle, message, wparam, lparam, isUsed);
61
62 if (isUsed)
63 {
64 return result;
65 }
66
67 for (const auto& i : children)
68 {
69 if (!i)
70 {
71 continue;
72 }
73
74 result = i->windowMessagesHandle(handle, message, wparam, lparam, isUsed);
75
76 if (isUsed)
77 {
78 return result;
79 }
80 }
81
82 isUsed = false;
83
84 return -1;
85 }
86
87 LRESULT BaseComposite::preWindowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool& isUsed)
88 {
89 isUsed = false;
90
91 if (message == WM_SIZE)
92 {
93 if (BaseComponent* component = dynamic_cast<BaseComposite*>(GUIFramework::get().findComponent(handle)))
94 {
95 interfaces::IResizableComponent* resizableComposite = dynamic_cast<interfaces::IResizableComponent*>(component);
96
97 if (resizableComposite && !resizableComposite->getBlockResize())
98 {
99 isUsed = true;
100
101 const vector<unique_ptr<BaseComponent>>& childrenToResize = static_cast<BaseComposite*>(component)->getChildren();
102 uint16_t width = LOWORD(lparam);
103 uint16_t height = HIWORD(lparam);
104
105 for (const auto& i : childrenToResize)
106 {
107 interfaces::IResizableComponent* resizable = dynamic_cast<interfaces::IResizableComponent*>(i.get());
108
109 if (resizable)
110 {
111 resizable->resize(width, height);
112 }
113 }
114
115 return 0;
116 }
117 }
118 }
119
120 return -1;
121 }
122
123 vector<pair<string, json::utility::jsonObject>> BaseComposite::getChildrenStructure() const
124 {
125 vector<json::JSONBuilder> childrenStructure;
126 vector<pair<string, json::utility::jsonObject>> data;
127
128 childrenStructure.reserve(children.size());
129
130 ranges::for_each(children, [&childrenStructure](const unique_ptr<BaseComponent>& child) { childrenStructure.push_back(child->getStructure()); });
131
132 for (size_t i = 0; i < children.size(); i++)
133 {
135
136 auto& childStructure = get<json::utility::jsonObject>(childrenStructure[i][childWindowName]);
137
138 data.push_back({ move(childWindowName), move(childStructure) });
139 }
140
141 return data;
142 }
143
144 void BaseComposite::addChild(BaseComponent* child)
145 {
146 children.push_back(unique_ptr<BaseComponent>(child));
147 }
148
149 void BaseComposite::setExitCode(int exitCode)
150 {
151 this->exitCode = exitCode;
152 }
153
154 BaseComposite::BaseComposite(const wstring& className, const wstring& windowName, const utility::ComponentSettings& settings, const interfaces::IStyles& styles, BaseComposite* parent, const string& windowFunctionName, const string& moduleName, uint16_t smallIconResource, uint16_t largeIconResource) :
156 (
157 className,
158 windowName,
159 settings,
160 styles,
161 parent,
162 windowFunctionName,
163 moduleName,
164 smallIconResource,
165 largeIconResource
166 ),
167 windowFunctionName(windowFunctionName),
168 mode(exitMode::destroyWindow),
169 onDestroy([]() {}),
170 exitCode(0)
171 {
172
173 }
174
176 {
177 for (auto it = children.begin(); it != children.end(); it++)
178 {
179 if (it->get() == child)
180 {
181 it->reset();
182
183 children.erase(it);
184
185 break;
186 }
187 }
188 }
189
190 void BaseComposite::removeComponents(const wstring& componentName)
191 {
192 erase_if(children, [&componentName](const unique_ptr<BaseComponent>& child) { return child->getWindowName() == componentName; });
193 }
194
195 BaseComponent* BaseComposite::findChild(const wstring& windowName) const
196 {
197 for (const unique_ptr<BaseComponent>& component : children)
198 {
199 if (component->getWindowName() == windowName)
200 {
201 return component.get();
202 }
203 else if (BaseComposite* composite = dynamic_cast<BaseComposite*>(component.get()))
204 {
205 if (BaseComponent* result = composite->findChild(windowName))
206 {
207 return result;
208 }
209 }
210 }
211
212 return nullptr;
213 }
214
216 {
217 for (const unique_ptr<BaseComponent>& component : children)
218 {
219 if (component->getHandle() == handle)
220 {
221 return component.get();
222 }
223 else if (BaseComposite* composite = dynamic_cast<BaseComposite*>(component.get()))
224 {
225 if (BaseComponent* result = composite->findChild(handle))
226 {
227 result;
228 }
229 }
230 }
231
232 return nullptr;
233 }
234
235 vector<BaseComponent*> BaseComposite::findChildren(const wstring& windowName) const
236 {
237 vector<BaseComponent*> result;
238
239 for (const unique_ptr<BaseComponent>& component : children)
240 {
241 if (component->getWindowName() == windowName)
242 {
243 result.push_back(component.get());
244 }
245 else if (BaseComposite* composite = dynamic_cast<BaseComposite*>(component.get()))
246 {
247 vector<BaseComponent*> subChildren = composite->findChildren(windowName);
248
249 ranges::copy(subChildren, back_inserter(result));
250 }
251 }
252
253 return result;
254 }
255
256 unique_ptr<Menu>& BaseComposite::createMainMenu(const wstring& menuName)
257 {
258 popupMenus.clear();
259
260 mainMenu = make_unique<Menu>(menuName, handle);
261
262 return mainMenu;
263 }
264
265 Menu& BaseComposite::addPopupMenu(const wstring& menuName)
266 {
267 Menu menu(menuName, nullptr);
268
269 auto it = popupMenus.emplace(menu.getHandle(), move(menu)).first;
270
271 return popupMenus.at(it->first);
272 }
273
274 void BaseComposite::removePopupMenus(const wstring& menuName)
275 {
276 vector<HMENU> itemsToRemove;
277
278 for (const auto& [handle, popupMenu] : popupMenus)
279 {
280 if (popupMenu.getName() == menuName)
281 {
282 itemsToRemove.push_back(handle);
283 }
284 }
285
286 for (const auto& i : itemsToRemove)
287 {
288 popupMenus.erase(i);
289 }
290 }
291
293 {
294 this->mode = mode;
295 }
296
297 void BaseComposite::setOnDestroy(const function<void()>& onDestroy)
298 {
299 this->onDestroy = onDestroy;
300
301 onDestroyFunctionName.clear();
303 }
304
305 void BaseComposite::setOnDestroy(const string& onDestroyFunctionName, const string& onDestroyFunctionModuleName)
306 {
307 GUIFramework& instance = GUIFramework::get();
308 const HMODULE& module = instance.getModules().at(onDestroyFunctionModuleName);
309
310 onDestroySignature tem = reinterpret_cast<onDestroySignature>(GetProcAddress(module, onDestroyFunctionName.data()));
311
312 if (!tem)
313 {
314 throw exceptions::CantFindFunctionFromModuleException(onDestroyFunctionName, onDestroyFunctionModuleName, __FILE__, __FUNCTION__, __LINE__);
315 }
316
317 onDestroy = tem;
318
319 this->onDestroyFunctionName = onDestroyFunctionName;
320 this->onDestroyFunctionModuleName = onDestroyFunctionModuleName;
321 }
322
327
329 {
330 return exitCode;
331 }
332
333 const vector<unique_ptr<BaseComponent>>& BaseComposite::getChildren() const
334 {
335 return children;
336 }
337
338 const unique_ptr<Menu>& BaseComposite::getMainMenu() const
339 {
340 return mainMenu;
341 }
342
343 unique_ptr<Menu>& BaseComposite::getMainMenu()
344 {
345 return mainMenu;
346 }
347
348 vector<const Menu*> BaseComposite::getPopupMenus() const
349 {
350 vector<const Menu*> result;
351
352 result.reserve(popupMenus.size());
353
354 for (const auto& [_, popupMenu] : popupMenus)
355 {
356 result.push_back(&popupMenu);
357 }
358
359 return result;
360 }
361
362 const function<void()>& BaseComposite::getOnDestroy() const
363 {
364 return onDestroy;
365 }
366
371
376
381
386
387 void BaseComposite::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue)
388 {
389 BaseComponent::setBackgroundColor(red, green, blue);
390
391 SetClassLongPtrW(handle, GCLP_HBRBACKGROUND, reinterpret_cast<LONG_PTR>(CreateSolidBrush(backgroundColor)));
392
393 InvalidateRect(handle, nullptr, true);
394 }
395
396 json::JSONBuilder BaseComposite::getStructure() const
397 {
398 using json::utility::jsonObject;
399
400 json::JSONBuilder builder = BaseComponent::getStructure();
401 vector<pair<string, jsonObject>> data = this->getChildrenStructure();
402 jsonObject& current = get<jsonObject>(builder[utility::to_string(windowName, ISerializable::getCodepage())]);
403 GUIFramework& instance = GUIFramework::get();
404
405 current.data.push_back({ "windowFunctionName"s, windowFunctionName });
406
407 current.data.push_back({ "exitMode"s, static_cast<int64_t>(mode) });
408
409 if (onDestroyFunctionName.size())
410 {
411 current.data.push_back({ "onDestroyFunctionName"s, onDestroyFunctionName });
412 current.data.push_back({ "onDestroyFunctionModuleName"s, onDestroyFunctionModuleName });
413 }
414
415 if (mainMenu)
416 {
417 jsonObject menuStructure;
418 json::JSONBuilder mainMenuBuilder = mainMenu->getStructure();
419 vector<jsonObject> popupItems;
420
421 menuStructure.data.push_back({ "mainMenuName"s, get<string>(mainMenuBuilder["menuName"]) });
422
423 menuStructure.data.push_back({ "mainMenuItems"s, move(mainMenuBuilder["items"]) });
424
425 for (const auto& [menuHandle, menu] : popupMenus)
426 {
427 jsonObject tem;
428 json::JSONBuilder temBuilder = menu.getStructure();
429
430 tem.data.push_back({ "menuName"s, get<string>(temBuilder["menuName"]) });
431 tem.data.push_back({ "menuId"s, get<uint64_t>(temBuilder["menuId"]) });
432 tem.data.push_back({ "items"s, move(temBuilder["items"]) });
433
434 json::utility::appendArray(move(tem), popupItems);
435 }
436
437 menuStructure.data.push_back({ "popupItems"s, move(popupItems) });
438
439 current.data.push_back(make_pair("menuStructure"s, move(menuStructure)));
440 }
441
442 if (data.size())
443 {
444 vector<jsonObject>& childrenStructures = get<vector<jsonObject>>(current.data.emplace_back(make_pair("children"s, vector<jsonObject>())).second);
445
446 for (auto& i : data)
447 {
448 jsonObject topLevel;
449 jsonObject tem;
450
451 tem.data.push_back(move(i));
452
453 topLevel.data.push_back({ ""s, move(tem) });
454
455 childrenStructures.push_back(move(topLevel));
456 }
457 }
458
459 if (!builder.contains("hotkeys", json::utility::variantTypeEnum::jJSONObject) && instance.getRegisteredHotkeys().size())
460 {
461 builder["hotkeys"] = move(instance.serializeHotkeys());
462 }
463
464 return builder;
465 }
466
468 {
469 vector<BaseComponent*> components;
470
471 ranges::for_each(children, [&components](const unique_ptr<BaseComponent>& component) { components.push_back(component.get()); });
472
473 ranges::for_each(components, [this](BaseComponent* component) { this->removeChild(component); });
474
476 }
477}
Base class for all windows, controls, etc.
std::wstring_view getWindowName() const
virtual LRESULT windowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool &isUsed)
virtual json::JSONBuilder getStructure() const override
const std::wstring windowName
COLORREF getBackgroundColor() const
virtual void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue)
Base class for all windows that has children windows.
std::unique_ptr< Menu > mainMenu
virtual json::JSONBuilder getStructure() const override
virtual iterators::composite_const_forward_iterator cbegin() const noexcept override
const std::unique_ptr< Menu > & getMainMenu() const
void setOnDestroy(const std::function< void()> &onDestroy)
virtual iterators::composite_forward_iterator end() noexcept override
virtual iterators::composite_forward_iterator begin() noexcept override
LRESULT windowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool &isUsed) override
BaseComponent * findChild(const std::wstring &windowName) const
std::string onDestroyFunctionModuleName
virtual LRESULT compositeWindowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool &isUsed)
std::unordered_map< HMENU, Menu > popupMenus
virtual void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) override
void setExitMode(exitMode mode)
virtual std::unique_ptr< Menu > & createMainMenu(const std::wstring &menuName)
It needs to be called once.
std::vector< std::unique_ptr< BaseComponent > > children
void removeComponents(const std::wstring &componentName)
virtual LRESULT preWindowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool &isUsed) override
virtual iterators::composite_const_forward_iterator cend() const noexcept override
virtual Menu & addPopupMenu(const std::wstring &menuName)
Don't call move operator with return value.
virtual void removePopupMenus(const std::wstring &menuName)
Remove all pop-up menus with menuName.
void removeChild(BaseComponent *child)
std::vector< const Menu * > getPopupMenus() const
const std::vector< std::unique_ptr< BaseComponent > > & getChildren() const
const std::function< void()> & getOnDestroy() const
std::vector< BaseComponent * > findChildren(const std::wstring &windowName) const
std::function< void()> onDestroy
Singleton with GUIFramework settings and some functionality.
std::vector< json::utility::jsonObject > serializeHotkeys()
Serialize hotkeys.
std::vector< hotkeyData > getRegisteredHotkeys()
Thread safe get hotkeys.
static GUIFramework & get()
Singleton instance access.
Menu class.
Definition Menu.h:9
HMENU getHandle() const
Definition Menu.cpp:102
Provides resize, setBlockResize, getBlockResize methods.
virtual void resize(uint16_t width, uint16_t height)
Resize component.
Provides styles for other classes.
Definition IStyles.h:11
IBaseConstForwardIterator implementation for BaseComponent.
IBaseForwardIterator implementation for BaseComponent.
constexpr uint32_t deinitTopLevelWindowPointer
Set to nullptr topLevelWindow for recreating window with same window class name.
string to_string(wstring_view stringToConvert, uint32_t codepage)
Definition Utility.cpp:41
void(*)() onDestroySignature
Default on destroy signature. Called before window is destroyed.