27#include "freertos/FreeRTOS.h"
28#include "freertos/timers.h"
39#include "images/bitmaps.h"
43#pragma GCC optimize ("O2")
56void dumpEvent(uiEvent * event)
59 static const char * TOSTR[] = {
"UIEVT_NULL",
"UIEVT_DEBUGMSG",
"UIEVT_APPINIT",
"UIEVT_GENPAINTEVENTS",
"UIEVT_PAINT",
"UIEVT_ACTIVATE",
60 "UIEVT_DEACTIVATE",
"UIEVT_MOUSEMOVE",
"UIEVT_MOUSEWHEEL",
"UIEVT_MOUSEBUTTONDOWN",
61 "UIEVT_MOUSEBUTTONUP",
"UIEVT_SETPOS",
"UIEVT_SETSIZE",
"UIEVT_RESHAPEWINDOW",
62 "UIEVT_MOUSEENTER",
"UIEVT_MOUSELEAVE",
"UIEVT_MAXIMIZE",
"UIEVT_MINIMIZE",
"UIEVT_RESTORE",
63 "UIEVT_SHOW",
"UIEVT_HIDE",
"UIEVT_SETFOCUS",
"UIEVT_KILLFOCUS",
"UIEVT_KEYDOWN",
"UIEVT_KEYUP",
"UIEVT_KEYTYPE",
64 "UIEVT_TIMER",
"UIEVT_CLICK",
"UIEVT_DBLCLICK",
"UIEVT_EXITMODAL",
"UIEVT_DESTROY",
"UIEVT_CLOSE",
65 "UIEVT_QUIT",
"UIEVT_CREATE",
"UIEVT_CHILDSETFOCUS",
"UIEVT_CHILDKILLFOCUS"
67 printf(
"#%d ", idx++);
68 printf(TOSTR[event->id]);
69 if (event->dest && event->dest->objectType().uiFrame && ((
uiFrame*)(event->dest))->title())
70 printf(
" dst=\"%s\"(%p) ", ((
uiFrame*)(event->dest))->title(), event->dest);
72 printf(
" dst=%p ", event->dest);
74 auto ot =
event->dest->objectType();
76 if (ot.uiApp) printf(
"uiApp ");
77 if (ot.uiEvtHandler) printf(
"uiEvtHandler ");
78 if (ot.uiWindow) printf(
"uiWindow ");
79 if (ot.uiFrame) printf(
"uiFrame ");
80 if (ot.uiControl) printf(
"uiControl ");
81 if (ot.uiScrollableControl) printf(
"uiScrollableControl ");
82 if (ot.uiButton) printf(
"uiButton ");
83 if (ot.uiTextEdit) printf(
"uiTextEdit ");
84 if (ot.uiLabel) printf(
"uiLabel ");
85 if (ot.uiImage) printf(
"uiImage ");
86 if (ot.uiPanel) printf(
"uiPanel ");
87 if (ot.uiPaintBox) printf(
"uiPaintBox ");
88 if (ot.uiCustomListBox) printf(
"uiCustomListBox ");
89 if (ot.uiListBox) printf(
"uiListBox ");
90 if (ot.uiFileBrowser) printf(
"uiFileBrowser ");
91 if (ot.uiComboBox) printf(
"uiComboBox ");
92 if (ot.uiCheckBox) printf(
"uiCheckBox ");
93 if (ot.uiSlider) printf(
"uiSlider ");
94 if (ot.uiColorListBox) printf(
"uiColorListBox ");
95 if (ot.uiCustomComboBox) printf(
"uiCustomComboBox ");
96 if (ot.uiColorBox) printf(
"uiColorBox ");
97 if (ot.uiColorComboBox) printf(
"uiColorComboBox ");
98 if (ot.uiProgressBar) printf(
"uiProgressBar ");
99 if (ot.uiSplitButton) printf(
"uiSplitButton ");
100 if (ot.uiSimpleMenu) printf(
"uiSimpleMenu ");
105 printf(event->params.debugMsg);
107 case UIEVT_MOUSEMOVE:
108 printf(
"X=%d Y=%d", event->params.mouse.status.X, event->params.mouse.status.Y);
110 case UIEVT_MOUSEWHEEL:
111 printf(
"delta=%d", event->params.mouse.status.wheelDelta);
113 case UIEVT_MOUSEBUTTONDOWN:
114 case UIEVT_MOUSEBUTTONUP:
116 printf(
"btn=%d", event->params.mouse.changedButton);
119 case UIEVT_GENPAINTEVENTS:
120 case UIEVT_RESHAPEWINDOW:
121 printf(
"rect=%d,%d,%d,%d", event->params.rect.X1, event->params.rect.Y1, event->params.rect.X2, event->params.rect.Y2);
124 printf(
"pos=%d,%d", event->params.pos.X, event->params.pos.Y);
127 printf(
"size=%d,%d", event->params.size.width, event->params.size.height);
132 #ifdef FABGLIB_HAS_VirtualKeyO_STRING
133 printf(
"VK=%s ", Keyboard::virtualKeyToString(event->params.key.VK));
134 if (event->params.key.LALT) printf(
" +LALT");
135 if (event->params.key.RALT) printf(
" +RALT");
136 if (event->params.key.CTRL) printf(
" +CTRL");
137 if (event->params.key.SHIFT) printf(
" +SHIFT");
138 if (event->params.key.GUI) printf(
" +GUI");
142 printf(
"handle=%p", event->params.timerHandle);
176uiEvtHandler::uiEvtHandler(
uiApp * app)
179 objectType().uiEvtHandler =
true;
183uiEvtHandler::~uiEvtHandler()
186 m_app->killEvtHandlerTimers(
this);
190void uiEvtHandler::processEvent(uiEvent * event)
211 : uiEvtHandler(nullptr),
212 m_rootWindow(nullptr),
213 m_activeWindow(nullptr),
214 m_focusedWindow(nullptr),
215 m_lastFocusedWindow(nullptr),
216 m_capturedMouseWindow(nullptr),
217 m_freeMouseWindow(nullptr),
218 m_modalWindow(nullptr),
219 m_combineMouseMoveEvents(false),
220 m_keyDownHandler(nullptr),
221 m_caretWindow(nullptr),
222 m_caretTimer(nullptr),
223 m_caretInvertState(-1),
224 m_lastMouseUpTimeMS(0),
227 objectType().uiApp =
true;
239 m_displayController = displayController;
240 m_displayColors = displayController->
colorsCount();
242 m_canvas =
new Canvas(m_displayController);
244 m_keyboard = keyboard;
246 if (PS2Controller::initialized()) {
248 if (m_keyboard ==
nullptr)
250 if (m_mouse ==
nullptr)
254 m_eventsQueue = xQueueCreate(FABGLIB_UI_EVENTS_QUEUE_SIZE,
sizeof(uiEvent));
266 m_rootWindow->setApp(
this);
267 m_rootWindow->setCanvas(m_canvas);
282 m_lastUserActionTimeMS = esp_timer_get_time() / 1000;
286 m_activeWindow = m_rootWindow;
289 uiEvent evt = uiEvent(
this, UIEVT_APPINIT);
297 if (getEvent(&event, -1)) {
299 preprocessEvent(&event);
307 event.dest->processEvent(&event);
309 if (event.id == UIEVT_QUIT) {
310 exitCode =
event.params.exitCode;
316 killEvtHandlerTimers(
this);
328 m_rootWindow =
nullptr;
336 vQueueDelete(m_eventsQueue);
337 m_eventsQueue =
nullptr;
345void uiApp::asyncRunTask(
void * arg)
349 if (
app->m_asyncRunWait)
350 xSemaphoreGive(
app->m_asyncRunWait);
357 m_displayController = displayController;
358 m_keyboard = keyboard;
360 m_asyncRunWait =
nullptr;
362 if (CoreUsage::busiestCore() == -1)
363 xTaskCreate(&asyncRunTask,
"", taskStack,
this, 5,
nullptr);
365 xTaskCreatePinnedToCore(&asyncRunTask,
"", taskStack,
this, 5,
nullptr, CoreUsage::quietCore());
373 m_asyncRunWait = xSemaphoreCreateBinary();
374 xSemaphoreTake(m_asyncRunWait, portMAX_DELAY);
375 vSemaphoreDelete(m_asyncRunWait);
376 m_asyncRunWait =
nullptr;
383 while (getEvent(&event, 0)) {
385 preprocessEvent(&event);
388 printf(
"processEvents(): ");
393 event.dest->processEvent(&event);
400 for (
auto child = m_rootWindow->
lastChild(); child; child = child->
prev())
402 uiEvent evt = uiEvent(
nullptr, UIEVT_QUIT);
403 evt.params.exitCode = exitCode;
408void uiApp::preprocessEvent(uiEvent * event)
410 if (event->dest ==
nullptr) {
413 case UIEVT_MOUSEMOVE:
414 case UIEVT_MOUSEWHEEL:
415 case UIEVT_MOUSEBUTTONDOWN:
416 case UIEVT_MOUSEBUTTONUP:
417 preprocessMouseEvent(event);
421 preprocessKeyboardEvent(event);
430 if (event->params.timerHandle == m_caretTimer) {
432 event->dest =
nullptr;
442 if (m_modalWindow !=
nullptr)
443 filterModalEvent(event);
448void uiApp::filterModalEvent(uiEvent * event)
450 if (event->dest !=
nullptr &&
451 event->dest->objectType().uiWindow &&
452 event->dest != m_modalWindow &&
453 event->dest != m_activeWindow &&
454 event->dest != m_focusedWindow &&
455 !m_modalWindow->isChild((uiWindow*)event->dest)) {
457 case UIEVT_MOUSEMOVE:
458 case UIEVT_MOUSEWHEEL:
459 case UIEVT_MOUSEBUTTONDOWN:
460 case UIEVT_MOUSEBUTTONUP:
461 case UIEVT_MOUSEENTER:
464 event->dest =
nullptr;
465 if (event->id == UIEVT_MOUSEENTER) {
480void uiApp::preprocessMouseEvent(uiEvent * event)
483 if (m_combineMouseMoveEvents && event->id == UIEVT_MOUSEMOVE) {
485 while (peekEvent(&nextEvent, 0) && nextEvent.id == UIEVT_MOUSEMOVE)
489 m_lastUserActionTimeMS = esp_timer_get_time() / 1000;
491 Point mousePos = Point(event->params.mouse.status.X, event->params.mouse.status.Y);
495 uiWindow * oldFreeMouseWindow = m_freeMouseWindow;
496 Point winMousePos = mousePos;
497 if (m_capturedMouseWindow) {
499 for (uiWindow * cur = m_capturedMouseWindow; cur != m_rootWindow; cur = cur->
parent())
500 winMousePos = winMousePos.sub(cur->pos());
501 event->dest = m_capturedMouseWindow;
503 if (event->id == UIEVT_MOUSEBUTTONUP && event->params.mouse.changedButton == 1) {
507 uiEvent evt = uiEvent(m_capturedMouseWindow, UIEVT_MOUSELEAVE);
509 m_freeMouseWindow = oldFreeMouseWindow =
nullptr;
511 captureMouse(
nullptr);
515 event->dest = m_freeMouseWindow;
517 event->params.mouse.status.X = winMousePos.X;
518 event->params.mouse.status.Y = winMousePos.Y;
521 if (oldFreeMouseWindow != m_freeMouseWindow) {
522 if (m_freeMouseWindow) {
523 uiEvent evt = uiEvent(m_freeMouseWindow, UIEVT_MOUSEENTER);
526 if (oldFreeMouseWindow) {
527 uiEvent evt = uiEvent(oldFreeMouseWindow, UIEVT_MOUSELEAVE);
533 if (event->id == UIEVT_MOUSEBUTTONUP && event->params.mouse.changedButton == 1) {
534 int curTime = esp_timer_get_time() / 1000;
535 if (m_lastMouseUpPos == mousePos && curTime - m_lastMouseUpTimeMS <= m_appProps.
doubleClickTime) {
537 uiEvent evt = *event;
538 evt.id = UIEVT_DBLCLICK;
541 m_lastMouseUpTimeMS = curTime;
542 m_lastMouseUpPos = mousePos;
547void uiApp::preprocessKeyboardEvent(uiEvent * event)
549 m_lastUserActionTimeMS = esp_timer_get_time() / 1000;
552 if (m_focusedWindow) {
553 event->dest = m_focusedWindow;
556 if (m_focusedWindow != m_activeWindow) {
557 uiEvent evt = *event;
558 evt.dest = m_activeWindow;
562 if (event->id == UIEVT_KEYDOWN)
563 m_keyDownHandler =
event->dest;
564 else if (event->id == UIEVT_KEYUP && m_keyDownHandler == event->dest) {
565 uiEvent evt = uiEvent(event->dest, UIEVT_KEYTYPE);
566 evt.params.key =
event->params.key;
573void uiApp::captureMouse(uiWindow * window)
575 m_capturedMouseWindow = window;
576 if (m_capturedMouseWindow)
590 for (; child; child = child->
prev()) {
593 point = point.sub(child->
pos());
597 if (child ==
nullptr)
611 return xQueueSendToBack(m_eventsQueue, event, 0) == pdTRUE;
617 return xQueueSendToFront(m_eventsQueue, event, 0) == pdTRUE;
621void uiApp::postDebugMsg(
char const * msg)
623 uiEvent evt = uiEvent(
nullptr, UIEVT_DEBUGMSG);
624 evt.params.debugMsg = msg;
629bool uiApp::getEvent(uiEvent * event,
int timeOutMS)
631 return xQueueReceive(m_eventsQueue, event, msToTicks(timeOutMS)) == pdTRUE;
635bool uiApp::peekEvent(uiEvent * event,
int timeOutMS)
637 return xQueuePeek(m_eventsQueue, event, msToTicks(timeOutMS)) == pdTRUE;
641void uiApp::processEvent(uiEvent * event)
643 uiEvtHandler::processEvent(event);
652 onTimer(event->params.timerHandle);
667 if (value != m_activeWindow) {
669 while (value && !value->m_windowProps.activable) {
670 value = value->m_parent;
674 if (value == m_activeWindow)
683 m_activeWindow = value;
687 uiEvent evt = uiEvent(prev, UIEVT_DEACTIVATE);
691 if (m_activeWindow) {
693 uiEvent evt = uiEvent(m_activeWindow, UIEVT_ACTIVATE);
709 if (value && !value->isFocusable())
712 if (m_focusedWindow != value) {
718 m_lastFocusedWindow = prev;
720 uiEvent evt = uiEvent(prev, UIEVT_KILLFOCUS);
721 evt.params.focusInfo.oldFocused = m_lastFocusedWindow;
722 evt.params.focusInfo.newFocused = value;
726 evt = uiEvent(prev->
parent(), UIEVT_CHILDKILLFOCUS);
727 evt.params.focusInfo.oldFocused = m_lastFocusedWindow;
728 evt.params.focusInfo.newFocused = value;
733 m_focusedWindow = value;
738 if (m_focusedWindow) {
739 uiEvent evt = uiEvent(m_focusedWindow, UIEVT_SETFOCUS);
740 evt.params.focusInfo.oldFocused = m_lastFocusedWindow;
741 evt.params.focusInfo.newFocused = m_focusedWindow;
743 if (m_focusedWindow->
parent()) {
745 evt = uiEvent(m_focusedWindow->
parent(), UIEVT_CHILDSETFOCUS);
746 evt.params.focusInfo.oldFocused = m_lastFocusedWindow;
747 evt.params.focusInfo.newFocused = m_focusedWindow;
764 int startingIndex = m_focusedWindow ? m_focusedWindow->
focusIndex() + delta : 0;
766 int newIndex = startingIndex;
769 uiWindow * newFocusedCtrl = parent->findChildWithFocusIndex(newIndex, &maxIndex);
770 if (maxIndex == -1) {
771 return m_focusedWindow;
773 if (newFocusedCtrl) {
775 return newFocusedCtrl;
778 newIndex = (newIndex >= maxIndex ? 0 : newIndex + delta);
780 newIndex = (newIndex <= 0 ? maxIndex : newIndex + delta);
781 }
while (newIndex != startingIndex);
783 return m_focusedWindow;
795 uiEvent evt = uiEvent(m_rootWindow, UIEVT_GENPAINTEVENTS);
796 evt.params.rect = rect;
823 uiEvent evt = uiEvent(window, UIEVT_RESHAPEWINDOW);
824 evt.params.rect = rect;
831 window->m_state.
visible = value;
832 uiEvent evt = uiEvent(window, value ? UIEVT_SHOW : UIEVT_HIDE);
841 auto state =
new ModalWindowState;
842 state->window = window;
843 state->modalResult = -1;
846 state->prevModal = m_modalWindow;
859 while (getEvent(&event, timeout)) {
861 if (m_modalWindow != state->window && event.dest == state->window) {
863 m_modalWindow = state->window;
866 preprocessEvent(&event);
869 printf(
"processModalWindowEvents(): ");
873 if (event.id == UIEVT_EXITMODAL && event.dest == state->window) {
875 state->modalResult =
event.params.modalResult;
877 }
else if (event.id == UIEVT_CLOSE) {
883 event.dest->processEvent(&event);
893 m_modalWindow = state->prevModal;
897 int result = state->modalResult;
914 uiEvent evt = uiEvent(frame, value ? UIEVT_MAXIMIZE : UIEVT_RESTORE);
921 uiEvent evt = uiEvent(frame, value ? UIEVT_MINIMIZE : UIEVT_RESTORE);
926void uiApp::timerFunc(TimerHandle_t xTimer)
929 uiEvent evt = uiEvent(dest, UIEVT_TIMER);
930 evt.params.timerHandle = xTimer;
938 TimerHandle_t h = xTimerCreate(
"", pdMS_TO_TICKS(periodMS), pdTRUE, dest, &uiApp::timerFunc);
939 m_timers.push_back(uiTimerAssoc(dest, h));
948 m_timers.remove(uiTimerAssoc(dest, handle));
949 xTimerStop(handle, portMAX_DELAY);
950 xTimerDelete(handle, portMAX_DELAY);
956 for (
auto t : m_timers)
957 if (t.first == dest) {
958 xTimerStop(t.second, portMAX_DELAY);
959 xTimerDelete(t.second, portMAX_DELAY);
961 m_timers.remove_if([&](uiTimerAssoc
const & p) {
return p.first == dest; });
967void uiApp::showCaret(uiWindow * window)
969 if (m_caretWindow != window) {
970 if (window && window == m_focusedWindow) {
972 m_caretWindow = window;
974 m_caretInvertState = 0;
976 }
else if (m_caretTimer) {
980 m_caretTimer =
nullptr;
981 m_caretWindow = NULL;
987void uiApp::suspendCaret(
bool value)
991 if (m_caretInvertState != -1) {
992 xTimerStop(m_caretTimer, 0);
994 m_caretInvertState = -1;
997 if (m_caretInvertState == -1) {
998 xTimerStart(m_caretTimer, 0);
999 m_caretInvertState = 0;
1008void uiApp::setCaret(
bool value)
1014void uiApp::setCaret(Point
const & pos)
1016 setCaret(m_caretRect.move(pos));
1020void uiApp::setCaret(Rect
const & rect)
1028void uiApp::blinkCaret(
bool forceOFF)
1030 if (m_caretWindow && m_caretInvertState != -1 && (forceOFF ==
false || m_caretInvertState == 1)) {
1034 Rect aRect = m_caretWindow->
transformRect(m_caretRect, m_rootWindow);
1036 m_caretInvertState = m_caretInvertState ? 0 : 1;
1046 for (
auto child = window->
lastChild(); child; child = child->
prev())
1049 if (m_caretWindow == window)
1051 if (m_focusedWindow == window)
1053 if (m_activeWindow == window)
1058 uiEvent evt = uiEvent(window, UIEVT_DESTROY);
1064void uiApp::cleanWindowReferences(
uiWindow * window)
1066 if (m_capturedMouseWindow == window)
1067 m_capturedMouseWindow =
nullptr;
1068 if (m_freeMouseWindow == window)
1069 m_freeMouseWindow =
nullptr;
1070 if (m_activeWindow == window)
1071 m_activeWindow =
nullptr;
1072 if (m_focusedWindow == window)
1073 m_focusedWindow =
nullptr;
1074 if (m_modalWindow == window)
1075 m_modalWindow =
nullptr;
1076 if (m_caretWindow == window)
1077 m_caretWindow =
nullptr;
1083 auto font = &FONT_std_14;
1084 const int titleHeight = title && strlen(title) ? font->height : 0;
1085 const int textExtent = m_canvas->
textExtent(font, text);
1086 const int button1Extent = button1Text ? m_canvas->
textExtent(font, button1Text) + 10 : 0;
1087 const int button2Extent = button2Text ? m_canvas->
textExtent(font, button2Text) + 10 : 0;
1088 const int button3Extent = button3Text ? m_canvas->
textExtent(font, button3Text) + 10 : 0;
1089 const int buttonsWidth = imax(imax(imax(button1Extent, button2Extent), button3Extent), 40);
1097 const int buttonsHeight = font->height + 6;
1102 const int bitmapWidth = bitmap ? bitmap->width : 0;
1103 const int bitmapHeight = bitmap ? bitmap->height : 0;
1104 constexpr int buttonsSpace = 10;
1105 const int bitmapSpace = bitmap ? 8 : 0;
1106 const int textHeight = imax(font->height, bitmapHeight);
1107 const int requiredWidth = imin(imax(bitmapWidth + bitmapSpace + textExtent + 10, buttonsWidth * totButtons + (2 + buttonsSpace) * totButtons), m_canvas->
getWidth());
1108 const int requiredHeight = textHeight + buttonsHeight + titleHeight + font->height * 3;
1109 const int frameX = (m_canvas->
getWidth() - requiredWidth) / 2;
1110 const int frameY = (m_canvas->
getHeight() - requiredHeight) / 2;
1112 auto mainFrame =
new uiFrame(m_rootWindow, title,
Point(frameX, frameY),
Size(requiredWidth, requiredHeight),
false);
1113 mainFrame->frameProps().resizeable =
false;
1114 mainFrame->frameProps().hasMaximizeButton =
false;
1115 mainFrame->frameProps().hasMinimizeButton =
false;
1117 int x = (requiredWidth - bitmapWidth - bitmapSpace - textExtent) / 2;
1119 int y = font->height + titleHeight + (textHeight - bitmapHeight) / 2;
1121 x += bitmapWidth + bitmapSpace;
1124 int y = font->height + titleHeight + (textHeight - font->height) / 2;
1129 y += textHeight + titleHeight;
1130 auto panel =
new uiPanel(mainFrame,
Point(0, y),
Size(mainFrame->size().width, mainFrame->size().height - y));
1131 panel->windowStyle().borderColor =
RGB888(128, 128, 128);
1132 panel->panelStyle().backgroundColor = mainFrame->frameStyle().backgroundColor;
1136 y = (panel->size().height - buttonsHeight) / 2;
1137 x = mainFrame->windowStyle().borderSize + requiredWidth - buttonsWidth * totButtons - buttonsSpace * totButtons;
1139 auto button1 = button1Text ?
new uiButton(panel, button1Text,
Point(x, y),
Size(buttonsWidth, buttonsHeight)) :
nullptr;
1141 button1->onClick = [&]() { mainFrame->exitModal(1); };
1142 x += buttonsWidth + buttonsSpace;
1145 auto button2 = button2Text ?
new uiButton(panel, button2Text,
Point(x, y),
Size(buttonsWidth, buttonsHeight)) :
nullptr;
1147 button2->onClick = [&]() { mainFrame->exitModal(2); };
1148 x += buttonsWidth + buttonsSpace;
1151 auto button3 = button3Text ?
new uiButton(panel, button3Text,
Point(x, y),
Size(buttonsWidth, buttonsHeight)) :
nullptr;
1153 button3->onClick = [&]() { mainFrame->exitModal(3); };
1154 x += buttonsWidth + buttonsSpace;
1158 mainFrame->onShow = [&]() {
1167 switch (modalResult) {
1182 auto font = &FONT_std_14;
1183 const int titleHeight = title && strlen(title) ? font->height : 0;
1184 const int textExtent = m_canvas->
textExtent(font, text);
1185 const int editExtent = imin(maxLength * m_canvas->
textExtent(font,
"M"), m_rootWindow->
clientSize().
width / 2 - textExtent);
1186 const int button1Extent = button1Text ? m_canvas->
textExtent(font, button1Text) + 10 : 0;
1187 const int button2Extent = button2Text ? m_canvas->
textExtent(font, button2Text) + 10 : 0;
1188 const int buttonsWidth = imax(imax(button1Extent, button2Extent), 40);
1194 const int buttonsHeight = font->height + 6;
1195 const int textHeight = font->height;
1196 constexpr int buttonsSpace = 10;
1197 const int requiredWidth = imin(imax(editExtent + textExtent + 10, buttonsWidth * totButtons + (2 + buttonsSpace) * totButtons), m_canvas->
getWidth());
1198 const int requiredHeight = textHeight + buttonsHeight + titleHeight + font->height * 3;
1199 const int frameX = (m_canvas->
getWidth() - requiredWidth) / 2;
1200 const int frameY = (m_canvas->
getHeight() - requiredHeight) / 2;
1202 auto mainFrame =
new uiFrame(m_rootWindow, title,
Point(frameX, frameY),
Size(requiredWidth, requiredHeight),
false);
1203 mainFrame->frameProps().resizeable =
false;
1204 mainFrame->frameProps().hasMaximizeButton =
false;
1205 mainFrame->frameProps().hasMinimizeButton =
false;
1208 mainFrame->exitModal(1);
1210 mainFrame->exitModal(0);
1214 int y = font->height + titleHeight + (textHeight - font->height) / 2;
1217 auto edit =
new uiTextEdit(mainFrame, inOutString,
Point(x + textExtent + 5, y - 4),
Size(editExtent - 15, textHeight + 6));
1221 y += textHeight + titleHeight;
1222 auto panel =
new uiPanel(mainFrame,
Point(0, y),
Size(mainFrame->size().width, mainFrame->size().height - y));
1223 panel->windowStyle().borderColor =
RGB888(128, 128, 128);
1224 panel->panelStyle().backgroundColor = mainFrame->frameStyle().backgroundColor;
1228 y = (panel->size().height - buttonsHeight) / 2;
1229 x = mainFrame->windowStyle().borderSize + requiredWidth - buttonsWidth * totButtons - buttonsSpace * totButtons;
1231 auto button1 = button1Text ?
new uiButton(panel, button1Text,
Point(x, y),
Size(buttonsWidth, buttonsHeight)) :
nullptr;
1233 button1->onClick = [&]() { mainFrame->exitModal(1); };
1234 x += buttonsWidth + buttonsSpace;
1237 auto button2 = button2Text ?
new uiButton(panel, button2Text,
Point(x, y),
Size(buttonsWidth, buttonsHeight)) :
nullptr;
1239 button2->onClick = [&]() { mainFrame->exitModal(2); };
1240 x += buttonsWidth + buttonsSpace;
1244 mainFrame->onShow = [&]() {
1253 switch (modalResult) {
1256 int len = imin(maxLength, strlen(edit->text()));
1257 memcpy(inOutString, edit->text(), len);
1258 inOutString[len] = 0;
1269uiMessageBoxResult uiApp::fileDialog(
char const * title,
char * inOutDirectory,
int maxDirNameSize,
char * inOutFilename,
int maxFileNameSize,
char const * buttonOKText,
char const * buttonCancelText,
int frameWidth,
int frameHeight)
1271 auto mainFrame =
new uiFrame(m_rootWindow, title, UIWINDOW_PARENTCENTER,
Size(frameWidth, frameHeight),
false);
1272 mainFrame->frameProps().resizeable =
false;
1273 mainFrame->frameProps().hasMaximizeButton =
false;
1274 mainFrame->frameProps().hasMinimizeButton =
false;
1277 mainFrame->exitModal(1);
1279 mainFrame->exitModal(0);
1283 constexpr int x = 8;
1284 constexpr int hh = 20;
1285 constexpr int dy = hh + 8;
1286 constexpr int lbloy = 3;
1288 constexpr int fnBorder = 20;
1289 new uiLabel(mainFrame,
"Filename",
Point(x + fnBorder, y + lbloy));
1290 auto filenameEdit =
new uiTextEdit(mainFrame, inOutFilename,
Point(x + 50 + fnBorder, y),
Size(frameWidth - x - 58 - fnBorder * 2, hh));
1294 auto browser =
new uiFileBrowser(mainFrame,
Point(x, y),
Size(frameWidth - x * 2, frameHeight - y - 35));
1295 browser->setDirectory(inOutDirectory);
1296 browser->onChange = [&]() {
1297 if (!browser->isDirectory()) {
1298 filenameEdit->setText(browser->filename());
1299 filenameEdit->repaint();
1302 browser->onDblClick = [&]() {
1303 if (!browser->isDirectory())
1304 mainFrame->exitModal(1);
1307 y += browser->clientSize().height + (dy - hh);
1312 auto buttonCancel =
new uiButton(mainFrame, buttonCancelText,
Point(frameWidth - buttonCancelLen - buttonOKLen - 20, y),
Size(buttonCancelLen, hh));
1313 auto buttonOK =
new uiButton(mainFrame, buttonOKText,
Point(frameWidth - buttonOKLen - 8, y),
Size(buttonOKLen, hh));
1315 buttonCancel->onClick = [&]() { mainFrame->exitModal(0); };
1316 buttonOK->onClick = [&]() { mainFrame->exitModal(1); };
1319 mainFrame->onShow = [&]() {
1326 switch (modalResult) {
1329 int len = imin(maxDirNameSize, strlen(browser->directory()));
1330 memcpy(inOutDirectory, browser->directory(), len);
1331 inOutDirectory[len] = 0;
1333 len = imin(maxFileNameSize, strlen(filenameEdit->text()));
1334 memcpy(inOutFilename, filenameEdit->text(), len);
1335 inOutFilename[len] = 0;
1379 m_isMouseOver(false),
1380 m_styleClassID(styleClassID),
1383 m_firstChild(nullptr),
1384 m_lastChild(nullptr),
1385 m_parentProcessKbdEvents(false)
1393 m_windowStyle.adaptToDisplayColors(
app()->displayColors());
1394 m_canvas =
app()->canvas();
1399 if (m_pos == UIWINDOW_PARENTCENTER) {
1403 m_pos =
Point(0, 0);
1410 if (visible &&
app())
1414 m_focusIndex = pframe ? ((
uiFrame*)pframe)->getNextFreeFocusIndex() : 0;
1417 uiEvent evt = uiEvent(
this, UIEVT_CREATE);
1423uiWindow::~uiWindow()
1429void uiWindow::freeChildren()
1435 m_firstChild = m_lastChild =
nullptr;
1439void uiWindow::addChild(uiWindow * child)
1443 m_lastChild->m_next = child;
1444 child->m_prev = m_lastChild;
1445 m_lastChild = child;
1448 m_firstChild = m_lastChild = child;
1455void uiWindow::insertAfter(uiWindow * child, uiWindow * underlyingChild)
1462 child->m_prev = underlyingChild;
1463 if (underlyingChild) {
1465 child->m_next = underlyingChild->m_next;
1467 child->m_next->m_prev = child;
1468 underlyingChild->m_next = child;
1469 if (m_lastChild == underlyingChild)
1470 m_lastChild = child;
1473 m_firstChild->m_prev = child;
1474 child->m_next = m_firstChild;
1475 m_firstChild = child;
1480void uiWindow::removeChild(uiWindow * child,
bool freeChild)
1483 if (child == m_firstChild)
1484 m_firstChild = child->m_next;
1486 child->m_prev->m_next = child->m_next;
1488 if (child == m_lastChild)
1489 m_lastChild = child->m_prev;
1491 child->m_next->m_prev = child->m_prev;
1495 app()->cleanWindowReferences(child);
1497 child->m_prev = child->m_next =
nullptr;
1504void uiWindow::moveChildOnTop(uiWindow * child)
1506 removeChild(child,
false);
1513void uiWindow::moveAfter(uiWindow * child, uiWindow * underlyingChild)
1515 removeChild(child,
false);
1516 insertAfter(child, underlyingChild);
1522 parent()->moveChildOnTop(
this);
1528 parent()->moveAfter(
this, insertionPoint);
1533bool uiWindow::isChild(
uiWindow * window)
1536 if (child == window || (child->hasChildren() && child->isChild(window)))
1546 for (
uiWindow * win =
this; win != baseWindow; win = win->m_parent)
1547 r = r.translate(win->m_pos);
1584 return rect(origin).shrink(bSize);
1600void uiWindow::beginPaint(uiEvent * paintEvent,
Rect const & clippingRect)
1604 canvas()->
setClippingRect( clippingRect.intersection(paintEvent->params.rect) );
1610void uiWindow::processEvent(uiEvent * event)
1612 uiEvtHandler::processEvent(event);
1614 switch (event->id) {
1617 m_parent->removeChild(
this);
1625 case UIEVT_ACTIVATE:
1630 for (
uiWindow * child =
this; child->parent() !=
nullptr; child = child->parent()) {
1631 if (child != child->parent()->lastChild()) {
1632 child->parent()->moveChildOnTop(child);
1633 winToRepaint = child;
1636 winToRepaint->repaint();
1640 case UIEVT_DEACTIVATE:
1645 case UIEVT_MOUSEBUTTONDOWN:
1646 if (event->params.mouse.changedButton == 1) {
1653 app()->captureMouse(
this);
1657 case UIEVT_MOUSEBUTTONUP:
1659 if (event->params.mouse.changedButton == 1) {
1661 if (
rect(
uiOrigin::Window).contains(event->params.mouse.status.X, event->params.mouse.status.Y)) {
1662 uiEvent evt = *event;
1663 evt.id = UIEVT_CLICK;
1677 case UIEVT_RESHAPEWINDOW:
1678 reshape(event->params.rect);
1681 case UIEVT_GENPAINTEVENTS:
1682 generatePaintEvents(event->params.rect);
1685 case UIEVT_MOUSEENTER:
1686 m_isMouseOver =
true;
1690 case UIEVT_MOUSELEAVE:
1691 m_isMouseOver =
false;
1695 if (m_parentProcessKbdEvents)
1696 m_parent->processEvent(event);
1700 if (m_parentProcessKbdEvents)
1701 m_parent->processEvent(event);
1709 case UIEVT_SETFOCUS:
1710 case UIEVT_KILLFOCUS:
1720void uiWindow::paintWindow()
1726 for (
int i = 0; i < bSize; ++i)
1733void uiWindow::generatePaintEvents(Rect
const & paintRect)
1735 app()->setCaret(
false);
1737 rects.push(paintRect);
1738 while (!rects.isEmpty()) {
1739 Rect thisRect = rects.pop();
1740 bool noIntesections =
true;
1743 if (win->state().visible && thisRect.intersects(winRect)) {
1744 noIntesections =
false;
1745 removeRectangle(rects, thisRect, winRect);
1746 Rect newRect = thisRect.intersection(winRect).translate(-win->pos().X, -win->pos().Y);
1747 win->generatePaintEvents(newRect);
1751 if (noIntesections) {
1752 uiEvent evt = uiEvent(
nullptr, UIEVT_PAINT);
1754 evt.params.rect = thisRect;
1765void uiWindow::reshape(Rect
const & r)
1773 if (oldRect == newRect)
1777 m_pos = Point(r.X1, r.Y1);
1780 if (!oldRect.intersects(newRect)) {
1785 removeRectangle(rects, oldRect, newRect);
1786 while (!rects.isEmpty())
1791 uiEvent evt = uiEvent(
this, UIEVT_SETPOS);
1792 evt.params.pos =
pos();
1796 evt = uiEvent(
this, UIEVT_SETSIZE);
1797 evt.params.size =
size();
1801 int dx = newRect.width() - oldRect.width();
1802 int dy = newRect.height() - oldRect.height();
1803 if (dx != 0 || dy != 0) {
1806 Rect newChildRect = childRect;
1808 if (!child->m_anchors.left && !child->m_anchors.right) {
1810 int ofs = dx > 0 ? imax(1, dx / 2) : imin(-1, dx / 2);
1811 newChildRect.X1 += ofs;
1812 newChildRect.X2 += ofs;
1813 }
else if (!child->m_anchors.left)
1814 newChildRect.X1 += dx;
1815 if (child->m_anchors.right)
1816 newChildRect.X2 += dx;
1819 if (!child->m_anchors.top && !child->m_anchors.bottom) {
1821 int ofs = dy > 0 ? imax(1, dy / 2) : imin(-1, dy / 2);
1822 newChildRect.Y1 += ofs;
1823 newChildRect.Y2 += ofs;
1824 }
else if (!child->m_anchors.top)
1825 newChildRect.Y1 += dy;
1826 if (child->m_anchors.bottom)
1827 newChildRect.Y2 += dy;
1829 if (newChildRect != childRect) {
1830 uiEvent evt = uiEvent(child, UIEVT_RESHAPEWINDOW);
1831 evt.params.rect = newChildRect;
1843 uiEvent evt = uiEvent(
this, UIEVT_EXITMODAL);
1844 evt.params.modalResult = modalResult;
1861bool uiWindow::isFocusable()
1868uiWindow * uiWindow::findChildWithFocusIndex(
int focusIndex,
int * maxIndex)
1870 for (
auto child = m_firstChild; child; child = child->m_next) {
1871 if (child->isFocusable()) {
1872 *maxIndex = imax(*maxIndex, child->m_focusIndex);
1877 if (child->hasChildren()) {
1878 auto r = child->findChildWithFocusIndex(
focusIndex, maxIndex);
1891 while (ret && ret->
objectType().uiFrame == 0)
1907 :
uiWindow(parent, pos, size, visible, 0),
1910 m_mouseDownFrameItem(uiFrameItem::None),
1911 m_mouseMoveFrameItem(uiFrameItem::None),
1912 m_lastReshapingBox(
Rect(0, 0, 0, 0)),
1913 m_nextFreeFocusIndex(0),
1914 m_mouseDownPos(
Point(-1, -1))
1922 m_frameStyle.adaptToDisplayColors(
app()->displayColors());
1939 m_titleLength = strlen(value);
1940 m_title = (
char*) realloc(m_title, m_titleLength + 1);
1941 strcpy(m_title, value);
1953 va_start(ap, format);
1954 int size = vsnprintf(
nullptr, 0, format, ap) + 1;
1957 va_start(ap, format);
1959 vsnprintf(buf,
size, format, ap);
1966int uiFrame::titleBarHeight()
1968 return m_frameStyle.
titleFont->height + 3;
1972Rect uiFrame::titleBarRect()
1975 r.Y2 = r.Y1 + titleBarHeight() - 1;
1985 if (m_titleLength > 0)
1986 r.
Y1 += titleBarHeight();
1992Size uiFrame::minWindowSize()
1996 r.
width += CORNERSENSE * 2;
1997 r.
height += CORNERSENSE * 2;
2001 if (m_titleLength > 0) {
2002 int barHeight = titleBarHeight();
2005 r.
width += barHeight * 3;
2006 r.
width += barHeight * 4;
2016Rect uiFrame::getBtnRect(
int buttonIndex)
2018 int btnSize = titleBarHeight();
2019 Rect barRect = titleBarRect();
2020 Rect btnRect = Rect(barRect.X2 - btnSize - CORNERSENSE / 2, barRect.Y1,
2021 barRect.X2 - CORNERSENSE / 2, barRect.Y2);
2022 while (buttonIndex--)
2023 btnRect = btnRect.translate(-btnSize, 0);
2028void uiFrame::paintFrame()
2032 if (m_titleLength > 0) {
2033 int barHeight = titleBarHeight();
2039 int btnX = paintButtons(bkgRect);
2045 bkgRect.Y1 += barHeight;
2056int uiFrame::paintButtons(Rect
const & bkgRect)
2058 int buttonsX = bkgRect.X2;
2061 Rect r = getBtnRect(0);
2063 if (m_mouseMoveFrameItem == uiFrameItem::CloseButton) {
2070 canvas()->
drawLine(r.X1, r.Y1, r.X2, r.Y2);
2071 canvas()->
drawLine(r.X2, r.Y1, r.X1, r.Y2);
2075 Rect r = getBtnRect(1);
2077 if (m_mouseMoveFrameItem == uiFrameItem::MaximizeButton) {
2086 r = r.shrink(1).translate(-1, +1);
2088 r = r.translate(+2, -2);
2089 canvas()->
moveTo(r.X1, r.Y1 + 2);
2090 canvas()->
lineTo(r.X1, r.Y1);
2091 canvas()->
lineTo(r.X2, r.Y1);
2092 canvas()->
lineTo(r.X2, r.Y2);
2093 canvas()->
lineTo(r.X2 - 2, r.Y2);
2099 Rect r = getBtnRect(2);
2101 if (m_mouseMoveFrameItem == uiFrameItem::MinimizeButton) {
2108 int h = (r.Y2 - r.Y1 + 1) / 2;
2109 canvas()->
drawLine(r.X1, r.Y1 + h, r.X2, r.Y1 + h);
2115void uiFrame::processEvent(uiEvent * event)
2117 uiWindow::processEvent(event);
2119 switch (event->id) {
2127 case UIEVT_MOUSEBUTTONDOWN:
2128 if (event->params.mouse.changedButton == 1) {
2129 m_mouseDownPos = Point(event->params.mouse.status.X, event->params.mouse.status.Y);
2130 m_mouseDownFrameItem = getFrameItemAt(event->params.mouse.status.X, event->params.mouse.status.Y);
2131 m_sizeAtMouseDown =
size();
2132 app()->combineMouseMoveEvents(
true);
2136 case UIEVT_MOUSEBUTTONUP:
2137 if (event->params.mouse.changedButton == 1) {
2138 int mouseX =
event->params.mouse.status.X;
2139 int mouseY =
event->params.mouse.status.Y;
2142 movingCapturedMouse(mouseX, mouseY,
false);
2145 movingFreeMouse(mouseX, mouseY);
2148 handleButtonsClick(mouseX, mouseY,
false);
2150 app()->combineMouseMoveEvents(
false);
2154 case UIEVT_MOUSEMOVE:
2155 if (
app()->capturedMouseWindow() ==
this)
2156 movingCapturedMouse(event->params.mouse.status.X, event->params.mouse.status.Y,
true);
2158 movingFreeMouse(event->params.mouse.status.X, event->params.mouse.status.Y);
2161 case UIEVT_MOUSELEAVE:
2162 if (m_mouseMoveFrameItem == uiFrameItem::CloseButton)
2164 if (m_mouseMoveFrameItem == uiFrameItem::MaximizeButton)
2166 if (m_mouseMoveFrameItem == uiFrameItem::MinimizeButton)
2168 m_mouseMoveFrameItem = uiFrameItem::None;
2171 case UIEVT_DBLCLICK:
2172 handleButtonsClick(event->params.mouse.status.X, event->params.mouse.status.Y,
true);
2183 case UIEVT_MAXIMIZE:
2191 case UIEVT_MINIMIZE:
2210 onTimer(event->params.timerHandle);
2215 if (event->params.key.VK ==
VK_TAB) {
2216 if (event->params.key.SHIFT)
2234uiFrameItem uiFrame::getFrameItemAt(
int x,
int y)
2236 Point p = Point(x, y);
2238 if (m_titleLength > 0) {
2240 return uiFrameItem::CloseButton;
2243 return uiFrameItem::MaximizeButton;
2246 return uiFrameItem::MinimizeButton;
2255 if (Rect(CORNERSENSE, 0, w - CORNERSENSE,
windowStyle().borderSize).contains(p))
2256 return uiFrameItem::TopCenterResize;
2259 if (Rect(0, CORNERSENSE,
windowStyle().borderSize, h - CORNERSENSE).contains(p))
2260 return uiFrameItem::CenterLeftResize;
2263 if (Rect(w -
windowStyle().borderSize, CORNERSENSE, w - 1, h - CORNERSENSE).contains(p))
2264 return uiFrameItem::CenterRightResize;
2267 if (Rect(CORNERSENSE, h -
windowStyle().borderSize, w - CORNERSENSE, h - 1).contains(p))
2268 return uiFrameItem::BottomCenterResize;
2271 if (Rect(0, 0, CORNERSENSE, CORNERSENSE).contains(p))
2272 return uiFrameItem::TopLeftResize;
2275 if (Rect(w - CORNERSENSE, 0, w - 1, CORNERSENSE).contains(p))
2276 return uiFrameItem::TopRightResize;
2279 if (Rect(0, h - CORNERSENSE, CORNERSENSE, h - 1).contains(p))
2280 return uiFrameItem::BottomLeftResize;
2283 if (Rect(w - CORNERSENSE, h - CORNERSENSE, w - 1, h - 1).contains(p))
2284 return uiFrameItem::BottomRightResize;
2289 if (m_titleLength > 0 && m_frameProps.
moveable && !m_frameState.
maximized && titleBarRect().contains(p))
2290 return uiFrameItem::MoveArea;
2292 return uiFrameItem::None;
2296void uiFrame::movingCapturedMouse(
int mouseX,
int mouseY,
bool mouseIsDown)
2298 int dx = mouseX - m_mouseDownPos.
X;
2299 int dy = mouseY - m_mouseDownPos.
Y;
2301 Size minSize = minWindowSize();
2305 switch (m_mouseDownFrameItem) {
2307 case uiFrameItem::MoveArea:
2308 newRect = newRect.move(
pos().
X + dx,
pos().
Y + dy);
2311 case uiFrameItem::CenterRightResize:
2312 newRect = newRect.resize(imax(m_sizeAtMouseDown.
width + dx, minSize.width), newRect.height());
2315 case uiFrameItem::CenterLeftResize:
2318 r.X1 =
pos().
X + dx;
2319 newRect.X1 = r.X1 - imax(0, minSize.width - r.size().width);
2323 case uiFrameItem::TopLeftResize:
2326 r.X1 =
pos().
X + dx;
2327 newRect.X1 = r.X1 - imax(0, minSize.width - r.size().width);
2328 r.Y1 =
pos().
Y + dy;
2329 newRect.Y1 = r.Y1 - imax(0, minSize.height - r.size().height);
2333 case uiFrameItem::TopCenterResize:
2336 r.Y1 =
pos().
Y + dy;
2337 newRect.Y1 = r.Y1 - imax(0, minSize.height - r.size().height);
2341 case uiFrameItem::TopRightResize:
2344 r.X2 =
pos().
X + m_sizeAtMouseDown.
width + dx;
2345 newRect.X2 = r.X2 + imax(0, minSize.width - r.size().width);
2346 r.Y1 =
pos().
Y + dy;
2347 newRect.Y1 = r.Y1 - imax(0, minSize.height - r.size().height);
2351 case uiFrameItem::BottomLeftResize:
2354 r.X1 =
pos().
X + dx;
2355 newRect.X1 = r.X1 - imax(0, minSize.width - r.size().width);
2356 r.Y2 =
pos().
Y + m_sizeAtMouseDown.
height + dy;
2357 newRect.Y2 = r.Y2 + imax(0, minSize.height - r.size().height);
2361 case uiFrameItem::BottomCenterResize:
2362 newRect = newRect.resize(newRect.width(), imax(m_sizeAtMouseDown.
height + dy, minSize.height));
2365 case uiFrameItem::BottomRightResize:
2366 newRect = newRect.resize(imax(m_sizeAtMouseDown.
width + dx, minSize.width), imax(m_sizeAtMouseDown.
height + dy, minSize.height));
2374 if (mouseIsDown ==
false || (
app()->appProps().realtimeReshaping && m_mouseDownFrameItem != uiFrameItem::MoveArea) || (
app()->appProps().realtimeMoving && m_mouseDownFrameItem == uiFrameItem::MoveArea)) {
2375 m_lastReshapingBox = Rect();
2378 drawReshapingBox(newRect);
2382void uiFrame::drawReshapingBox(Rect boxRect)
2390 if (m_lastReshapingBox != Rect()) {
2392 if (m_titleLength > 0)
2393 canvas()->
drawLine(m_lastReshapingBox.
X1, m_lastReshapingBox.
Y1 + clientOffsetY, m_lastReshapingBox.
X2, m_lastReshapingBox.
Y1 + clientOffsetY);
2395 if (boxRect != Rect()) {
2397 if (m_titleLength > 0)
2398 canvas()->
drawLine(boxRect.X1, boxRect.Y1 + clientOffsetY, boxRect.X2, boxRect.Y1 + clientOffsetY);
2401 m_lastReshapingBox = boxRect;
2405void uiFrame::movingFreeMouse(
int mouseX,
int mouseY)
2407 uiFrameItem prevSensPos = m_mouseMoveFrameItem;
2409 m_mouseMoveFrameItem = getFrameItemAt(mouseX, mouseY);
2411 if ((m_mouseMoveFrameItem == uiFrameItem::CloseButton || prevSensPos == uiFrameItem::CloseButton) && m_mouseMoveFrameItem != prevSensPos)
2414 if ((m_mouseMoveFrameItem == uiFrameItem::MaximizeButton || prevSensPos == uiFrameItem::MaximizeButton) && m_mouseMoveFrameItem != prevSensPos)
2417 if ((m_mouseMoveFrameItem == uiFrameItem::MinimizeButton || prevSensPos == uiFrameItem::MinimizeButton) && m_mouseMoveFrameItem != prevSensPos)
2422 switch (m_mouseMoveFrameItem) {
2424 case uiFrameItem::TopLeftResize:
2428 case uiFrameItem::TopCenterResize:
2432 case uiFrameItem::TopRightResize:
2436 case uiFrameItem::CenterLeftResize:
2440 case uiFrameItem::CenterRightResize:
2444 case uiFrameItem::BottomLeftResize:
2448 case uiFrameItem::BottomCenterResize:
2452 case uiFrameItem::BottomRightResize:
2464void uiFrame::handleButtonsClick(
int x,
int y,
bool doubleClick)
2466 if (m_titleLength > 0) {
2467 if (m_frameProps.
hasCloseButton && getBtnRect(0).contains(x, y) && getBtnRect(0).contains(m_mouseDownPos)) {
2469 uiEvent evt = uiEvent(
this, UIEVT_CLOSE);
2471 }
else if (m_frameProps.
hasMaximizeButton && ((getBtnRect(1).contains(x, y) && getBtnRect(1).contains(m_mouseDownPos)) ||
2472 (doubleClick && titleBarRect().contains(x, y)))) {
2477 }
else if (m_frameProps.
hasMinimizeButton && !m_frameState.
minimized && getBtnRect(2).contains(x, y) && getBtnRect(2).contains(m_mouseDownPos)) {
2482 m_mouseMoveFrameItem = uiFrameItem::None;
2497 :
uiWindow(parent, pos, size, visible, 0)
2507uiControl::~uiControl()
2512void uiControl::processEvent(uiEvent * event)
2514 uiWindow::processEvent(event);
2529 :
uiControl(parent, pos, size, visible, 0),
2544 m_buttonStyle.adaptToDisplayColors(
app()->displayColors());
2553uiButton::~uiButton()
2561 int len = strlen(value);
2562 m_text = (
char*) realloc(m_text, len + 1);
2563 strcpy(m_text, value);
2569void uiButton::paintButton()
2574 if (
app()->capturedMouseWindow() ==
this)
2581 paintContent(bkgRect);
2585void uiButton::paintContent(Rect
const & rect)
2587 Bitmap
const * bitmap = m_down ? m_buttonStyle.
downBitmap : m_buttonStyle.
bitmap;
2588 int textHeight = m_buttonStyle.
textFont->height;
2589 int bitmapWidth = bitmap ? bitmap->width : 0;
2590 int bitmapHeight = bitmap ? bitmap->height : 0;
2593 int x =
rect.
X1 + (
rect.size().
width - m_textExtent - bitmapTextSpace - bitmapWidth) / 2;
2594 int y =
rect.
Y1 + (
rect.size().
height - imax(textHeight, bitmapHeight)) / 2;
2598 x += bitmapWidth + bitmapTextSpace;
2599 y += (imax(textHeight, bitmapHeight) - textHeight) / 2;
2612void uiButton::processEvent(uiEvent * event)
2614 uiControl::processEvent(event);
2616 switch (event->id) {
2628 case UIEVT_MOUSEENTER:
2632 case UIEVT_MOUSEBUTTONDOWN:
2633 if (event->params.mouse.changedButton == 1)
2638 case UIEVT_MOUSEBUTTONUP:
2642 case UIEVT_MOUSELEAVE:
2660void uiButton::trigger()
2672 if (value != m_down) {
2691 :
uiControl(parent, pos, size, visible, 0),
2709 m_textEditStyle.adaptToDisplayColors(
app()->displayColors());
2718uiTextEdit::~uiTextEdit()
2727 m_textLength = strlen(value);
2728 checkAllocatedSpace(m_textLength);
2729 strcpy(m_text, value);
2731 m_text = strdup(
"");
2740 va_start(ap, format);
2741 int size = vsnprintf(
nullptr, 0, format, ap) + 1;
2744 va_start(ap, format);
2745 checkAllocatedSpace(
size + 1);
2746 vsnprintf(m_text,
size, format, ap);
2747 m_textLength = strlen(m_text);
2753void uiTextEdit::processEvent(uiEvent * event)
2755 uiControl::processEvent(event);
2757 switch (event->id) {
2763 app()->setCaret(
true);
2766 case UIEVT_MOUSEBUTTONDOWN:
2767 if (event->params.mouse.changedButton == 1) {
2768 int col = getColFromMouseX(event->params.mouse.status.X);
2769 moveCursor(col, col);
2774 case UIEVT_MOUSEBUTTONUP:
2777 case UIEVT_MOUSEENTER:
2781 case UIEVT_MOUSELEAVE:
2785 case UIEVT_MOUSEMOVE:
2787 if (
app()->capturedMouseWindow() ==
this)
2788 moveCursor(getColFromMouseX(event->params.mouse.status.X), m_selCursorCol);
2791 case UIEVT_SETFOCUS:
2794 app()->showCaret(
this);
2799 case UIEVT_KILLFOCUS:
2801 app()->showCaret(NULL);
2807 handleKeyDown(event->params.key);
2814 case UIEVT_DBLCLICK:
2815 selectWordAt(event->params.mouse.status.X);
2827 if (m_codepage ==
nullptr || m_codepage->codepage != m_textEditStyle.
textFont->codepage)
2828 m_codepage = CodePages::get(m_textEditStyle.
textFont->codepage);
2830 VirtualKeyItem item = { };
2832 item.CTRL = key.
CTRL;
2833 item.SHIFT = key.
SHIFT;
2834 return virtualKeyToASCII(item, m_codepage);
2844 if (m_cursorCol != m_selCursorCol)
2846 else if (m_cursorCol > 0) {
2848 moveCursor(m_cursorCol - 1, m_cursorCol - 1);
2864 auto ASCII = keyToASCII(key);
2866 if (ASCII >= 0x20 && ASCII != 0x7F) {
2867 if (m_cursorCol != m_selCursorCol)
2885 int newCurCol = key.
CTRL ? getWordPosAtLeft() : m_cursorCol - 1;
2886 moveCursor(newCurCol, (key.
SHIFT ? m_selCursorCol : newCurCol));
2897 int newCurCol = key.
CTRL ? getWordPosAtRight() : m_cursorCol + 1;
2898 moveCursor(newCurCol, (key.
SHIFT ? m_selCursorCol : newCurCol));
2906 moveCursor(0, (key.
SHIFT ? m_selCursorCol : 0));
2913 moveCursor(m_textLength, (key.
SHIFT ? m_selCursorCol : m_textLength));
2923 moveCursor(m_textLength, 0);
2935Rect uiTextEdit::getEditRect()
2941void uiTextEdit::paintTextEdit()
2943 m_contentRect = getEditRect();
2955uint8_t
const * uiTextEdit::getCharInfo(
char ch,
int *
width)
2959 uint8_t
const * chptr;
2960 if (m_textEditStyle.
textFont->chptr) {
2962 chptr = m_textEditStyle.
textFont->data + m_textEditStyle.
textFont->chptr[(int)(ch)];
2966 chptr = m_textEditStyle.
textFont->data + ch;
2973void uiTextEdit::paintContent()
2975 m_contentRect = m_contentRect.shrink(2);
2976 canvas()->
setClippingRect(canvas()->getClippingRect().intersection(m_contentRect));
2979 GlyphOptions glyphOpt = GlyphOptions().FillBackground(
false).DoubleWidth(0).Bold(
false).Italic(
false).Underline(
false).Invert(0);
2980 if (m_selCursorCol != m_cursorCol)
2981 glyphOpt.FillBackground(
true);
2984 for (
int x = m_contentRect.
X1 + m_viewX, y = m_contentRect.
Y1, col = 0, fontWidth; m_text[col]; ++col, x += fontWidth) {
2985 uint8_t
const * chptr = getCharInfo(m_text[col], &fontWidth);
2986 if (m_selCursorCol != m_cursorCol && (col == m_selCursorCol || col == m_cursorCol)) {
2987 glyphOpt.invert = !glyphOpt.invert;
2990 if (x >= m_contentRect.
X1 && x <= m_contentRect.
X2)
2991 canvas()->
drawGlyph(x, y, fontWidth, m_textEditStyle.
textFont->height, chptr, 0);
2999int uiTextEdit::charColumnToWindowX(
int col)
3001 int x = m_contentRect.
X1 + m_viewX;
3002 for (
int curcol = 0, fontWidth; m_text[curcol]; ++curcol, x += fontWidth) {
3003 getCharInfo(m_text[curcol], &fontWidth);
3012void uiTextEdit::updateCaret()
3015 int x = charColumnToWindowX(m_cursorCol);
3016 app()->setCaret(Rect(x, m_contentRect.
Y1, x, m_contentRect.
Y1 + m_textEditStyle.
textFont->height));
3025void uiTextEdit::moveCursor(
int col,
int selCol)
3027 col = iclamp(col, 0, m_textLength);
3028 selCol = iclamp(selCol, 0, m_textLength);
3030 if (col == m_cursorCol && selCol == m_selCursorCol)
3033 bool doRepaint =
false;
3036 if (m_cursorCol != m_selCursorCol && col == selCol)
3040 m_selCursorCol = selCol;
3042 if (m_cursorCol != m_selCursorCol)
3046 int x = charColumnToWindowX(m_cursorCol);
3048 int prevCharWidth = 0;
3050 getCharInfo(m_text[col - 1], &prevCharWidth);
3053 getCharInfo(m_text[col < m_textLength ? col : col - 1], &charWidth);
3055 if (x - prevCharWidth < m_contentRect.
X1) {
3057 m_viewX += m_contentRect.
X1 - (x - prevCharWidth);
3059 }
else if (x + charWidth > m_contentRect.
X2) {
3061 m_viewX -= (x + charWidth - m_contentRect.
X2);
3073int uiTextEdit::getColFromMouseX(
int mouseX)
3076 for (
int x = m_contentRect.
X1 + m_viewX, fontWidth; m_text[col]; ++col, x += fontWidth) {
3077 getCharInfo(m_text[col], &fontWidth);
3078 if (mouseX < x || (mouseX >= x && mouseX < x + fontWidth))
3086void uiTextEdit::checkAllocatedSpace(
int requiredLength)
3089 if (m_textSpace < requiredLength) {
3090 if (m_textSpace == 0) {
3092 m_textSpace = requiredLength;
3095 while (m_textSpace < requiredLength)
3098 m_text = (
char*) realloc(m_text, m_textSpace);
3104void uiTextEdit::insert(
char c)
3107 checkAllocatedSpace(m_textLength);
3108 memmove(m_text + m_cursorCol + 1, m_text + m_cursorCol, m_textLength - m_cursorCol);
3109 m_text[m_cursorCol] = c;
3110 moveCursor(m_cursorCol + 1, m_cursorCol + 1);
3117void uiTextEdit::removeSel()
3119 if (m_textLength > 0) {
3120 if (m_cursorCol > m_selCursorCol)
3121 iswap(m_cursorCol, m_selCursorCol);
3122 int count = imax(1, m_selCursorCol - m_cursorCol);
3123 if (m_cursorCol < m_textLength) {
3124 memmove(m_text + m_cursorCol, m_text + m_cursorCol + count, m_textLength - m_cursorCol - count + 1);
3125 m_textLength -= count;
3126 moveCursor(m_cursorCol, m_cursorCol);
3135int uiTextEdit::getWordPosAtLeft()
3137 int col = m_cursorCol - 1;
3138 while (col > 0 && (!isspace(m_text[col - 1]) || isspace(m_text[col])))
3140 return imax(0, col);
3145int uiTextEdit::getWordPosAtRight()
3147 int col = m_cursorCol + 1;
3148 while (col < m_textLength && (!isspace(m_text[col - 1]) || isspace(m_text[col])))
3150 return imin(m_textLength, col);
3156void uiTextEdit::selectWordAt(
int mouseX)
3158 int col = getColFromMouseX(mouseX), left = col, right = col;
3159 bool lspc = isspace(m_text[col]);
3160 while (left > 0 && (
bool)isspace(m_text[left - 1]) == lspc)
3162 while (right < m_textLength && (
bool)isspace(m_text[right]) == lspc)
3164 moveCursor(left, right);
3180 :
uiControl(parent, pos, size, visible, 0),
3190 m_labelStyle.adaptToDisplayColors(
app()->displayColors());
3209 int len = strlen(value);
3210 m_text = (
char*) realloc(m_text, len + 1);
3211 strcpy(m_text, value);
3219 va_start(ap, format);
3220 int size = vsnprintf(
nullptr, 0, format, ap) + 1;
3223 va_start(ap, format);
3224 m_text = (
char*) realloc(m_text,
size + 1);
3225 vsnprintf(m_text,
size, format, ap);
3241void uiLabel::paintLabel()
3262 int y = r.
Y1 + (r.height() - m_labelStyle.
textFont->height) / 2;
3267void uiLabel::processEvent(uiEvent * event)
3269 uiControl::processEvent(event);
3271 switch (event->id) {
3300 :
uiControl(parent, pos, size, visible, 0),
3309 m_imageStyle.adaptToDisplayColors(
app()->displayColors());
3329 if (m_autoSize &&
bitmap)
3334void uiImage::paintImage()
3340 int x = r.
X1 + (r.
X2 + 1 - m_bitmap->
width) / 2;
3341 int y = r.
Y1 + (r.
Y2 + 1 - m_bitmap->
height) / 2;
3347void uiImage::processEvent(uiEvent * event)
3349 uiControl::processEvent(event);
3351 switch (event->id) {
3374 :
uiControl(parent, pos, size, visible, 0)
3383 m_panelStyle.adaptToDisplayColors(
app()->displayColors());
3395void uiPanel::paintPanel()
3404void uiPanel::processEvent(uiEvent * event)
3406 uiControl::processEvent(event);
3408 switch (event->id) {
3440 m_paintBoxStyle.adaptToDisplayColors(
app()->displayColors());
3447uiPaintBox::~uiPaintBox()
3452void uiPaintBox::paintPaintBox()
3464void uiPaintBox::processEvent(uiEvent * event)
3466 uiScrollableControl::processEvent(event);
3468 switch (event->id) {
3491 :
uiControl(parent, pos, size, visible, 0),
3505uiColorBox::~uiColorBox()
3517void uiColorBox::paintColorBox()
3526void uiColorBox::processEvent(uiEvent * event)
3528 uiControl::processEvent(event);
3530 switch (event->id) {
3553 :
uiControl(parent, pos, size, visible, 0),
3554 m_HScrollBarPosition(0),
3555 m_HScrollBarVisible(0),
3556 m_HScrollBarRange(0),
3557 m_VScrollBarPosition(0),
3558 m_VScrollBarVisible(0),
3559 m_VScrollBarRange(0),
3560 m_mouseOverItem(uiScrollBarItem::None),
3561 m_scrollTimer(nullptr),
3562 m_mouseDownPos(
Point(-1, -1))
3567 m_scrollableControlStyle.adaptToDisplayColors(
app()->displayColors());
3574uiScrollableControl::~uiScrollableControl()
3586 position = iclamp(position, 0, range - visible);
3587 switch (orientation) {
3590 bool changedPos = (m_VScrollBarPosition != position);
3591 if (m_VScrollBarVisible != visible || m_VScrollBarRange != range || changedPos) {
3592 m_VScrollBarVisible = visible;
3593 m_VScrollBarRange = range;
3594 m_VScrollBarPosition = position;
3595 if (repaintScrollbar)
3596 repaintScrollBar(orientation);
3604 bool changedPos = (m_HScrollBarPosition != position);
3605 if (m_HScrollBarVisible != visible || m_HScrollBarRange != range || changedPos) {
3606 m_HScrollBarVisible = visible;
3607 m_HScrollBarRange = range;
3608 m_HScrollBarPosition = position;
3609 if (repaintScrollbar)
3610 repaintScrollBar(orientation);
3620void uiScrollableControl::repaintScrollBar(
uiOrientation orientation)
3626void uiScrollableControl::processEvent(uiEvent * event)
3628 uiControl::processEvent(event);
3630 switch (event->id) {
3634 paintScrollableControl();
3637 case UIEVT_MOUSEBUTTONDOWN:
3638 if (event->params.mouse.changedButton == 1) {
3639 m_mouseDownPos = Point(event->params.mouse.status.X, event->params.mouse.status.Y);
3640 m_mouseDownHScrollBarPosition = m_HScrollBarPosition;
3641 m_mouseDownVScrollBarPosition = m_VScrollBarPosition;
3642 if (m_mouseOverItem == uiScrollBarItem::LeftButton || m_mouseOverItem == uiScrollBarItem::RightButton ||
3643 m_mouseOverItem == uiScrollBarItem::TopButton || m_mouseOverItem == uiScrollBarItem::BottomButton) {
3646 handleButtonsScroll();
3650 app()->combineMouseMoveEvents(
true);
3654 case UIEVT_MOUSEBUTTONUP:
3655 if (event->params.mouse.changedButton == 1) {
3656 app()->combineMouseMoveEvents(
false);
3657 if (m_scrollTimer) {
3659 m_scrollTimer =
nullptr;
3664 case UIEVT_MOUSEMOVE:
3665 if (
app()->capturedMouseWindow() ==
this)
3666 handleCapturedMouseMove(event->params.mouse.status.X, event->params.mouse.status.Y);
3668 handleFreeMouseMove(event->params.mouse.status.X, event->params.mouse.status.Y);
3671 case UIEVT_MOUSEWHEEL:
3672 if (m_VScrollBarRange)
3677 if (event->params.timerHandle == m_scrollTimer)
3678 handleButtonsScroll();
3687void uiScrollableControl::handleButtonsScroll()
3689 switch (m_mouseOverItem) {
3690 case uiScrollBarItem::LeftButton:
3693 case uiScrollBarItem::RightButton:
3696 case uiScrollBarItem::TopButton:
3699 case uiScrollBarItem::BottomButton:
3708void uiScrollableControl::handlePageScroll()
3710 switch (m_mouseOverItem) {
3711 case uiScrollBarItem::PageLeft:
3714 case uiScrollBarItem::PageRight:
3717 case uiScrollBarItem::PageUp:
3720 case uiScrollBarItem::PageDown:
3729void uiScrollableControl::handleFreeMouseMove(
int mouseX,
int mouseY)
3731 auto prev = m_mouseOverItem;
3732 m_mouseOverItem = getItemAt(mouseX, mouseY);
3733 if (m_mouseOverItem !=
prev) {
3734 if (m_VScrollBarRange)
3736 if (m_HScrollBarRange)
3742void uiScrollableControl::handleCapturedMouseMove(
int mouseX,
int mouseY)
3744 if (m_mouseOverItem == uiScrollBarItem::HBar) {
3746 int offset = mouseX - m_mouseDownPos.
X;
3747 int newPos = m_mouseDownHScrollBarPosition + offset * m_HScrollBarRange / m_HBarArea;
3749 }
else if (m_mouseOverItem == uiScrollBarItem::VBar) {
3751 int offset = mouseY - m_mouseDownPos.
Y;
3752 int newPos = m_mouseDownVScrollBarPosition + offset * m_VScrollBarRange / m_VBarArea;
3758uiScrollBarItem uiScrollableControl::getItemAt(
int x,
int y)
3760 if (m_HScrollBarRange) {
3761 Rect lbtn, rbtn, bar;
3762 Rect box = getHScrollBarRects(&lbtn, &rbtn, &bar);
3763 if (lbtn.contains(x, y))
3764 return uiScrollBarItem::LeftButton;
3765 if (rbtn.contains(x, y))
3766 return uiScrollBarItem::RightButton;
3767 if (bar.contains(x, y))
3768 return uiScrollBarItem::HBar;
3769 if (box.contains(x, y))
3770 return x < bar.X1 ? uiScrollBarItem::PageLeft : uiScrollBarItem::PageRight;
3772 if (m_VScrollBarRange) {
3773 Rect tbtn, bbtn, bar;
3774 Rect box = getVScrollBarRects(&tbtn, &bbtn, &bar);
3775 if (tbtn.contains(x, y))
3776 return uiScrollBarItem::TopButton;
3777 if (bbtn.contains(x, y))
3778 return uiScrollBarItem::BottomButton;
3779 if (bar.contains(x, y))
3780 return uiScrollBarItem::VBar;
3781 if (box.contains(x, y))
3782 return y < bar.Y1 ? uiScrollBarItem::PageUp: uiScrollBarItem::PageDown;
3784 return uiScrollBarItem::None;
3788Rect uiScrollableControl::getVScrollBarRects(Rect * topButton, Rect * bottomButton, Rect * bar)
3792 Rect box = Rect(cArea.X2 + 1 - sbSize, cArea.Y1, cArea.X2, cArea.Y2 - (m_HScrollBarRange ? sbSize : 0));
3793 if (topButton && bottomButton && bar) {
3795 *topButton = Rect(box.X1 + 2, box.Y1 + 2, box.X2 - 2, box.Y1 + sbSize - 2);
3796 *bottomButton = Rect(box.X1 + 2, box.Y2 - sbSize + 2, box.X2 - 2, box.Y2 - 2);
3798 int barAreaY1 = topButton->Y2 + 2;
3799 int barAreaY2 = bottomButton->Y1 - 2;
3800 m_VBarArea = barAreaY2 - barAreaY1 + 1;
3801 int barOffsetY = m_VScrollBarPosition * m_VBarArea / m_VScrollBarRange;
3802 int barHeight = m_VScrollBarVisible * m_VBarArea / m_VScrollBarRange;
3803 *bar = Rect(box.X1 + 1, barAreaY1 + barOffsetY, box.X2 - 1, barAreaY1 + barOffsetY + barHeight);
3809Rect uiScrollableControl::getHScrollBarRects(Rect * leftButton, Rect * rightButton, Rect * bar)
3813 Rect box = Rect(cArea.X1, cArea.Y2 + 1 - sbSize, cArea.X2 - (m_VScrollBarRange ? sbSize : 0), cArea.Y2);
3814 if (leftButton && rightButton && bar) {
3816 *leftButton = Rect(box.X1 + 2, box.Y1 + 2, box.X1 + sbSize - 2, box.Y2 - 2);
3817 *rightButton = Rect(box.X2 - sbSize + 2, box.Y1 + 2, box.X2 - 2, box.Y2 - 2);
3819 int barAreaX1 = leftButton->X2 + 2;
3820 int barAreaX2 = rightButton->X1 - 2;
3821 m_HBarArea = barAreaX2 - barAreaX1 + 1;
3822 int barOffsetX = m_HScrollBarPosition * m_HBarArea / m_HScrollBarRange;
3823 int barWidth = m_HScrollBarVisible * m_HBarArea / m_HScrollBarRange;
3824 *bar = Rect(barAreaX1 + barOffsetX, box.Y1 + 1, barAreaX1 + barOffsetX + barWidth, box.Y2 - 1);
3830void uiScrollableControl::paintScrollableControl()
3834 if (m_HScrollBarRange) {
3836 Rect lbtn, rbtn, bar;
3837 Rect box = getHScrollBarRects(&lbtn, &rbtn, &bar);
3841 canvas()->
fillRectangle(Rect(box.X1, box.Y1, bar.X1 - 1, box.Y2));
3842 canvas()->
fillRectangle(Rect(bar.X2 + 1, box.Y1, box.X2, box.Y2));
3843 canvas()->
drawLine(bar.X1, box.Y1, bar.X2, box.Y1);
3844 canvas()->
drawLine(bar.X1, box.Y2, bar.X2, box.Y2);
3846 canvas()->
setPenColor(m_mouseOverItem == uiScrollBarItem::LeftButton ? mouseOverFColor : FColor);
3847 canvas()->
drawLine(lbtn.X2, lbtn.Y1, lbtn.X1, lbtn.Y1 + lbtn.height() / 2);
3848 canvas()->
drawLine(lbtn.X1, lbtn.Y1 + lbtn.height() / 2, lbtn.X2, lbtn.Y2);
3849 canvas()->
setPenColor(m_mouseOverItem == uiScrollBarItem::RightButton ? mouseOverFColor : FColor);
3850 canvas()->
drawLine(rbtn.X1, rbtn.Y1, rbtn.X2, rbtn.Y1 + lbtn.height() / 2);
3851 canvas()->
drawLine(rbtn.X2, rbtn.Y1 + lbtn.height() / 2, rbtn.X1, rbtn.Y2);
3853 canvas()->
setBrushColor(m_mouseOverItem == uiScrollBarItem::HBar ? mouseOverFColor : FColor);
3856 if (m_VScrollBarRange) {
3858 Rect ubtn, bbtn, bar;
3859 Rect box = getVScrollBarRects(&ubtn, &bbtn, &bar);
3863 canvas()->
fillRectangle(Rect(box.X1, box.Y1, box.X2, bar.Y1 - 1));
3864 canvas()->
fillRectangle(Rect(box.X1, bar.Y2 + 1, box.X2, box.Y2));
3865 canvas()->
drawLine(box.X1, bar.Y1, box.X1, bar.Y2);
3866 canvas()->
drawLine(box.X2, bar.Y1, box.X2, bar.Y2);
3868 if (m_HScrollBarRange)
3871 canvas()->
setPenColor(m_mouseOverItem == uiScrollBarItem::TopButton ? mouseOverFColor : FColor);
3872 canvas()->
drawLine(ubtn.X1, ubtn.Y2, ubtn.X1 + ubtn.width() / 2, ubtn.Y1);
3873 canvas()->
drawLine(ubtn.X1 + ubtn.width() / 2, ubtn.Y1, ubtn.X2, ubtn.Y2);
3874 canvas()->
setPenColor(m_mouseOverItem == uiScrollBarItem::BottomButton ? mouseOverFColor : FColor);
3875 canvas()->
drawLine(bbtn.X1, bbtn.Y1, bbtn.X1 + bbtn.width() / 2, bbtn.Y2);
3876 canvas()->
drawLine(bbtn.X1 + bbtn.width() / 2, bbtn.Y2, bbtn.X2, bbtn.Y1);
3878 canvas()->
setBrushColor(m_mouseOverItem == uiScrollBarItem::VBar ? mouseOverFColor : FColor);
3887 r.
X2 -= (m_VScrollBarRange ? m_scrollableControlStyle.
scrollBarSize : 0);
3888 r.
Y2 -= (m_HScrollBarRange ? m_scrollableControlStyle.
scrollBarSize : 0);
3905 m_firstVisibleItem(0)
3915 m_listBoxStyle.adaptToDisplayColors(
app()->displayColors());
3922uiCustomListBox::~uiCustomListBox()
3927void uiCustomListBox::processEvent(uiEvent * event)
3929 uiScrollableControl::processEvent(event);
3931 switch (event->id) {
3938 case UIEVT_MOUSEBUTTONDOWN:
3939 if (event->params.mouse.changedButton == 1)
3940 mouseDownSelect(event->params.mouse.status.X, event->params.mouse.status.Y);
3943 case UIEVT_MOUSEMOVE:
3945 mouseMoveSelect(event->params.mouse.status.X, event->params.mouse.status.Y);
3949 handleKeyDown(event->params.key);
3960 case UIEVT_KILLFOCUS:
3972 case UIEVT_DBLCLICK:
3984 bool shift = key.
SHIFT;
4013 selectItem(items_getCount() - 1, shift, shift);
4024 if (items_getCount() > 0) {
4025 index = iclamp(index, 0, items_getCount() - 1);
4028 items_deselectAll();
4030 if (index <= first) {
4031 for (
int i = index; i <= first; ++i)
4032 items_select(i,
true);
4034 for (
int i = index; i >= first; --i)
4035 items_select(i,
true);
4038 items_select(index,
true);
4042 makeItemVisible(index);
4051void uiCustomListBox::makeItemVisible(
int index)
4054 if (index < m_firstVisibleItem)
4055 m_firstVisibleItem = index;
4064 items_deselectAll();
4070void uiCustomListBox::paintListBox()
4076 if (itmRect.height() * items_getCount() > cliRect.height()) {
4077 int visible = cliRect.height() / itmRect.height();
4078 int range = items_getCount();
4087 m_firstVisibleItem = 0;
4093 int index = m_firstVisibleItem;
4095 if (!itmRect.intersects(cliRect))
4100 if (index < items_getCount() && items_selected(index))
4105 if (index < items_getCount()) {
4108 items_draw(index, itmRect);
4112 itmRect = itmRect.translate(0, m_listBoxStyle.
itemHeight);
4122 for (
int i = 0; i < items_getCount(); ++i)
4123 if (items_selected(i))
4132 for (
int i = items_getCount() - 1; i >= 0; --i)
4133 if (items_selected(i))
4152int uiCustomListBox::getItemAtMousePos(
int mouseX,
int mouseY)
4155 if (cliRect.contains(mouseX, mouseY)) {
4156 int idx = m_firstVisibleItem + (mouseY - cliRect.
Y1) / m_listBoxStyle.
itemHeight;
4157 return idx < items_getCount() ? idx : -1;
4163void uiCustomListBox::mouseDownSelect(
int mouseX,
int mouseY)
4165 int idx = getItemAtMousePos(mouseX, mouseY);
4169 bool wasSelected = items_selected(idx);
4171 items_select(idx, !wasSelected);
4173 items_deselectAll();
4175 items_select(idx,
true);
4179 items_deselectAll();
4180 items_select(idx,
true);
4182 }
else if (idx == -1)
4183 items_deselectAll();
4191void uiCustomListBox::mouseMoveSelect(
int mouseX,
int mouseY)
4193 int idx = getItemAtMousePos(mouseX, mouseY);
4194 if (idx >= 0 && !items_selected(idx)) {
4195 items_deselectAll();
4196 items_select(idx,
true);
4222void uiListBox::items_draw(
int index,
const Rect & itemRect)
4224 int x = itemRect.
X1 + 1;
4241 m_selectedColor((
Color)0)
4252void uiColorListBox::items_draw(
int index,
const Rect & itemRect)
4254 constexpr int BORDER = 1;
4256 canvas()->
fillRectangle(itemRect.
X1 + BORDER, itemRect.
Y1 + BORDER, itemRect.
X2 - BORDER, itemRect.
Y2 - BORDER);
4280void uiFileBrowser::items_draw(
int index,
const Rect & itemRect)
4282 int x = itemRect.
X1 + 1;
4286 static const char * DIRTXT =
"[dir]";
4293void uiFileBrowser::items_select(
int index,
bool select)
4297 else if (index == m_selected || index == -1)
4305 m_selected = m_dir.
count() > 0 ? 0 : -1;
4313 m_selected = m_dir.
count() > 0 ? 0 : -1;
4320 return m_selected >= 0 ? m_dir.
get(m_selected)->
name :
nullptr;
4326 return m_selected >= 0 ? m_dir.
get(m_selected)->
isDir :
false;
4330void uiFileBrowser::enterSubDir()
4332 if (m_selected >= 0) {
4333 auto selItem = m_dir.
get(m_selected);
4334 if (selItem->isDir) {
4347 m_selected = imin(m_dir.
count() - 1, m_selected);
4353void uiFileBrowser::processEvent(uiEvent * event)
4355 uiCustomListBox::processEvent(event);
4357 switch (event->id) {
4372 case UIEVT_DBLCLICK:
4392 :
uiControl(parent, pos, size, visible, 0),
4393 m_listHeight(listHeight),
4395 m_listBoxParent(nullptr)
4404 m_comboBoxStyle.adaptToDisplayColors(
app()->displayColors());
4416uiCustomComboBox::~uiCustomComboBox()
4428 updateEditControl();
4432void uiCustomComboBox::processEvent(uiEvent * event)
4434 uiControl::processEvent(event);
4436 switch (event->id) {
4443 updateEditControl();
4450 m_loseFocusBy = key.
SHIFT ? -1 : 2;
4452 uiEvent evt = uiEvent(
parentFrame(), UIEVT_KEYDOWN);
4453 evt.params.key = key;
4455 evt.id = UIEVT_KEYUP;
4467 case UIEVT_MOUSEBUTTONDOWN:
4468 if (event->params.mouse.changedButton == 1 && getButtonRect().contains(event->params.mouse.status.X, event->params.mouse.status.Y))
4472 case UIEVT_CHILDSETFOCUS:
4473 if (m_comboBoxProps.
openOnFocus && event->params.focusInfo.newFocused == editcontrol()
4474 && event->params.focusInfo.oldFocused != listbox()
4475 && event->params.focusInfo.oldFocused !=
this) {
4480 case UIEVT_SETFOCUS:
4481 if (m_loseFocusBy) {
4485 if (event->params.focusInfo.oldFocused != listbox() && event->params.focusInfo.oldFocused != editcontrol()) {
4488 }
else if (!isListBoxOpen()) {
4491 }
else if (event->params.focusInfo.oldFocused == listbox()) {
4498 listbox()->processEvent(event);
4503 if (((event->params.key.RALT || event->params.key.LALT) && (event->params.key.VK ==
VK_DOWN || event->params.key.VK ==
VK_UP)) || (event->params.key.VK ==
VK_RETURN))
4517void uiCustomComboBox::openListBox()
4520 if (r.Y2 + m_listHeight + 1 >=
app()->rootWindow()->
size().
height) {
4523 r.Y1 = r.Y2 - m_listHeight;
4527 r.Y2 = r.Y1 + m_listHeight;
4540void uiCustomComboBox::closeListBox()
4543 if (
app()->focusedWindow() ==
nullptr ||
app()->focusedWindow() == listbox()) {
4551void uiCustomComboBox::switchListBox()
4553 if (isListBoxOpen()) {
4562Size uiCustomComboBox::getEditControlSize()
4565 return Size(clientArea.width() - buttonWidth(), clientArea.height());
4569int uiCustomComboBox::buttonWidth()
4572 return clientArea.height() / 2;
4576Rect uiCustomComboBox::getButtonRect()
4579 btnRect.X1 = btnRect.X2 - buttonWidth() + 1;
4584void uiCustomComboBox::paintButton()
4586 Rect btnRect = getButtonRect();
4594 Rect arrowRect = btnRect.hShrink(1).vShrink(2);
4595 int hHeight = arrowRect.height() / 2;
4596 int hWidth = arrowRect.width() / 2;
4597 constexpr int vDist = 2;
4598 canvas()->
drawLine(arrowRect.X1, arrowRect.Y1 + hHeight - vDist, arrowRect.X1 + hWidth, arrowRect.Y1);
4599 canvas()->
drawLine(arrowRect.X1 + hWidth, arrowRect.Y1, arrowRect.X2, arrowRect.Y1 + hHeight - vDist);
4600 canvas()->
drawLine(arrowRect.X1, arrowRect.Y1 + hHeight + vDist, arrowRect.X1 + hWidth, arrowRect.Y2);
4601 canvas()->
drawLine(arrowRect.X1 + hWidth, arrowRect.Y2, arrowRect.X2, arrowRect.Y1 + hHeight + vDist);
4616 m_textEdit(nullptr),
4632uiComboBox::~uiComboBox()
4638void uiComboBox::updateEditControl()
4657 m_colorBox(nullptr),
4658 m_colorListBox(nullptr)
4670uiColorComboBox::~uiColorComboBox()
4676void uiColorComboBox::updateEditControl()
4692 :
uiControl(parent, pos, size, visible, 0),
4706 m_checkBoxStyle.adaptToDisplayColors(
app()->displayColors());
4713uiCheckBox::~uiCheckBox()
4718void uiCheckBox::paintCheckBox()
4733 canvas()->
drawLine(r.X1, r.Y2 - r.height() / 3, r.X1 + r.width() / 3, r.Y2);
4734 canvas()->
drawLine(r.X1 + r.width() / 3, r.Y2, r.X2, r.Y1);
4738 canvas()->
fillEllipse(r.X1 + r.width() / 2 - 1, r.Y1 + r.height() / 2 - 1, r.width(), r.height());
4745void uiCheckBox::processEvent(uiEvent * event)
4747 uiControl::processEvent(event);
4749 switch (event->id) {
4761 case UIEVT_MOUSEENTER:
4765 case UIEVT_MOUSEBUTTONDOWN:
4766 if (event->params.mouse.changedButton == 1)
4770 case UIEVT_MOUSELEAVE:
4788void uiCheckBox::trigger()
4792 m_checked = !m_checked;
4806 if (value != m_checked) {
4816void uiCheckBox::unCheckGroup()
4818 if (m_groupIndex == -1)
4823 if (chk->m_groupIndex == m_groupIndex)
4841 :
uiControl(parent, pos, size, visible, 0),
4842 m_orientation(orientation),
4846 m_ticksFrequency(25)
4856 m_sliderStyle.adaptToDisplayColors(
app()->displayColors());
4863uiSlider::~uiSlider()
4870 if (value != m_position) {
4871 m_position = iclamp(value, m_min, m_max);
4882 m_ticksFrequency = ticksFrequency;
4883 m_position = iclamp(m_position, m_min, m_max);
4887void uiSlider::paintSlider()
4890 Rect slideRect = cRect.shrink(4);
4891 Rect gripRect = getGripRect();
4897 switch (m_orientation) {
4910 if (m_ticksFrequency > 0) {
4912 int range = m_max - m_min + 0;
4913 for (
int p = m_min; p <= m_max; p += m_ticksFrequency) {
4914 switch (m_orientation) {
4917 int x = slideRect.
X1 + slideRect.width() * (p - m_min) / range;
4923 int y = slideRect.
Y2 - slideRect.height() * (p - m_min) / range;
4938Rect uiSlider::getGripRect()
4941 Rect slideRect = cRect.shrink(4);
4942 int range = m_max - m_min + 0;
4943 switch (m_orientation) {
4946 int x = slideRect.X1 + slideRect.width() * (m_position - m_min) / range;
4947 return Rect(x - 4, cRect.Y1, x + 4, cRect.Y2);
4951 int y = slideRect.Y2 - slideRect.height() * (m_position - m_min) / range;
4952 return Rect(cRect.X1, y - 4, cRect.X2, y + 4);
4960void uiSlider::moveGripTo(
int x,
int y)
4963 Rect slideRect = cRect.shrink(4);
4964 int range = m_max - m_min + 1;
4965 switch (m_orientation) {
4967 setPosition(m_min + (x - slideRect.X1) * range / slideRect.width());
4970 setPosition(m_min + (slideRect.Y2 - y) * range / slideRect.height());
4976void uiSlider::processEvent(uiEvent * event)
4978 uiControl::processEvent(event);
4980 switch (event->id) {
4987 case UIEVT_MOUSEBUTTONDOWN:
4988 moveGripTo(event->params.mouse.status.X, event->params.mouse.status.Y);
4991 case UIEVT_MOUSEMOVE:
4992 if (
app()->capturedMouseWindow() ==
this)
4993 moveGripTo(event->params.mouse.status.X, event->params.mouse.status.Y);
4997 handleKeyDown(event->params.key);
5000 case UIEVT_MOUSEENTER:
5004 case UIEVT_MOUSELEAVE:
5069 :
uiControl(parent, pos, size, visible, 0)
5078 m_progressBarStyle.adaptToDisplayColors(
app()->displayColors());
5087uiProgressBar::~uiProgressBar()
5092void uiProgressBar::paintProgressBar()
5096 int splitPos = cRect.width() * m_percentage / 100;
5097 Rect fRect = Rect(cRect.X1, cRect.Y1, cRect.X1 + splitPos, cRect.Y2);
5098 Rect bRect = Rect(cRect.X1 + splitPos + 1, cRect.Y1, cRect.X2, cRect.Y2);
5108 sprintf(txt,
"%d%%", m_percentage);
5112 int y = cRect.Y1 + (cRect.height() - m_progressBarStyle.
textFont->height) / 2;
5118void uiProgressBar::processEvent(uiEvent * event)
5120 uiControl::processEvent(event);
5122 switch (event->id) {
5137 value = imin(imax(0, value), 100);
5138 if (value != m_percentage) {
5139 m_percentage = value;
5167void uiSimpleMenu::processEvent(uiEvent * event)
5169 uiCustomListBox::processEvent(event);
5171 switch (event->id) {
5173 case UIEVT_MOUSEBUTTONUP:
5174 if (event->params.mouse.changedButton == 1) {
5175 int idx = getItemAtMousePos(event->params.mouse.status.X, event->params.mouse.status.Y);
5186 }
else if (event->params.key.VK ==
VK_ESCAPE) {
5198void uiSimpleMenu::items_draw(
int index,
const Rect & itemRect)
5200 int x = itemRect.X1 + 1;
5227 if (!isListBoxOpen())
5232 m_menu->
items().appendSepList(itemsText, separator);
5236 m_selectedItem = idx;
5244uiSplitButton::~uiSplitButton()
5249void uiSplitButton::processEvent(uiEvent * event)
5251 uiCustomComboBox::processEvent(event);
5253 switch (event->id) {
5255 case UIEVT_SETFOCUS:
5256 if (m_selectedItem > -1) {
5258 m_selectedItem = -1;
5268void uiSplitButton::openListBox()
5271 uiCustomComboBox::openListBox();
5275void uiSplitButton::updateEditControl()
5280void uiSplitButton::paintButton()
5282 Rect btnRect = getButtonRect();
5289 Rect arrowRect = btnRect.hShrink(btnRect.width() / 4).vShrink(btnRect.height() / 4);
5290 if ((arrowRect.X1 + arrowRect.X2) & 1)
5292 bool up = isListBoxOpen();
5293 Point points[3] = { { arrowRect.X1, up ? arrowRect.Y2 : arrowRect.Y1 },
5294 { arrowRect.X2, up ? arrowRect.Y2 : arrowRect.Y1 },
5295 { (arrowRect.X1 + arrowRect.X2) / 2, up ? arrowRect.Y1 : arrowRect.Y2 } };
This file contains fabgl::Canvas definition.
virtual int colorsCount()=0
Determines number of colors this display can provide.
void enableBackgroundPrimitiveTimeout(bool value)
Enables or disables execution time limitation inside vertical retracing interrupt.
void setMouseCursor(Cursor *cursor)
Sets mouse cursor and make it visible.
Represents the base abstract class for bitmapped display controllers.
void fillRectangle(int X1, int Y1, int X2, int Y2)
Fills a rectangle using the current brush color.
int getHeight()
Determines the canvas height in pixels.
void drawTextWithEllipsis(FontInfo const *fontInfo, int X, int Y, char const *text, int maxX)
Draws a string at specified position. Add ellipses before truncation.
void drawBitmap(int X, int Y, Bitmap const *bitmap)
Draws a bitmap at specified position.
void setPaintOptions(PaintOptions options)
Sets paint options.
void setOrigin(int X, int Y)
Sets the axes origin.
void setClippingRect(Rect const &rect)
Sets clipping rectangle relative to the origin.
void drawRectangle(int X1, int Y1, int X2, int Y2)
Draws a rectangle using the current pen color.
void drawGlyph(int X, int Y, int width, int height, uint8_t const *data, int index=0)
Draws a glyph at specified position.
int getWidth()
Determines the canvas width in pixels.
void drawPath(Point const *points, int pointsCount)
Draws a sequence of lines.
void fillEllipse(int X, int Y, int width, int height)
Fills an ellipse specifying center and size, using current brush color.
void setBrushColor(uint8_t red, uint8_t green, uint8_t blue)
Sets brush (background) color specifying color components.
int textExtent(FontInfo const *fontInfo, char const *text)
Calculates text extension in pixels.
void invertRectangle(int X1, int Y1, int X2, int Y2)
Inverts a rectangle.
void drawLine(int X1, int Y1, int X2, int Y2)
Draws a line specifying initial and ending coordinates.
void setPenColor(uint8_t red, uint8_t green, uint8_t blue)
Sets pen (foreground) color specifying color components.
void clear()
Fills the entire canvas with the brush color.
void resetPaintOptions()
Resets paint options.
void resetGlyphOptions()
Resets glyph options.
void drawText(int X, int Y, char const *text, bool wrap=false)
Draws a string at specified position.
void lineTo(int X, int Y)
Draws a line starting from current pen position.
void moveTo(int X, int Y)
Moves current pen position to the spcified coordinates.
void setGlyphOptions(GlyphOptions options)
Sets drawing options for the next glyphs.
void fillPath(Point const *points, int pointsCount)
Fills the polygon enclosed in a sequence of lines.
A class with a set of drawing methods.
void changeDirectory(const char *subdir)
Sets relative directory path.
bool reload()
Reloads directory content.
bool setDirectory(const char *path)
Sets absolute directory path.
int count()
Determines number of files in current directory.
DirItem const * get(int index)
Gets file/directory at index.
void setUIApp(uiApp *app)
Sets current UI app.
The PS2 Keyboard controller class.
void setupAbsolutePositioner(int width, int height, bool createAbsolutePositionsQueue, BitmappedDisplayController *updateDisplayController=nullptr, uiApp *app=nullptr)
Initializes absolute position handler.
void terminateAbsolutePositioner()
Terminates absolute position handler.
bool isMouseAvailable()
Checks if mouse has been detected and correctly initialized.
The PS2 Mouse controller class.
static Mouse * mouse()
Returns the instance of Mouse object automatically created by PS2Controller.
static Keyboard * keyboard()
Returns the instance of Keyboard object automatically created by PS2Controller.
void killTimer(uiTimerHandle handle)
Kills a timer.
virtual void init()
Method to inherit to implement an application.
int run(BitmappedDisplayController *displayController, Keyboard *keyboard=nullptr, Mouse *mouse=nullptr)
Initializes application and executes the main event loop.
void resizeWindow(uiWindow *window, int width, int height)
Resizes a window.
bool postEvent(uiEvent const *event)
Places an event in the event queue and returns without waiting for the receiver to process the event.
void destroyWindow(uiWindow *window)
Destroys a window.
uiWindow * screenToWindow(Point &point)
Determines which window a point belongs to.
int showModalWindow(uiWindow *window)
Makes a window visible and handles it has a modal window.
uiWindow * moveFocus(int delta)
Move focus to a control with current focus index plus a delta.
void showWindow(uiWindow *window, bool value)
Makes a window visible or invisible.
uiMessageBoxResult messageBox(char const *title, char const *text, char const *button1Text, char const *button2Text=nullptr, char const *button3Text=nullptr, uiMessageBoxIcon icon=uiMessageBoxIcon::Question)
Displays a modal dialog box with an icon, text and some buttons.
void repaintRect(Rect const &rect)
Repaints a screen area.
uiMessageBoxResult inputBox(char const *title, char const *text, char *inOutString, int maxLength, char const *button1Text, char const *button2Text=nullptr)
Displays a modal dialog box with a text, a text edit and up to two buttons.
int endModalWindow(ModalWindowState *state)
Ends modal window processing.
uiWindow * setFocusedWindow(uiWindow *value)
Sets the focused window (control)
void enableKeyboardAndMouseEvents(bool value)
Enables or disables mouse and keyboard events.
void quit(int exitCode)
Terminates application and free resources.
ModalWindowState * initModalWindow(uiWindow *window)
Begins modal window processing.
uiWindow * activeWindow()
Gets a pointer to the currently active window.
uiTimerHandle setTimer(uiEvtHandler *dest, int periodMS)
Setups a timer.
uiMessageBoxResult fileDialog(char const *title, char *inOutDirectory, int maxDirNameSize, char *inOutFilename, int maxFileNameSize, char const *buttonOKText, char const *buttonCancelText, int frameWidth=200, int frameHeight=250)
Displays a modal open/save dialog box.
uiStyle * style()
Gets current application controls style.
Delegate< uiTimerHandle > onTimer
Timer event delegate.
void joinAsyncRun()
Waits for runAsync termination.
uiFrame * rootWindow()
Gets a pointer to the root window.
void repaintWindow(uiWindow *window)
Repaints a window.
uiWindow * setActiveWindow(uiWindow *value)
Sets the active window.
void processEvents()
Processes all events in queue.
void minimizeFrame(uiFrame *frame, bool value)
Minimizes or restores a frame.
uiWindow * focusedWindow()
Gets the focused window (control)
void reshapeWindow(uiWindow *window, Rect const &rect)
Reshapes a window.
void moveWindow(uiWindow *window, int x, int y)
Moves a window.
uiApp & runAsync(BitmappedDisplayController *displayController, int taskStack=3000, Keyboard *keyboard=nullptr, Mouse *mouse=nullptr)
Initializes application and executes asynchronously the main event loop.
bool insertEvent(uiEvent const *event)
Inserts (first position) an event in the event queue and returns without waiting for the receiver to ...
void maximizeFrame(uiFrame *frame, bool value)
Maximizes or restores a frame.
bool processModalWindowEvents(ModalWindowState *state, int timeout)
Processes all messages from modal window.
Represents the whole application base class.
void setChecked(bool value)
Sets current checkbox or radiobutton checked status.
Delegate onChange
Change event delegate.
uiCheckBox(uiWindow *parent, const Point &pos, const Size &size, uiCheckBoxKind kind=uiCheckBoxKind::CheckBox, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Delegate onClick
Mouse click event delegate.
Represents a checkbox or a radiobutton.
void setColor(Color value)
Sets current colorbox color.
uiColorBox(uiWindow *parent, const Point &pos, const Size &size, Color color=Color::BrightWhite, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
A color box is a control that shows a single color.
uiColorComboBox(uiWindow *parent, const Point &pos, const Size &size, int listHeight, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
uiColorListBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Shows a list of 16 colors, one selectable.
StringList & items()
A list of strings representing items of the combobox.
uiComboBox(uiWindow *parent, const Point &pos, const Size &size, int listHeight, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
uiControl(uiWindow *parent, const Point &pos, const Size &size, bool visible, uint32_t styleClassID=0)
Creates an instance of the object.
This is the base class for all controls. A control can have focus and is not activable.
uiComboBoxProps & comboBoxProps()
Sets or gets combobox properties.
Delegate onChange
Change event delegate.
uiComboBoxStyle & comboBoxStyle()
Sets or gets combobox style.
uiCustomComboBox(uiWindow *parent, const Point &pos, const Size &size, int listHeight, bool visible, uint32_t styleClassID)
Creates an instance of the object.
int selectedItem()
Represents currently selected item.
void selectItem(int index)
Selects an item.
This is a combination of a listbox and another component, base of all combobox components.
uiCustomListBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
int firstSelectedItem()
Gets the first selected item.
Delegate onKillFocus
Kill focus event delegate.
void deselectAll()
Deselects all selected items.
int lastSelectedItem()
Gets the last selected item.
Delegate onChange
Change event delegate.
uiListBoxStyle & listBoxStyle()
Sets or gets listbox style.
Delegate onClick
Mouse click event delegate.
Delegate< uiKeyEventInfo const & > onKeyUp
Key-up event delegate.
uiListBoxProps & listBoxProps()
Sets or gets list box properties.
void selectItem(int index, bool add=false, bool range=false)
Selects a listbox item.
Delegate< uiKeyEventInfo const & > onKeyType
Key-type event delegate.
Delegate onDblClick
Mouse double click event delegate.
void setScrollBar(uiOrientation orientation, int position, int visible, int range, bool repaintScrollbar)
Sets scrollbar position, visible portion and range.
Shows generic a list of selectable items.
uiApp * app()
Determines the app that owns this object.
Base class of all UI elements that can receive events.
void changeDirectory(char const *path)
Changes current directory as relative path.
void setDirectory(char const *path)
Sets current directory as absolute path.
char const * filename()
Currently selected filename.
bool isDirectory()
Determines whether currently selected item is a directory.
void update()
Reloads current directory content and repaints.
uiFileBrowser(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Shows and navigates Virtual Filesystem content.
void setTitle(char const *value)
Sets window title.
Delegate onHide
Hide window event delegate.
uiFrame(uiWindow *parent, char const *title, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Delegate onShow
Show window event delegate.
uiFrameProps & frameProps()
Sets or gets frame properties.
Delegate onPaint
Paint event delegate.
Delegate< uiKeyEventInfo const & > onKeyDown
Key-down event delegate.
void setTitleFmt(const char *format,...)
Sets window title as formatted text.
Delegate< uiKeyEventInfo const & > onKeyUp
Key-up event delegate.
Delegate onResize
Resize window event delegate.
uiFrameStyle & frameStyle()
Sets or gets frame style.
Delegate< uiTimerHandle > onTimer
Timer event delegate.
char const * title()
Determines the window title.
Rect clientRect(uiOrigin origin)
Determines the client area bounding box.
A frame is a window with a title bar, maximize/minimize/close buttons and that is resizeable or movea...
Bitmap const * bitmap()
Gets image bitmap.
void setBitmap(Bitmap const *bitmap)
Sets image bitmap.
uiImage(uiWindow *parent, Bitmap const *bitmap, const Point &pos, const Size &size=Size(0, 0), bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Image control to display a static bitmap.
char const * text()
Determines label text.
void setTextFmt(const char *format,...)
Sets label formatted text.
uiLabel(uiWindow *parent, char const *text, const Point &pos, const Size &size=Size(0, 0), bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Delegate onClick
Mouse click event delegate.
void update()
Updates the label content.
void setText(char const *value)
Sets label text.
A label is a static text UI element.
uiListBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Shows a list of selectable string items.
uiObjectType & objectType()
Determines the object type.
Delegate< Rect const & > onPaint
Paint event delegate.
uiPaintBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
uiPanel(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
A panel is used to contain and to group some controls.
void setPercentage(int value)
Sets percentage.
uiProgressBar(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
void setup(int min, int max, int ticksFrequency)
Sets minimum, maximum position and ticks frequency.
void setPosition(int value)
Sets the slider position.
Delegate onChange
Slider changed event delegate.
uiSlider(uiWindow *parent, const Point &pos, const Size &size, uiOrientation orientation, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
int max()
Gets maximum position.
int min()
Gets minimum position.
char const * text()
Gets current content of the text edit.
Delegate onChange
Text edit event delegate.
void setTextFmt(const char *format,...)
Replaces current text.
uiTextEdit(uiWindow *parent, char const *text, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
uiTextEditProps & textEditProps()
Sets or gets text edit properties.
Delegate< uiKeyEventInfo const & > onKeyType
Key-type event delegate.
void setText(char const *value)
Replaces current text.
Represents a text edit control.
uiWindow * prev()
Gets previous sibling.
bool hasChildren()
Determines whether this window has children.
void repaint(Rect const &rect)
Repaints a rectangle of this window.
uiWindow * firstChild()
Gets first child.
bool isMouseOver()
Determines whether the mouse is over this window.
void bringOnTop()
Brings this window on top.
void exitModal(int modalResult)
Exits from a modal window.
Rect transformRect(Rect const &rect, uiWindow *baseWindow)
Transforms rectangle origins from current window to another one.
uiWindow * parentFrame()
Determines the parent frame.
Point pos()
Determines the window position relative to parent window.
Rect rect(uiOrigin origin)
Determines the window bounding box.
uiWindow * next()
Gets next sibling.
uiWindow * lastChild()
Gets last child.
uint16_t styleClassID()
Determines current style class for this UI element.
void setParentProcessKbdEvents(bool value)
Enables a child window to send keyboard events to its parent.
Size size()
Determines the window size.
uiWindowProps & windowProps()
Sets or gets window properties.
uiWindowStyle & windowStyle()
Sets or gets window style.
int focusIndex()
Determines the focus index (aka tab-index)
Size clientSize()
Determines the client area size.
bool isActiveWindow()
Determines wheter this window is the active window.
void repaint()
Repaints this window.
void bringAfter(uiWindow *insertionPoint)
Brings this window after another one.
bool hasFocus()
Determines whether this window or control has focus.
uiWindow * parent()
Determines the parent window.
uiWindow(uiWindow *parent, const Point &pos, const Size &size, bool visible, uint32_t styleClassID=0)
Creates an instance of the object.
Point clientPos()
Determines position of the client area.
uiWindowState state()
Determines the window state.
virtual Rect clientRect(uiOrigin origin)
Determines the client area bounding box.
Base class for all visible UI elements (Frames and Controls)
GlyphOptions & DoubleWidth(uint8_t value)
Helper method to set or reset doubleWidth.
GlyphOptions & Invert(uint8_t value)
Helper method to set or reset foreground and background swapping.
GlyphOptions & Underline(bool value)
Helper method to set or reset underlined.
GlyphOptions & Italic(bool value)
Helper method to set or reset italic.
GlyphOptions & Bold(bool value)
Helper method to set or reset bold.
GlyphOptions & FillBackground(bool value)
Helper method to set or reset fillBackground.
This file contains all classes related to FabGL Graphical User Interface.
This file contains some utility classes and functions.
uiButtonKind
Specifies the button kind.
uiMessageBoxResult
Return values from uiApp.messageBox() method.
uiOrientation
Item direction/orientation.
uiMessageBoxIcon
Icon displayed by the uiApp.messageBox() method.
Color
This enum defines named colors.
CursorName
This enum defines a set of predefined mouse cursors.
uiCheckBoxKind
Specifies the combobox behaviour.
uiOrigin
Specifies window rectangle origin.
This file contains fabgl::Keyboard definition.
This file contains fabgl::Mouse definition.
Represents the coordinate of a point.
Represents a 24 bit RGB color.
Represents a bidimensional size.
uint16_t caretBlinkingTime
RGB888 mouseOverForegroundColor
RGB888 checkedBackgroundColor
RGB888 mouseOverBackgroundColor
RGB888 buttonBackgroundColor
uint8_t hasMaximizeButton
uint8_t hasMinimizeButton
RGB888 mouseOverButtonColor
RGB888 activeTitleBackgroundColor
RGB888 mouseOverBackgroundButtonColor
FontInfo const * titleFont
RGB888 titleBackgroundColor
Contains details about the key event.
FontInfo const * textFont
uint8_t selectOnMouseOver
FontInfo const * textFont
RGB888 selectedBackgroundColor
RGB888 focusedSelectedBackgroundColor
RGB888 focusedBackgroundColor
Contains details about the mouse event.
FontInfo const * textFont
RGB888 mouseOverGripColor
FontInfo const * textFont
RGB888 mouseOverBackgroundColor
RGB888 focusedBackgroundColor
RGB888 focusedBorderColor
uint8_t focusedBorderSize
Specifies various glyph painting options.