From: John Hodge Date: Sat, 5 Nov 2011 09:44:44 +0000 (+0800) Subject: Usermode/AxWin3 - Adding decorator to widget renderer X-Git-Tag: rel0.14~143 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=7f1cbeafb4acc13d0cc7c11ac47df3efe473c106;p=tpg%2Facess2.git Usermode/AxWin3 - Adding decorator to widget renderer TODO: Implement inter-window messaging, needed to get the new size for the element calculations --- diff --git a/Usermode/Applications/axwin3_src/WM/Makefile b/Usermode/Applications/axwin3_src/WM/Makefile index 5afff6f0..83544130 100644 --- a/Usermode/Applications/axwin3_src/WM/Makefile +++ b/Usermode/Applications/axwin3_src/WM/Makefile @@ -8,7 +8,8 @@ DIR := Apps/AxWin/3.0 BIN := AxWinWM OBJ := main.o wm.o input.o video.o ipc.o OBJ += messageio.o -OBJ += renderer_classes.o renderer_passthru.o renderer_widget.o renderer_background.o +OBJ += renderer_classes.o renderer_passthru.o renderer_background.o +OBJ += renderer_widget.o renderer_widget_decorator.o LDFLAGS += -limage_sif -luri -lnet diff --git a/Usermode/Applications/axwin3_src/WM/include/renderer_widget.h b/Usermode/Applications/axwin3_src/WM/include/renderer_widget.h index 35b767d2..700540d5 100644 --- a/Usermode/Applications/axwin3_src/WM/include/renderer_widget.h +++ b/Usermode/Applications/axwin3_src/WM/include/renderer_widget.h @@ -13,5 +13,60 @@ #include +// === TYPES === +typedef struct sWidgetWin tWidgetWin; +typedef struct sAxWin_Element tElement; + +// === STRUCTURES === +struct sAxWin_Element +{ + enum eElementTypes Type; + + uint32_t ID; //!< Application provided ID number + tElement *ListNext; //!< Next element in bucket + + // Element Tree + tElement *Parent; + tElement *FirstChild; + tElement *LastChild; + tElement *NextSibling; + + // User modifiable attributes + short PaddingL, PaddingR; + short PaddingT, PaddingB; + short GapSize; + + uint32_t Flags; + + short FixedWith; //!< Fixed lengthways Size attribute (height) + short FixedCross; //!< Fixed Cross Size attribute (width) + + tColour BackgroundColour; + + char *Text; + + // -- Attributes maitained by the element code + // Not touched by the user + short MinWith; //!< Minimum long size + short MinCross; //!< Minimum cross size + void *Data; //!< Per-type data + + // -- Render Cache + short CachedX, CachedY; + short CachedW, CachedH; + + char DebugName[]; +}; +struct sWidgetWin +{ + tElement RootElement; + + int TableSize; //!< Number of entries, anything over will wrap + tElement *ElementTable[]; //!< Hash table essentially +}; + +// === FUNCTIONS === +extern void Widget_Decorator_RenderWidget(tWindow *Window, tElement *Element); + #endif diff --git a/Usermode/Applications/axwin3_src/WM/include/wm.h b/Usermode/Applications/axwin3_src/WM/include/wm.h index 2766c68d..a96061e2 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm.h @@ -8,6 +8,8 @@ #ifndef _WM_H_ #define _WM_H_ +#include + // === CONSTANTS === /** * \brief Window Flags @@ -40,7 +42,10 @@ extern int WM_ResizeWindow(tWindow *Window, int W, int H); extern int WM_MoveWindow(tWindow *Window, int X, int Y); extern int WM_SendMessage(tWindow *Window, int MessageID, int Length, void *Data); // --- Rendering -extern void WM_Render_FilledRect(tWindow *Window, tColour Colour, int X, int Y, int W, int H); +extern void WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour); +extern void WM_Render_DrawRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour); +extern void WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, void *Font, tColour Colour, const char *Text); +extern void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Image); #endif diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_messages.h b/Usermode/Applications/axwin3_src/WM/include/wm_messages.h index 0bebfdad..d37097ff 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_messages.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_messages.h @@ -8,6 +8,9 @@ #ifndef _WM_MESSAGES_H_ #define _WM_MESSAGES_H_ +/** + * \brief Messages delivered to windows + */ enum eWM_WindowMessages { WNDMSG_NULL, @@ -16,6 +19,8 @@ enum eWM_WindowMessages WNDMSG_DESTROY, WNDMSG_FOCUS, // Called on change WNDMSG_SHOW, // Called on change + + WNDMSG_RESIZE, WNDMSG_MOUSEMOVE, WNDMSG_MOUSEBTN, @@ -27,4 +32,9 @@ enum eWM_WindowMessages WNDMSG_CLASS_MAX = 0x2000, }; +struct sWndMsg_Resize +{ + uint16_t W, H; +}; + #endif diff --git a/Usermode/Applications/axwin3_src/WM/renderer_background.c b/Usermode/Applications/axwin3_src/WM/renderer_background.c index df28c833..7772cddb 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_background.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_background.c @@ -51,7 +51,7 @@ void Renderer_Background_Redraw(tWindow *Window) { struct sBgWin *info = Window->RendererInfo; - WM_Render_FilledRect(Window, info->Colour, 0, 0, 0xFFFF, 0xFFFF); + WM_Render_FillRect(Window, 0, 0, 0xFFFF, 0xFFFF, info->Colour); } int Renderer_Background_HandleMessage(tWindow *Target, int Msg, int Len, void *Data) diff --git a/Usermode/Applications/axwin3_src/WM/renderer_classes.c b/Usermode/Applications/axwin3_src/WM/renderer_classes.c index 439adaae..4b0f3c61 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_classes.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_classes.c @@ -44,7 +44,7 @@ tWindow *Renderer_Class_Create(int Flags) void Renderer_Class_Redraw(tWindow *Window) { tClassfulInfo *info = Window->RendererInfo; - WM_Render_FilledRect(Window, info->BGColour, 0, 0, Window->W, Window->H); + WM_Render_FillRect(Window, 0, 0, Window->W, Window->H, info->BGColour); } int Renderer_Class_HandleMessage(tWindow *Target, int Msg, int Len, void *Data) diff --git a/Usermode/Applications/axwin3_src/WM/renderer_widget.c b/Usermode/Applications/axwin3_src/WM/renderer_widget.c index 3fbe3cb7..00debedc 100644 --- a/Usermode/Applications/axwin3_src/WM/renderer_widget.c +++ b/Usermode/Applications/axwin3_src/WM/renderer_widget.c @@ -10,62 +10,16 @@ #include #include -// === TYPES === -typedef struct sWidgetWin tWidgetWin; -typedef struct sAxWin_Element tElement; - -// === STRUCTURES === -struct sAxWin_Element -{ - enum eElementTypes Type; - - uint32_t ID; //!< Application provided ID number - tElement *ListNext; //!< Next element in bucket - - // Element Tree - tElement *Parent; - tElement *FirstChild; - tElement *LastChild; - tElement *NextSibling; - - // User modifiable attributes - short PaddingL, PaddingR; - short PaddingT, PaddingB; - short GapSize; - - uint32_t Flags; - - short FixedWith; //!< Fixed lengthways Size attribute (height) - short FixedCross; //!< Fixed Cross Size attribute (width) - - tColour BackgroundColour; - - char *Text; - - // -- Attributes maitained by the element code - // Not touched by the user - short MinWith; //!< Minimum long size - short MinCross; //!< Minimum cross size - void *Data; //!< Per-type data - - // -- Render Cache - short CachedX, CachedY; - short CachedW, CachedH; - - char DebugName[]; -}; -struct sWidgetWin -{ - tElement RootElement; - - int TableSize; //!< Number of entries, anything over will wrap - tElement *ElementTable[]; //!< Hash table essentially -}; - // === PROTOTYPES === + int Renderer_Widget_Init(void); tWindow *Renderer_Widget_Create(int Flags); void Renderer_Widget_Redraw(tWindow *Window); -int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data); +void Widget_RenderWidget(tWindow *Window, tElement *Element); + int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data); +void Widget_UpdateDimensions(tElement *Element); +void Widget_UpdatePosition(tElement *Element); +tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID); +void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg); // === GLOBALS === tWMRenderer gRenderer_Widget = { @@ -98,10 +52,30 @@ tWindow *Renderer_Widget_Create(int Flags) void Renderer_Widget_Redraw(tWindow *Window) { tWidgetWin *info = Window->RendererInfo; - WM_Render_FilledRect(Window, info->RootElement.BackgroundColour, 0, 0, 0xFFF, 0xFFF); + WM_Render_FillRect(Window, 0, 0, 0xFFF, 0xFFF, info->RootElement.BackgroundColour); + + Widget_UpdateDimensions(&info->RootElement); + Widget_UpdatePosition(&info->RootElement); + + Widget_RenderWidget(Window, &info->RootElement); } // --- Render / Resize --- +void Widget_RenderWidget(tWindow *Window, tElement *Element) +{ + tElement *child; + + if( Element->Flags & ELEFLAG_NORENDER ) return ; + if( Element->Flags & ELEFLAG_INVISIBLE ) return ; + + Widget_Decorator_RenderWidget(Window, Element); + + for(child = Element->FirstChild; child; child = child->NextSibling) + { + Widget_RenderWidget(Window, child); + } +} + void Widget_UpdateDimensions(tElement *Element) { tElement *child; @@ -267,6 +241,9 @@ void Widget_UpdatePosition(tElement *Element) tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID) { tElement *ele; + + if(ID == -1) + return &Info->RootElement; if( ID < Info->TableSize ) return Info->ElementTable[ID]; @@ -297,6 +274,14 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data) tWidgetWin *info = Target->RendererInfo; switch(Msg) { + case WNDMSG_RESIZE: { + struct sWndMsg_Resize *msg = Data; + if(Len < sizeof(*msg)) return -1; + + info->RootElement.CachedW = msg->W; + info->RootElement.CachedH = msg->H; + return 0; } + // New Widget case MSG_WIDGET_CREATE: Widget_NewWidget(info, Len, Data); diff --git a/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c b/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c new file mode 100644 index 00000000..ec70a565 --- /dev/null +++ b/Usermode/Applications/axwin3_src/WM/renderer_widget_decorator.c @@ -0,0 +1,121 @@ +/* + * Acess2 Window Manager v3 + * - By John Hodge (thePowersGang) + * + * renderer_widget_decorator.c + * - Widget Decorator + */ +#include +#include +#include + +#define BORDER_EVERYTHING 1 + +#define BOX_BGCOLOUR 0xC0C0C0 +#define BOX_BORDER 0xA0A0A0 +#define BUTTON_BGCOLOUR 0xD0D0D0 +#define BUTTON_BORDER 0xF0F0F0 +#define TEXT_COLOUR 0x000000 + +// === CODE === +void Widget_Decorator_RenderWidget(tWindow *Window, tElement *Element) +{ + _SysDebug("Widget_Decorator_RenderWidget: (Element={Type:%i,(%i,%i) %ix%i})", + Element->Type, + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH + ); + + #if BORDER_EVERYTHING + WM_Render_DrawRect( + Window, + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH, + 0 + ); + #endif + + switch(Element->Type) + { + case ELETYPE_NONE: + case ELETYPE_BOX: break; // Box is a meta-element + + case ELETYPE_TABBAR: // Tab Bar + WM_Render_DrawRect( + Window, + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH, + BOX_BORDER + ); + WM_Render_FillRect( + Window, + Element->CachedX+1, Element->CachedY+1, + Element->CachedW-2, Element->CachedH-2, + BOX_BGCOLOUR + ); + // Enumerate Items. + break; + case ELETYPE_TOOLBAR: // Tool Bar + WM_Render_DrawRect( + Window, + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH, + BOX_BORDER + ); + WM_Render_FillRect( + Window, + Element->CachedX+1, Element->CachedY+1, + Element->CachedW-2, Element->CachedH-2, + BOX_BGCOLOUR + ); + break; + + case ELETYPE_SPACER: // Spacer (subtle line) + WM_Render_FillRect( + Window, + Element->CachedX+3, Element->CachedY+3, + Element->CachedW-6, Element->CachedH-6, + BOX_BORDER + ); + break; + + case ELETYPE_BUTTON: // Button + WM_Render_FillRect( + Window, + Element->CachedX+1, Element->CachedY+1, + Element->CachedW-2, Element->CachedH-2, + BUTTON_BGCOLOUR + ); + WM_Render_DrawRect( + Window, + Element->CachedX, Element->CachedY, + Element->CachedW-1, Element->CachedH-1, + BUTTON_BORDER + ); + break; + + case ELETYPE_TEXT: + WM_Render_DrawText( + Window, + Element->CachedX+1, Element->CachedY+1, + Element->CachedW-2, Element->CachedH-2, + NULL, + TEXT_COLOUR, + Element->Text + ); + break; + + case ELETYPE_IMAGE: + WM_Render_DrawImage( + Window, + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH, + Element->Data + ); + break; + + default: + _SysDebug(" ERROR: Unknown type %i", Element->Type); + break; + } +} diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index b40d1c61..eddd12de 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -201,7 +201,7 @@ void WM_Update(void) // --- WM Render Routines // TODO: Move to another file? -void WM_Render_FilledRect(tWindow *Window, tColour Colour, int X, int Y, int W, int H) +void WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour) { uint32_t *dest; int i; @@ -232,3 +232,107 @@ void WM_Render_FilledRect(tWindow *Window, tColour Colour, int X, int Y, int W, } } +void WM_Render_DrawRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour) +{ + WM_Render_FillRect(Window, X, Y, W, 1, Colour); + WM_Render_FillRect(Window, X, Y+H-1, W, 1, Colour); + WM_Render_FillRect(Window, X, Y, 1, H, Colour); + WM_Render_FillRect(Window, X+W-1, Y, 1, H, Colour); +} + +void WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, void *Font, tColour Colour, const char *Text) +{ + // TODO: Implement +} + +/** + * \brief Draw an image to the screen + * \todo Maybe have support for an offset in the image + */ +void WM_Render_DrawImage(tWindow *Window, int X, int Y, int W, int H, tImage *Image) +{ + int x, y; + uint32_t *dest; + uint8_t *data; + + // Sanity please + if( !Image ) return ; + + // Allocate + if(!Window->RenderBuffer) { + Window->RenderBuffer = malloc(Window->W*Window->H*4); + } + + // Bounds Check + if( X >= Window->W ) return ; + if( Y >= Window->H ) return ; + + // Wrap to image size + if( W > Image->Width ) W = Image->Width; + if( H > Image->Height ) H = Image->Height; + + // Wrap to screen size + if( X + W > Window->W ) W = Window->W - X; + if( Y + H > Window->H ) H = Window->H - Y; + + dest = (uint32_t*)Window->RenderBuffer + Y * Window->W + X; + data = Image->Data; + + // Do the render + switch( Image->Format ) + { + case IMGFMT_BGRA: + for( y = 0; y < H; y ++ ) + { + int r, g, b, a; // New + int or, og, ob; // Original + for( x = 0; x < W; x ++ ) + { + b = data[x*4+0]; g = data[x*4+1]; r = data[x*4+2]; a = data[x*4+3]; + if( a == 0 ) continue; // 100% transparent + ob = dest[x]&0xFF; og = (dest[x] >> 8)&0xFF; or = (dest[x] >> 16)&0xFF; + // Handle Alpha + switch(a) + { + // Transparent: Handled above + // Solid + case 0xFF: break; + // Half + case 0x80: + r = (or + r) / 2; + g = (og + g) / 2; + b = (ob + b) / 2; + break; + // General + default: + r = (or * (255-a) + r * a) / 255; + g = (og * (255-a) + g * a) / 255; + b = (ob * (255-a) + b * a) / 255; + break; + } + dest[x] = b | (g << 8) | (r << 16); + } + data += Image->Width * 4; + dest += Window->W; + } + break; + + // RGB + case IMGFMT_RGB: + for( y = 0; y < H; y ++ ) + { + for( x = 0; x < W; x ++ ) + { + // Blue Green Red + dest[x] = data[x*3+2] | (data[x*3+1] << 8) | (data[x*3+0] << 16); + } + data += W * 3; + dest += Window->W; + } + break; + default: + _SysDebug("ERROR: Unknown image format %i\n", Image->Format); + break; + } +} +