27 #include "freertos/FreeRTOS.h" 28 #include "freertos/timers.h" 39 #include "images/bitmaps.h" 43 #pragma GCC optimize ("O2") 56 void 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);
162 uiObject::~uiObject()
176 uiEvtHandler::uiEvtHandler(
uiApp * app)
179 objectType().uiEvtHandler =
true;
183 uiEvtHandler::~uiEvtHandler()
186 m_app->killEvtHandlerTimers(
this);
190 void 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;
345 void 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;
408 void 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);
448 void 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) {
480 void 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;
547 void 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;
573 void 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;
621 void uiApp::postDebugMsg(
char const * msg)
623 uiEvent evt = uiEvent(
nullptr, UIEVT_DEBUGMSG);
624 evt.params.debugMsg = msg;
629 bool uiApp::getEvent(uiEvent * event,
int timeOutMS)
631 return xQueueReceive(m_eventsQueue, event, msToTicks(timeOutMS)) == pdTRUE;
635 bool uiApp::peekEvent(uiEvent * event,
int timeOutMS)
637 return xQueuePeek(m_eventsQueue, event, msToTicks(timeOutMS)) == pdTRUE;
641 void 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);
926 void 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; });
967 void 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;
987 void 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;
1008 void uiApp::setCaret(
bool value)
1014 void uiApp::setCaret(Point
const & pos)
1016 setCaret(m_caretRect.move(pos));
1020 void uiApp::setCaret(Rect
const & rect)
1028 void 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);
1064 void 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;
1269 uiMessageBoxResult 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);
1423 uiWindow::~uiWindow()
1429 void uiWindow::freeChildren()
1435 m_firstChild = m_lastChild =
nullptr;
1439 void 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;
1455 void 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;
1480 void 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;
1504 void uiWindow::moveChildOnTop(uiWindow * child)
1506 removeChild(child,
false);
1513 void uiWindow::moveAfter(uiWindow * child, uiWindow * underlyingChild)
1515 removeChild(child,
false);
1516 insertAfter(child, underlyingChild);
1522 parent()->moveChildOnTop(
this);
1528 parent()->moveAfter(
this, insertionPoint);
1533 bool 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);
1600 void uiWindow::beginPaint(uiEvent * paintEvent,
Rect const & clippingRect)
1604 canvas()->
setClippingRect( clippingRect.intersection(paintEvent->params.rect) );
1610 void 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:
1720 void uiWindow::paintWindow()
1726 for (
int i = 0; i < bSize; ++i)
1733 void 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;
1765 void 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;
1861 bool uiWindow::isFocusable()
1868 uiWindow * 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);
1966 int uiFrame::titleBarHeight()
1968 return m_frameStyle.
titleFont->height + 3;
1972 Rect uiFrame::titleBarRect()
1975 r.Y2 = r.Y1 + titleBarHeight() - 1;
1985 if (m_titleLength > 0)
1986 r.
Y1 += titleBarHeight();
1992 Size 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;
2016 Rect 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);
2028 void uiFrame::paintFrame()
2032 if (m_titleLength > 0) {
2033 int barHeight = titleBarHeight();
2039 int btnX = paintButtons(bkgRect);
2045 bkgRect.Y1 += barHeight;
2056 int 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);
2115 void 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)
2234 uiFrameItem 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;
2296 void 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);
2382 void 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;
2405 void 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:
2464 void 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)
2507 uiControl::~uiControl()
2512 void uiControl::processEvent(uiEvent * event)
2514 uiWindow::processEvent(event);
2529 :
uiControl(parent, pos, size, visible, 0),
2544 m_buttonStyle.adaptToDisplayColors(
app()->displayColors());
2553 uiButton::~uiButton()
2561 int len = strlen(value);
2562 m_text = (
char*) realloc(m_text, len + 1);
2563 strcpy(m_text, value);
2569 void uiButton::paintButton()
2574 if (
app()->capturedMouseWindow() ==
this)
2581 paintContent(bkgRect);
2585 void 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;
2612 void 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:
2660 void uiButton::trigger()
2672 if (value != m_down) {
2691 :
uiControl(parent, pos, size, visible, 0),
2709 m_textEditStyle.adaptToDisplayColors(
app()->displayColors());
2718 uiTextEdit::~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);
2753 void 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);
2935 Rect uiTextEdit::getEditRect()
2941 void uiTextEdit::paintTextEdit()
2943 m_contentRect = getEditRect();
2955 uint8_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;
2973 void 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);
2999 int 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);
3012 void uiTextEdit::updateCaret()
3015 int x = charColumnToWindowX(m_cursorCol);
3016 app()->setCaret(Rect(x, m_contentRect.
Y1, x, m_contentRect.
Y1 + m_textEditStyle.
textFont->height));
3025 void 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);
3073 int 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))
3086 void 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);
3104 void 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);
3117 void 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);
3135 int 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);
3145 int 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);
3156 void 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);
3241 void uiLabel::paintLabel()
3262 int y = r.
Y1 + (r.height() - m_labelStyle.
textFont->height) / 2;
3267 void 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)
3334 void 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;
3347 void 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());
3395 void uiPanel::paintPanel()
3404 void uiPanel::processEvent(uiEvent * event)
3406 uiControl::processEvent(event);
3408 switch (event->id) {
3440 m_paintBoxStyle.adaptToDisplayColors(
app()->displayColors());
3447 uiPaintBox::~uiPaintBox()
3452 void uiPaintBox::paintPaintBox()
3464 void uiPaintBox::processEvent(uiEvent * event)
3466 uiScrollableControl::processEvent(event);
3468 switch (event->id) {
3491 :
uiControl(parent, pos, size, visible, 0),
3505 uiColorBox::~uiColorBox()
3517 void uiColorBox::paintColorBox()
3526 void 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());
3574 uiScrollableControl::~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);
3620 void uiScrollableControl::repaintScrollBar(
uiOrientation orientation)
3626 void 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();
3687 void uiScrollableControl::handleButtonsScroll()
3689 switch (m_mouseOverItem) {
3690 case uiScrollBarItem::LeftButton:
3693 case uiScrollBarItem::RightButton:
3696 case uiScrollBarItem::TopButton:
3699 case uiScrollBarItem::BottomButton:
3708 void uiScrollableControl::handlePageScroll()
3710 switch (m_mouseOverItem) {
3711 case uiScrollBarItem::PageLeft:
3714 case uiScrollBarItem::PageRight:
3717 case uiScrollBarItem::PageUp:
3720 case uiScrollBarItem::PageDown:
3729 void 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)
3742 void 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;
3758 uiScrollBarItem 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;
3788 Rect 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);
3809 Rect 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);
3830 void 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());
3922 uiCustomListBox::~uiCustomListBox()
3927 void 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);
4051 void uiCustomListBox::makeItemVisible(
int index)
4054 if (index < m_firstVisibleItem)
4055 m_firstVisibleItem = index;
4064 items_deselectAll();
4070 void 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))
4152 int 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;
4163 void 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();
4191 void 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);
4222 void uiListBox::items_draw(
int index,
const Rect & itemRect)
4224 int x = itemRect.
X1 + 1;
4241 m_selectedColor((
Color)0)
4252 void 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);
4280 void uiFileBrowser::items_draw(
int index,
const Rect & itemRect)
4282 int x = itemRect.
X1 + 1;
4286 static const char * DIRTXT =
"[dir]";
4293 void 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;
4330 void 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);
4353 void 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());
4416 uiCustomComboBox::~uiCustomComboBox()
4428 updateEditControl();
4432 void 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))
4517 void 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;
4540 void uiCustomComboBox::closeListBox()
4543 if (
app()->focusedWindow() ==
nullptr ||
app()->focusedWindow() == listbox()) {
4551 void uiCustomComboBox::switchListBox()
4553 if (isListBoxOpen()) {
4562 Size uiCustomComboBox::getEditControlSize()
4565 return Size(clientArea.width() - buttonWidth(), clientArea.height());
4569 int uiCustomComboBox::buttonWidth()
4572 return clientArea.height() / 2;
4576 Rect uiCustomComboBox::getButtonRect()
4579 btnRect.X1 = btnRect.X2 - buttonWidth() + 1;
4584 void 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),
4632 uiComboBox::~uiComboBox()
4638 void uiComboBox::updateEditControl()
4657 m_colorBox(nullptr),
4658 m_colorListBox(nullptr)
4670 uiColorComboBox::~uiColorComboBox()
4676 void uiColorComboBox::updateEditControl()
4692 :
uiControl(parent, pos, size, visible, 0),
4706 m_checkBoxStyle.adaptToDisplayColors(
app()->displayColors());
4713 uiCheckBox::~uiCheckBox()
4718 void 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());
4745 void 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:
4788 void uiCheckBox::trigger()
4792 m_checked = !m_checked;
4806 if (value != m_checked) {
4816 void uiCheckBox::unCheckGroup()
4818 if (m_groupIndex == -1)
4821 if (sibling !=
this &&
objectType().uiCheckBox) {
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());
4863 uiSlider::~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);
4887 void 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;
4938 Rect 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);
4960 void 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());
4976 void 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());
5087 uiProgressBar::~uiProgressBar()
5092 void 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;
5118 void 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;
5167 void 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) {
5198 void 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;
5244 uiSplitButton::~uiSplitButton()
5249 void 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;
5268 void uiSplitButton::openListBox()
5271 uiCustomComboBox::openListBox();
5275 void uiSplitButton::updateEditControl()
5280 void 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 } };
int textExtent(FontInfo const *fontInfo, char const *text)
Calculates text extension in pixels.
RGB888 mouseOverGripColor
Represents a 24 bit RGB color.
uiWindow * setActiveWindow(uiWindow *value)
Sets the active window.
uiWindowStyle & windowStyle()
Sets or gets window style.
void selectItem(int index, bool add=false, bool range=false)
Selects a listbox item.
GlyphOptions & Bold(bool value)
Helper method to set or reset bold.
Delegate onChange
Change event delegate.
int selectedItem()
Represents currently selected item.
A class with a set of drawing methods.
uiComboBoxStyle & comboBoxStyle()
Sets or gets combobox style.
Shows a list of 16 colors, one selectable.
A frame is a window with a title bar, maximize/minimize/close buttons and that is resizeable or movea...
int lastSelectedItem()
Gets the last selected item.
Contains details about the key event.
Rect rect(uiOrigin origin)
Determines the window bounding box.
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.
ModalWindowState * initModalWindow(uiWindow *window)
Begins modal window processing.
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.
uiOrientation
Item direction/orientation.
uiApp & runAsync(BitmappedDisplayController *displayController, int taskStack=3000, Keyboard *keyboard=nullptr, Mouse *mouse=nullptr)
Initializes application and executes asynchronously the main event loop.
void setScrollBar(uiOrientation orientation, int position, int visible, int range, bool repaintScrollbar)
Sets scrollbar position, visible portion and range.
int firstSelectedItem()
Gets the first selected item.
Represents the whole application base class.
uint16_t styleClassID()
Determines current style class for this UI element.
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.
bool insertEvent(uiEvent const *event)
Inserts (first position) an event in the event queue and returns without waiting for the receiver to ...
Delegate onClick
Mouse click event delegate.
This file contains all classes related to FabGL Graphical User Interface.
This is a combination of a listbox and another component, base of all combobox components.
uiStyle * style()
Gets current application controls style.
void setText(char const *value)
Sets label text.
char const * text()
Gets current content of the text edit.
void selectItem(int index)
Selects an item.
Base class for all visible UI elements (Frames and Controls)
void update()
Reloads current directory content and repaints.
int getHeight()
Determines the canvas height in pixels.
int run(BitmappedDisplayController *displayController, Keyboard *keyboard=nullptr, Mouse *mouse=nullptr)
Initializes application and executes the main event loop.
void setup(int min, int max, int ticksFrequency)
Sets minimum, maximum position and ticks frequency.
A color box is a control that shows a single color.
void setParentProcessKbdEvents(bool value)
Enables a child window to send keyboard events to its parent.
GlyphOptions & Italic(bool value)
Helper method to set or reset italic.
void setUIApp(uiApp *app)
Sets current UI app.
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.
virtual int colorsCount()=0
Determines number of colors this display can provide.
DirItem const * get(int index)
Gets file/directory at index.
uiColorComboBox(uiWindow *parent, const Point &pos, const Size &size, int listHeight, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Delegate< Rect const & > onPaint
Paint event delegate.
FontInfo const * textFont
Shows a list of selectable string items.
uiListBoxProps & listBoxProps()
Sets or gets list box properties.
This file contains fabgl::Keyboard definition.
Bitmap const * bitmap()
Gets image bitmap.
void bringAfter(uiWindow *insertionPoint)
Brings this window after another one.
Size size()
Determines the window size.
RGB888 mouseOverBackgroundButtonColor
virtual void init()
Method to inherit to implement an application.
uiWindow * parent()
Determines the parent window.
void resetGlyphOptions()
Resets glyph options.
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.
Base class of all UI elements that can receive events.
void quit(int exitCode)
Terminates application and free resources.
Color
This enum defines named colors.
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.
static Mouse * mouse()
Returns the instance of Mouse object automatically created by PS2Controller.
uiColorListBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
bool setDirectory(const char *path)
Sets absolute directory path.
int showModalWindow(uiWindow *window)
Makes a window visible and handles it has a modal window.
Delegate< uiKeyEventInfo const & > onKeyType
Key-type event delegate.
The PS2 Keyboard controller class.
Represents the base abstract class for bitmapped display controllers.
This file contains fabgl::Canvas definition.
Size clientSize()
Determines the client area size.
uiWindow * lastChild()
Gets last child.
A panel is used to contain and to group some controls.
int getWidth()
Determines the canvas width in pixels.
Represents a checkbox or a radiobutton.
void setPaintOptions(PaintOptions options)
Sets paint options.
This file contains fabgl::Mouse definition.
RGB888 mouseOverForegroundColor
void moveWindow(uiWindow *window, int x, int y)
Moves a window.
void destroyWindow(uiWindow *window)
Destroys a window.
uint16_t caretBlinkingTime
Delegate onResize
Resize window event delegate.
uiCheckBoxKind
Specifies the combobox behaviour.
void setTitleFmt(const char *format,...)
Sets window title as formatted text.
void fillEllipse(int X, int Y, int width, int height)
Fills an ellipse specifying center and size, using current brush color.
void update()
Updates the label content.
void setColor(Color value)
Sets current colorbox color.
uiWindowProps & windowProps()
Sets or gets window properties.
void setTextFmt(const char *format,...)
Sets label formatted text.
uiCustomComboBox(uiWindow *parent, const Point &pos, const Size &size, int listHeight, bool visible, uint32_t styleClassID)
Creates an instance of the object.
void setBrushColor(uint8_t red, uint8_t green, uint8_t blue)
Sets brush (background) color specifying color components.
void setClippingRect(Rect const &rect)
Sets clipping rectangle relative to the origin.
bool processModalWindowEvents(ModalWindowState *state, int timeout)
Processes all messages from modal window.
RGB888 focusedSelectedBackgroundColor
void setTextFmt(const char *format,...)
Replaces current text.
uiButtonKind
Specifies the button kind.
uiWindow * parentFrame()
Determines the parent frame.
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.
void deselectAll()
Deselects all selected items.
uiFrameProps & frameProps()
Sets or gets frame properties.
Delegate onChange
Change event delegate.
uiCustomListBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
void minimizeFrame(uiFrame *frame, bool value)
Minimizes or restores a frame.
RGB888 buttonBackgroundColor
uiFrameStyle & frameStyle()
Sets or gets frame style.
void maximizeFrame(uiFrame *frame, bool value)
Maximizes or restores a frame.
Represents the coordinate of a point.
Delegate onClick
Mouse click event delegate.
void setPosition(int value)
Sets the slider position.
This file contains some utility classes and functions.
Delegate< uiTimerHandle > onTimer
Timer event delegate.
RGB888 mouseOverBackgroundColor
uiSlider(uiWindow *parent, const Point &pos, const Size &size, uiOrientation orientation, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
void fillRectangle(int X1, int Y1, int X2, int Y2)
Fills a rectangle using the current brush color.
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.
uiControl(uiWindow *parent, const Point &pos, const Size &size, bool visible, uint32_t styleClassID=0)
Creates an instance of the object.
uiOrigin
Specifies window rectangle origin.
Rect transformRect(Rect const &rect, uiWindow *baseWindow)
Transforms rectangle origins from current window to another one.
Delegate onClick
Mouse click event delegate.
GlyphOptions & Underline(bool value)
Helper method to set or reset underlined.
Delegate< uiKeyEventInfo const & > onKeyDown
Key-down event delegate.
uiPaintBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
void drawGlyph(int X, int Y, int width, int height, uint8_t const *data, int index=0)
Draws a glyph at specified position.
char const * filename()
Currently selected filename.
bool isMouseAvailable()
Checks if mouse has been detected and correctly initialized.
uiMessageBoxResult
Return values from uiApp.messageBox() method.
Specifies various glyph painting options.
uiWindow * screenToWindow(Point &point)
Determines which window a point belongs to.
uint8_t focusedBorderSize
Delegate< uiTimerHandle > onTimer
Timer event delegate.
void terminateAbsolutePositioner()
Terminates absolute position handler.
void drawTextWithEllipsis(FontInfo const *fontInfo, int X, int Y, char const *text, int maxX)
Draws a string at specified position. Add ellipses before truncation.
Delegate onDblClick
Mouse double click event delegate.
Represents a text edit control.
uiWindow * prev()
Gets previous sibling.
void repaintWindow(uiWindow *window)
Repaints a window.
uiTextEditProps & textEditProps()
Sets or gets text edit properties.
Contains details about the mouse event.
RGB888 mouseOverButtonColor
CursorName
This enum defines a set of predefined mouse cursors.
int focusIndex()
Determines the focus index (aka tab-index)
RGB888 mouseOverBackgroundColor
FontInfo const * textFont
uiWindow * firstChild()
Gets first child.
void setPercentage(int value)
Sets percentage.
void setMouseCursor(Cursor *cursor)
Sets mouse cursor and make it visible.
uint8_t hasMaximizeButton
GlyphOptions & DoubleWidth(uint8_t value)
Helper method to set or reset doubleWidth.
void reshapeWindow(uiWindow *window, Rect const &rect)
Reshapes a window.
FontInfo const * titleFont
StringList & items()
A list of strings representing items of the combobox.
RGB888 activeTitleBackgroundColor
uiWindow * setFocusedWindow(uiWindow *value)
Sets the focused window (control)
void setBitmap(Bitmap const *bitmap)
Sets image bitmap.
Delegate< uiKeyEventInfo const & > onKeyUp
Key-up event delegate.
Point pos()
Determines the window position relative to parent window.
virtual Rect clientRect(uiOrigin origin)
Determines the client area bounding box.
void setChecked(bool value)
Sets current checkbox or radiobutton checked status.
Represents a bidimensional size.
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 onKillFocus
Kill focus event delegate.
uiComboBoxProps & comboBoxProps()
Sets or gets combobox properties.
static Keyboard * keyboard()
Returns the instance of Keyboard object automatically created by PS2Controller.
uiObjectType & objectType()
Determines the object type.
bool hasChildren()
Determines whether this window has children.
RGB888 focusedBorderColor
Delegate onShow
Show window event delegate.
bool isDirectory()
Determines whether currently selected item is a directory.
uiTimerHandle setTimer(uiEvtHandler *dest, int periodMS)
Setups a timer.
int max()
Gets maximum position.
void clear()
Fills the entire canvas with the brush color.
uiApp * app()
Determines the app that owns this object.
FontInfo const * textFont
void setGlyphOptions(GlyphOptions options)
Sets drawing options for the next glyphs.
void resizeWindow(uiWindow *window, int width, int height)
Resizes a window.
int endModalWindow(ModalWindowState *state)
Ends modal window processing.
bool postEvent(uiEvent const *event)
Places an event in the event queue and returns without waiting for the receiver to process the event...
void drawLine(int X1, int Y1, int X2, int Y2)
Draws a line specifying initial and ending coordinates.
A label is a static text UI element.
void processEvents()
Processes all events in queue.
uiProgressBar(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
uiComboBox(uiWindow *parent, const Point &pos, const Size &size, int listHeight, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
uiListBox(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
void bringOnTop()
Brings this window on top.
uiWindowState state()
Determines the window state.
uiPanel(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
Rect clientRect(uiOrigin origin)
Determines the client area bounding box.
uiWindow * moveFocus(int delta)
Move focus to a control with current focus index plus a delta.
RGB888 checkedBackgroundColor
void repaintRect(Rect const &rect)
Repaints a screen area.
This is the base class for all controls. A control can have focus and is not activable.
RGB888 titleBackgroundColor
bool hasFocus()
Determines whether this window or control has focus.
uint8_t selectOnMouseOver
void setPenColor(uint8_t red, uint8_t green, uint8_t blue)
Sets pen (foreground) color specifying color components.
void repaint()
Repaints this window.
uiFileBrowser(uiWindow *parent, const Point &pos, const Size &size, bool visible=true, uint32_t styleClassID=0)
Creates an instance of the object.
void repaint(Rect const &rect)
Repaints a rectangle of this window.
char const * title()
Determines the window title.
GlyphOptions & FillBackground(bool value)
Helper method to set or reset fillBackground.
RGB888 selectedBackgroundColor
Delegate onPaint
Paint event delegate.
void drawPath(Point const *points, int pointsCount)
Draws a sequence of lines.
RGB888 focusedBackgroundColor
Shows generic a list of selectable items.
uiWindow * next()
Gets next sibling.
void drawText(int X, int Y, char const *text, bool wrap=false)
Draws a string at specified position.
Delegate onHide
Hide window event delegate.
void setDirectory(char const *path)
Sets current directory as absolute path.
uiListBoxStyle & listBoxStyle()
Sets or gets listbox style.
void invertRectangle(int X1, int Y1, int X2, int Y2)
Inverts a rectangle.
Delegate onChange
Change event delegate.
void changeDirectory(const char *subdir)
Sets relative directory path.
void setText(char const *value)
Replaces current text.
uiWindow * activeWindow()
Gets a pointer to the currently active window.
void fillPath(Point const *points, int pointsCount)
Fills the polygon enclosed in a sequence of lines.
Point clientPos()
Determines position of the client area.
uiWindow(uiWindow *parent, const Point &pos, const Size &size, bool visible, uint32_t styleClassID=0)
Creates an instance of the object.
GlyphOptions & Invert(uint8_t value)
Helper method to set or reset foreground and background swapping.
uiFrame * rootWindow()
Gets a pointer to the root window.
Delegate< uiKeyEventInfo const & > onKeyUp
Key-up event delegate.
Shows and navigates Virtual Filesystem content.
The PS2 Mouse controller class.
void setupAbsolutePositioner(int width, int height, bool createAbsolutePositionsQueue, BitmappedDisplayController *updateDisplayController=nullptr, uiApp *app=nullptr)
Initializes absolute position handler.
void setOrigin(int X, int Y)
Sets the axes origin.
void moveTo(int X, int Y)
Moves current pen position to the spcified coordinates.
int count()
Determines number of files in current directory.
bool reload()
Reloads directory content.
Delegate onChange
Text edit event delegate.
void enableBackgroundPrimitiveTimeout(bool value)
Enables or disables execution time limitation inside vertical retracing interrupt.
void resetPaintOptions()
Resets paint options.
bool isMouseOver()
Determines whether the mouse is over this window.
void joinAsyncRun()
Waits for runAsync termination.
void showWindow(uiWindow *window, bool value)
Makes a window visible or invisible.
uint8_t hasMinimizeButton
RGB888 focusedBackgroundColor
void exitModal(int modalResult)
Exits from a modal window.
uiWindow * focusedWindow()
Gets the focused window (control)
bool isActiveWindow()
Determines wheter this window is the active window.
void changeDirectory(char const *path)
Changes current directory as relative path.
void drawRectangle(int X1, int Y1, int X2, int Y2)
Draws a rectangle using the current pen color.
char const * text()
Determines label text.
void lineTo(int X, int Y)
Draws a line starting from current pen position.
void setTitle(char const *value)
Sets window title.
uiMessageBoxIcon
Icon displayed by the uiApp.messageBox() method.
FontInfo const * textFont
void enableKeyboardAndMouseEvents(bool value)
Enables or disables mouse and keyboard events.
int min()
Gets minimum position.
Image control to display a static bitmap.
void killTimer(uiTimerHandle handle)
Kills a timer.
void drawBitmap(int X, int Y, Bitmap const *bitmap)
Draws a bitmap at specified position.
Delegate< uiKeyEventInfo const & > onKeyType
Key-type event delegate.
Delegate onChange
Slider changed event delegate.