int Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data);
// === CONSTANTS ===
+#define BTN_CLOSE(win) win->W-16, -16, 14, 14
+#define BTN_MIN(win) win->W-32, -16, 14, 14
tColour cColourActive_Titlebar = 0x00CC44;
tColour cColourActive_TitleText = 0x000000;
tColour cColourInactive_Titlebar = 0xD0D0D0;
tColour cColour_TitleTopBorder = 0xFFFFFF;
tColour cColour_SideBorder = 0x008000;
tColour cColour_BottomBorder = 0x008000;
+tColour cColour_CloseBtn = 0xFF1100;
int ciTitlebarHeight = 18;
int ciSideBorderWidth = 2;
int ciBottomBorderWidth = 4;
);
// Buttons
+ WM_Render_FillRect(Window, BTN_CLOSE(Window), cColour_CloseBtn);
// TODO: Conditional for each
}
+static inline int Decorator_INT_CoordInRange(int X, int Y, int SX, int SY, int EX, int EY)
+{
+ _SysDebug("(%i<=%i<%i, %i<=%i<%i", SX, X, EX, SY, Y, EY);
+ return (X >= SX && X < EX && Y >= SY && Y < EY);
+}
+static inline int Decorator_INT_CoordInRangeR(int X, int Y, int SX, int SY, int W, int H)
+{
+ return Decorator_INT_CoordInRange(X, Y, SX, SY, SX+W, SY+H);
+}
+
int Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data)
{
static tWindow *btn1_down;
+ static enum {
+ BTN1_MOVE,
+ BTN1_RLEFT,
+ BTN1_RRIGHT,
+ BTN1_RBOTTOM,
+ } btn1_mode;
switch(Message)
{
case WNDMSG_MOUSEMOVE: {
const struct sWndMsg_MouseMove *msg = Data;
- if( btn1_down == Window ) {
- WM_MoveWindow(Window, Window->X + msg->dX, Window->Y + msg->dY);
+ if( btn1_down == Window )
+ {
+ switch(btn1_mode)
+ {
+ case BTN1_MOVE: // Move
+ WM_MoveWindow(Window, Window->X + msg->dX, Window->Y + msg->dY);
+ break;
+ case BTN1_RLEFT: // Resize left
+ if( Window->W + msg->dX > 50 )
+ {
+ WM_MoveWindow(Window, Window->X + msg->dX, Window->Y);
+ WM_ResizeWindow(Window, Window->W - msg->dX, Window->H);
+ }
+ break;
+ case BTN1_RRIGHT: // Resize right
+ if( Window->W + msg->dX > 50 )
+ {
+ WM_ResizeWindow(Window, Window->W + msg->dX, Window->H);
+ }
+ break;
+ case BTN1_RBOTTOM: // Resize bottom
+ if( Window->H + msg->dY > 50 )
+ {
+ WM_ResizeWindow(Window, Window->W, Window->H + msg->dY);
+ }
+ break;
+ }
return 0;
}
+ // TODO: Change cursor when hovering over edges
+
if(msg->Y >= 0) return 1; // Pass
// TODO: Handle
return 0; }
case WNDMSG_MOUSEBTN: {
const struct sWndMsg_MouseButton *msg = Data;
- if( msg->Button == 0 && !msg->bPressed )
+
+ // TODO: Do something with other buttons
+ // - Window menu for example
+ if( msg->Button != 0 )
+ return 1; // pass on
+
+ if( !msg->bPressed )
btn1_down = 0;
- if(msg->Y >= 0) return 1; // Pass
-
- if( msg->Button == 0 && msg->bPressed )
+ #define HOTSPOTR(x,y,w,h) Decorator_INT_CoordInRangeR(msg->X, msg->Y, x, y, w, h)
+ #define HOTSPOTA(sx,sy,ex,ey) Decorator_INT_CoordInRange(msg->X, msg->Y, sx, sy, ew, eh)
+ // Left resize border
+ if( msg->bPressed && HOTSPOTR(-ciSideBorderWidth, -ciTitlebarHeight,
+ ciSideBorderWidth, ciTitlebarHeight+Window->H+ciBottomBorderWidth) )
+ {
btn1_down = Window;
+ btn1_mode = BTN1_RLEFT;
+ return 0;
+ }
+ // Right resize border
+ if( msg->bPressed && HOTSPOTR(Window->W, -ciTitlebarHeight,
+ ciSideBorderWidth, ciTitlebarHeight+Window->H+ciBottomBorderWidth) )
+ {
+ btn1_down = Window;
+ btn1_mode = BTN1_RRIGHT;
+ return 0;
+ }
+ // Bottom resize border
+ if( msg->bPressed && HOTSPOTR(0, Window->H,
+ Window->W, ciTitlebarHeight) )
+ {
+ btn1_down = Window;
+ btn1_mode = BTN1_RBOTTOM;
+ return 0;
+ }
+ // Titlebar buttons
+ if( msg->bPressed && Decorator_INT_CoordInRangeR(msg->X, msg->Y, BTN_CLOSE(Window)) )
+ {
+ WM_SendMessage(NULL, Window, WNDMSG_CLOSE, 0, NULL);
+ return 0;
+ }
+ // Titlebar - Move
+ if( msg->bPressed && msg->Y < 0 )
+ {
+ btn1_down = Window;
+ btn1_mode = BTN1_MOVE;
+ return 0;
+ }
+ #undef HOTSPOTR
+ #undef HOTSPOTA
- // TODO: Handle
- return 0; }
+ return 1; }
default: // Anything unhandled is passed on
return 1;
}
// === PROTOTYPES ===
int Renderer_RichText_Init(void);
tWindow *Renderer_RichText_Create(int Flags);
+void Renderer_RichText_Destroy(tWindow *Window);
void Renderer_RichText_Redraw(tWindow *Window);
int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data);
int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data);
tWMRenderer gRenderer_RichText = {
.Name = "RichText",
.CreateWindow = Renderer_RichText_Create,
+ .DestroyWindow = Renderer_RichText_Destroy,
.Redraw = Renderer_RichText_Redraw,
.HandleMessage = Renderer_RichText_HandleMessage,
.nIPCHandlers = N_IPC_RICHTEXT,
return ret;
}
+void Renderer_RichText_Destroy(tWindow *Window)
+{
+ tRichText_Window *info = ret->RendererInfo;
+
+ // TODO: Is locking needed? WM_Destroy should have taken us off the render tree
+ while( info->FirstLine )
+ {
+ tRichText_Line *line = info->FirstLine;
+ info->FirstLine = line->Next;
+
+ free(line);
+ }
+
+ if( info->Font )
+ _SysDebug("RichText_Destroy - TODO: Free font");
+}
+
static inline int Renderer_RichText_RenderText_Act(tWindow *Window, tRichText_Window *info, int X, int Row, const char *Text, int Bytes, tColour FG, tColour BG, int Flags)
{
int rwidth;
// - Remove from inheritance tree?
// - Clean up render children
- // Lock should not be needed
- tWindow *win, *next;
- for( win = Window->FirstChild; win; win = next )
{
- next = win->NextSibling;
- ASSERT(Window->FirstChild->Parent == Window);
- WM_DestroyWindow(win);
+ // Lock should not be needed
+ tWindow *win, *next;
+ for( win = Window->FirstChild; win; win = next )
+ {
+ next = win->NextSibling;
+ ASSERT(Window->FirstChild->Parent == Window);
+ WM_DestroyWindow(win);
+ }
}
// - Clean up inheriting children?
Window->Renderer->DestroyWindow(Window);
else
_SysDebug("WARN: Renderer %s does not have a destroy function", Window->Renderer->Name);
-
+
+ // - Tell client to clean up
+ WM_SendMessage(NULL, Window, WNDMSG_DESTROY, 0, NULL);
+
// - Clean up render cache and window structure
free(Window->Title);
free(Window->RenderBuffer);
if( Window->W == W && Window->H == H )
return 0;
- _SysDebug("WM_Resizeindow: %ix%i", W, H);
+ _SysDebug("WM_ResizeWindow: %ix%i", W, H);
Window->W = W; Window->H = H;
if(Window->RenderBuffer) {