#include "wmwindow.h" #include "array.h" uint8_t __MAGIC_WINDOW = 0; static WindowT **_windowList = NULL; static GrTextOption _textOption; WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title, uint8_t flags, ...) { WindowT *win = NULL; NEW(WindowT, win); guiWidgetBaseSet((WidgetT *)win, __MAGIC_WINDOW, x, y, w, h); win->title = strdup(title); win->flags = flags; win->close.x = win->close.y = win->close.x2 = win->close.y2 = 0; win->titlebar.x = win->titlebar.y = win->titlebar.x2 = win->titlebar.y2 = 0; win->minimize.x = win->minimize.y = win->minimize.x2 = win->minimize.y2 = 0; win->maximize.x = win->maximize.y = win->maximize.x2 = win->maximize.y2 = 0; win->bounds.x = win->bounds.y = win->bounds.x2 = win->bounds.y2 = 0; arrput(_windowList, win); return win; } void windowDestroy(struct WidgetS *widget, ...) { uint16_t i; WindowT *window = (WindowT *)widget; for (i=0; ititle) DEL(_windowList[i]->title); DEL(_windowList[i]); arrdel(_windowList, i); break; } } } void windowPaint(struct WidgetS *widget, ...) { WindowT *w = (WindowT *)widget; uint16_t x1 = w->base.r.x; uint16_t y1 = w->base.r.y; uint16_t x2 = w->base.r.x + w->base.r.w - 1; uint16_t y2 = w->base.r.y + w->base.r.h - 1; uint16_t tx1; uint16_t ty1; uint16_t tx2; uint16_t ty2; uint16_t minimizeOffset = 0; GrColor titleBackgroundColor = GUI_DARKGRAY; // Fake Window contents. GrFilledBox(x1, y1, x2, y2, GUI_BLACK); // If we need a titlebar, it's 18px. if (w->title || w->flags & WIN_CLOSE || w->flags & WIN_MAXIMIZE || w->flags & WIN_MINIMIZE) { // Draw title bar background. y1 -= 18; GrFilledBox(x1, y1, x2, y1 + 17, titleBackgroundColor); // Close box? if (w->flags & WIN_CLOSE) { // 26px wide, 18 tall including highlight and shadow. w->close.x = x1 + 1; w->close.y = y1 + 1; w->close.x2 = w->close.x + 24; w->close.y2 = w->close.y + 15; GrFilledBox(w->close.x + 1, w->close.y + 1, w->close.x2 - 1, w->close.y2 - 1, GUI_LIGHTGRAY); GrHLine(w->close.x, w->close.x2, w->close.y, GUI_WHITE); GrVLine(w->close.x, w->close.y, w->close.y2, GUI_WHITE); // Button is 8px down, 3px tall, and 4px in on both sides. tx1 = w->close.x + 4; ty1 = w->close.y + 7; tx2 = w->close.x2 - 4; ty2 = w->close.y + 9; GrHLine(tx1, tx2, ty1, GUI_WHITE); GrPlot(tx1, ty1 + 1, GUI_WHITE); GrHLine(tx1, tx2, ty2, GUI_BLACK); GrVLine(tx2, ty1, ty2, GUI_BLACK); // Set titlebar area. w->titlebar.x = w->close.x2 + 2; } else { // No close box - set titlebar area. w->titlebar.x = x1; } w->titlebar.y = y1; w->titlebar.x2 = x2; w->titlebar.y2 = y1 + 17; // Maximize box? if (w->flags & WIN_MAXIMIZE) { // 26px wide, 18 tall including highlight and shadow. w->maximize.y = y1 + 1; w->maximize.x2 = x2 - 1; w->maximize.x = w->maximize.x2 - 24; w->maximize.y2 = w->maximize.y + 15; GrFilledBox(w->maximize.x + 1, w->maximize.y + 1, w->maximize.x2 - 1, w->maximize.y2 - 1, GUI_LIGHTGRAY); GrHLine(w->maximize.x, w->maximize.x2, w->maximize.y, GUI_WHITE); GrVLine(w->maximize.x, w->maximize.y, w->maximize.y2, GUI_WHITE); // Button is 3px down, and 4px in on both sides. tx1 = w->maximize.x + 4; ty1 = w->maximize.y + 4; tx2 = w->maximize.x2 - 3; ty2 = w->maximize.y + 12; GrHLine(tx1, tx2, ty1, GUI_WHITE); GrVLine(tx1, ty1, ty2, GUI_WHITE); GrHLine(tx1, tx2, ty2, GUI_BLACK); GrVLine(tx2, ty1, ty2, GUI_BLACK); // Move minimize button over. minimizeOffset = 26; // Set titlebar area. w->titlebar.x2 -= 26; } // Minimize box? if (w->flags & WIN_MINIMIZE) { // 26px wide, 18 tall including highlight and shadow. w->minimize.y = y1 + 1; w->minimize.x2 = x2 - 1 - minimizeOffset; w->minimize.x = w->minimize.x2 - 24; w->minimize.y2 = w->minimize.y + 15; GrFilledBox(w->minimize.x + 1, w->minimize.y + 1, w->minimize.x2 - 1, w->minimize.y2 - 1, GUI_LIGHTGRAY); GrHLine(w->minimize.x, w->minimize.x2, w->minimize.y, GUI_WHITE); GrVLine(w->minimize.x, w->minimize.y, w->minimize.y2, GUI_WHITE); tx1 = w->minimize.x + 10; ty1 = w->minimize.y + 6; tx2 = w->minimize.x2 - 8; ty2 = w->minimize.y + 9; GrHLine(tx1, tx2, ty1, GUI_WHITE); GrVLine(tx1, ty1, ty2, GUI_WHITE); GrHLine(tx1, tx2, ty2, GUI_BLACK); GrVLine(tx2, ty1, ty2, GUI_BLACK); // Set titlebar area. w->titlebar.x2 -= 26; } // Title font area is 12px high. GrHLine(w->titlebar.x, w->titlebar.x2 - 1, w->titlebar.y, GUI_WHITE); GrVLine(w->titlebar.x, w->titlebar.y, w->titlebar.y2 - 1, GUI_WHITE); if (w->title) { //***TODO*** Look into GrTextRegion _textOption.txo_bgcolor.v = titleBackgroundColor; ty1 = w->titlebar.y + 2; tx1 = w->titlebar.x + 2 + (w->titlebar.x2 - w->titlebar.x - 4) * 0.5 - (GrStringWidth(w->title, strlen(w->title), &_textOption) * 0.5); //***TODO*** Does not handle text being clipped. GrDrawString(w->title, strlen(w->title), tx1, ty1, &_textOption); } } // Innermost shadow frame. 1px wide. x1--; y1--; x2++; y2++; GrHLine(x1, x2, y2, GUI_WHITE); GrVLine(x2, y1, y2, GUI_WHITE); GrHLine(x1, x2, y1, GUI_DARKGRAY); GrVLine(x1, y1, y2, GUI_DARKGRAY); // Frame Border. 4px wide. x1 -= 4; y1 -= 4; x2 += 4; y2 += 4; GrFilledBox(x1, y1, x1 + 3, y2, GUI_LIGHTGRAY); GrFilledBox(x2, y1, x2 - 3, y2, GUI_LIGHTGRAY); GrFilledBox(x1, y1, x2, y1 + 3, GUI_LIGHTGRAY); GrFilledBox(x1, y2, x2, y2 - 3, GUI_LIGHTGRAY); // Resize handle. if (w->flags & WIN_RESIZE) { ty1 = y2 - 15 - 3; tx1 = x2 - 15 - 3; GrHLine(x2, x2 - 3, ty1, GUI_DARKGRAY); GrHLine(x2, x2 - 3, ty1 + 1, GUI_WHITE); GrVLine(tx1, y2, y2 - 3, GUI_DARKGRAY); GrVLine(tx1 + 1, y2, y2 - 3, GUI_WHITE); } // Outermost shadow frame. 1px wide. x1--; y1--; x2++; y2++; GrHLine(x1, x2, y1, GUI_WHITE); GrVLine(x1, y1, y2, GUI_WHITE); GrHLine(x1, x2, y2, GUI_DARKGRAY); GrVLine(x2, y1, y2, GUI_DARKGRAY); w->bounds.x = x1; w->bounds.x2 = x2; w->bounds.y = y1; w->bounds.y2 = y2; } RegisterT *windowRegister(uint8_t magic) { static RegisterT reg = { "Window", windowPaint, windowDestroy, NULL }; // One-time widget startup code. __MAGIC_WINDOW = magic; _textOption.txo_bgcolor.v = GUI_DARKGRAY; _textOption.txo_fgcolor.v = GUI_WHITE; _textOption.txo_chrtype = GR_BYTE_TEXT; _textOption.txo_direct = GR_TEXT_RIGHT; _textOption.txo_font = &GrFont_PC8x14; _textOption.txo_xalign = GR_ALIGN_DEFAULT; _textOption.txo_yalign = GR_ALIGN_DEFAULT; return ® } void wmPaint(GrMouseEvent *event) { uint16_t i; WidgetT *widget; WindowT *win; static uint8_t dragging = 0; static PointT dragOffset = { 0 }; // Do we have windows? if (arrlen(_windowList) > 0) { // Paint all windows. for (i=0; ireg->paint(widget); } // Get top window. win = _windowList[arrlen(_windowList) - 1]; // Wrap left button processing with a 'for' so we can 'break' out of it. for (;;) { // Is the left mouse button down? if (event->buttons & GR_M_LEFT) { // DEBUG - draw active regions. ***TODO*** No resize grabber here. GrBox(win->bounds.x, win->bounds.y, win->bounds.x2, win->bounds.y2, GUI_YELLOW); GrBox(win->base.r.x, win->base.r.y, win->base.r.x + win->base.r.w - 1, win->base.r.y + win->base.r.h - 1, GUI_YELLOW); GrBox(win->close.x, win->close.y, win->close.x2, win->close.y2, GUI_RED); GrBox(win->titlebar.x, win->titlebar.y, win->titlebar.x2, win->titlebar.y2, GUI_RED); GrBox(win->minimize.x, win->minimize.y, win->minimize.x2, win->minimize.y2, GUI_RED); GrBox(win->maximize.x, win->maximize.y, win->maximize.x2, win->maximize.y2, GUI_RED); // Are we currently dragging? if (dragging) { // Move window to new mouse location. win->base.r.x = event->x - dragOffset.x; win->base.r.y = event->y - dragOffset.y; break; } else { // Dragging. // Did the button just go down? if (event->flags & GR_M_LEFT_DOWN) { // Are we on the topmost window? if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) { //***TODO*** Are we inside the window content? Most likely, check first. if (event->x <= (win->base.r.x + win->base.r.w - 1) && event->x >= win->base.r.x && event->y <= (win->base.r.y + win->base.r.h - 1) && event->y >= win->base.r.y) { //***TODO*** Send to window for processing. } //***TODO*** Are we inside the close button? // Are we inside the title bar to begin dragging? if (event->x <= win->titlebar.x2 && event->x >= win->titlebar.x && event->y <= win->titlebar.y2 && event->y >= win->titlebar.y) { dragging = 1; dragOffset.x = event->x - win->base.r.x; dragOffset.y = event->y - win->base.r.y; break; } //***TODO*** Are we inside the minimize button? //***TODO*** Are we inside the maximize button? } else { // On topmost window. // Not over topmost window. Search backwards to find first window we're inside. i = arrlen(_windowList) - 2; if (i >= 0) { for (; i>=0; i--) { win = _windowList[i]; if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) { // Bring this window forward. arrdel(_windowList, i); arrput(_windowList, win); // If we happened to be in the title bar, go ahead and start dragging. if (event->x <= win->titlebar.x2 && event->x >= win->titlebar.x && event->y <= win->titlebar.y2 && event->y >= win->titlebar.y) { dragging = 1; dragOffset.x = event->x - win->base.r.x; dragOffset.y = event->y - win->base.r.y; } break; } } } } // On topmost window. } // Button just went down. } // Dragging. } else { // Left mouse button. // Left mouse not down. // Can no longer be dragging. dragging = 0; } break; } // Left button processing. } // Do we have windows? } void wmShutdown(void) { while (arrlen(_windowList) > 0) { windowDestroy((WidgetT *)_windowList[0]); } arrfree(_windowList); } void wmStartup(void) { }