#include <axwin3/axwin.h>
#include <axwin3/widget.h>
+#define SIDEBAR_WIDTH 32
+
+// === PROTOTYPES ===
+void create_sidebar(void);
+
// === GLOBALS ===
tHWND gSidebar;
+tAxWin3_Widget *gSidebarRoot;
// === CODE ===
int sidebar_callback(tHWND Window, int Length, void *Data)
// Connect to AxWin3 Server
AxWin3_Connect(NULL);
+ create_sidebar();
+
+ // Idle loop
+ AxWin3_MainLoop();
+
+ return 0;
+}
+
+void create_sidebar(void)
+{
+ tAxWin3_Widget *btn, *txt, *ele;
+
// Create sidebar
- // TODO: Use the widget library instead
// TODO: Get screen dimensions somehow
- gSidebar = AxWin3_Widget_CreateWindow(NULL, 32, 600, 0);
-
+ gSidebar = AxWin3_Widget_CreateWindow(NULL, SIDEBAR_WIDTH, 480, 0);
AxWin3_MoveWindow(gSidebar, 0, 0);
+ gSidebarRoot = AxWin3_Widget_GetRoot(gSidebar);
+
+ // - Main menu
+ btn = AxWin3_Widget_AddWidget(gSidebarRoot, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, "SystemButton");
+ AxWin3_Widget_SetSize(btn, SIDEBAR_WIDTH-4);
+ txt = AxWin3_Widget_AddWidget(btn, ELETYPE_IMAGE, 0, "SystemLogo");
+ AxWin3_Widget_SetText(txt, "file://./AcessLogo.sif");
+ // - Plain <hr/> style spacer
+ ele = AxWin3_Widget_AddWidget(gSidebarRoot, ELETYPE_SPACER, ELEFLAG_NOSTRETCH, "SideBar Spacer Top");
+ AxWin3_Widget_SetSize(ele, 4);
+
+ // TODO: Program list
+ ele = AxWin3_Widget_AddWidget(gSidebarRoot, ELETYPE_BOX, ELEFLAG_VERTICAL, "ProgramList");
+
+ // - Plain <hr/> style spacer
+ ele = AxWin3_Widget_AddWidget(gSidebarRoot, ELETYPE_SPACER, ELEFLAG_NOSTRETCH, "SideBar Spacer Top");
+ AxWin3_Widget_SetSize(ele, 4);
+
+ // > Version/Time
+ txt = AxWin3_Widget_AddWidget(gSidebarRoot, ELETYPE_TEXT, ELEFLAG_NOSTRETCH, "Version String");
+ AxWin3_Widget_SetSize(txt, 20);
+ AxWin3_Widget_SetText(txt, "2.0");
+
// Show!
AxWin3_ShowWindow(gSidebar, 1);
-
- // Idle loop
- AxWin3_MainLoop();
- return 0;
}
DIR := Apps/AxWin/3.0
BIN := AxWinWM
-OBJ := main.o wm.o input.o video.o ipc.o
-OBJ += messageio.o
+OBJ := main.o input.o video.o ipc.o
+OBJ += wm.o wm_render.o
OBJ += renderer_classes.o renderer_passthru.o renderer_background.o
OBJ += renderer_widget.o renderer_widget_decorator.o
// -- Render Cache
short CachedX, CachedY;
short CachedW, CachedH;
-
- char DebugName[];
};
struct sWidgetWin
{
}
// --- IPC Message Handlers ---
+int IPC_Msg_SendMsg(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
+{
+ tIPCMsg_SendMsg *info = (void*)Msg->Data;
+ tWindow *src, *dest;
+
+ // - Sanity checks
+ if( Msg->Size < sizeof(tIPCMsg_SendMsg) )
+ return -1;
+ if( Msg->Size < sizeof(tIPCMsg_SendMsg) + info->Length )
+ return -1;
+
+ src = IPC_int_GetWindow(Client, Msg->Window);
+ if(!src) return 1;
+ dest = IPC_int_GetWindow(Client, info->Dest);
+ if(!dest) return 1;
+
+ WM_SendMessage(src, dest, info->ID, info->Length, info->Data);
+
+ return 0;
+}
+
int IPC_Msg_CreateWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
{
tIPCMsg_CreateWin *info = (void*)Msg->Data;
}
break;
+ // --- Send a message
+ case IPCMSG_SENDMSG:
+ _SysDebug(" IPC_Handle: IPCMSG_SENDMSG %i", ((tIPCMsg_SendMsg*)Msg->Data)->ID);
+ rv = IPC_Msg_SendMsg(client, Msg);
+ break;
+
// --- Create window
case IPCMSG_CREATEWIN:
_SysDebug(" IPC_Handle: IPCMSG_CREATEWIN");
#include <renderer_widget.h>
#include <string.h>
#include <wm_messages.h>
+#include <stdlib.h>
+
+#define DEFAULT_ELETABLE_SIZE 64
// === PROTOTYPES ===
int Renderer_Widget_Init(void);
{
tWindow *ret;
tWidgetWin *info;
- ret = WM_CreateWindowStruct( sizeof(tWidgetWin) );
+ int eletable_size = DEFAULT_ELETABLE_SIZE;
+
+ // TODO: Use `Flags` as default element count?
+
+ ret = WM_CreateWindowStruct( sizeof(tWidgetWin) + sizeof(tElement*)*eletable_size );
info = ret->RendererInfo;
+ info->TableSize = eletable_size;
info->RootElement.BackgroundColour = 0xCCCCCC;
return ret;
void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
{
const int max_debugname_len = Len - sizeof(tWidgetMsg_Create);
- tElement *parent;
+ tElement *parent, *new;
// Sanity check
if( Len < sizeof(tWidgetMsg_Create) )
// Create
parent = Widget_GetElementById(Info, Msg->Parent);
+ if(!parent)
+ {
+ _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
+ return ;
+ }
+
+ // Check if the ID is already in use
+ if( Widget_GetElementById(Info, Msg->NewID) )
+ return ;
+
+ // Create new element
+ new = calloc(sizeof(tElement), 1);
+ new->ID = Msg->NewID;
+ new->Type = Msg->Type;
+ new->Parent = parent;
+ new->Flags = Msg->Flags;
+ new->PaddingT = 2;
+ new->PaddingB = 2;
+ new->PaddingL = 2;
+ new->PaddingR = 2;
+
+ // Add to parent's list
+ if(parent->LastChild)
+ parent->LastChild->NextSibling = new;
+ else
+ parent->FirstChild = new;
+ new->NextSibling = parent->LastChild;
+ parent->LastChild = new;
+
+ // Add to info
+ {
+ tElement *ele, *prev = NULL;
+ for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
+ if(prev)
+ prev->ListNext = new;
+ else
+ Info->ElementTable[new->ID % Info->TableSize] = new;
+ }
+}
+
+void Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg)
+{
+ tElement *ele;
+
+ if( Len < sizeof(tWidgetMsg_SetSize) )
+ return ;
+
+ ele = Widget_GetElementById(Info, Msg->WidgetID);
+ if(!ele) return ;
+
+ ele->FixedWith = Msg->Value;
+}
+
+void Widget_SetText(tWidgetWin *Info, int Len, tWidgetMsg_SetText *Msg)
+{
}
case MSG_WIDGET_CREATE:
Widget_NewWidget(info, Len, Data);
return 0;
+
+ // Set length
+ case MSG_WIDGET_SETSIZE:
+ Widget_SetSize(info, Len, Data);
+ return 0;
+ // Set text
+ case MSG_WIDGET_SETTEXT:
+ Widget_SetText(info, Len, Data);
+ return 0;
+
//
default:
return 1; // Unhandled, pass to user
// Create local framebuffer (back buffer)
gpScreenBuffer = malloc( giScreenWidth*giScreenHeight*4 );
-// memset(gpScreenBufferi
-// Video_FillRect(0, 0, giScreenWidth, giScreenHeight, 0x8080FF);
// Set cursor position and bitmap
ioctl(giTerminalFD, TERM_IOCTL_SETCURSORBITMAP, &cCursorBitmap);
Video_SetCursorPos( giScreenWidth/2, giScreenHeight/2 );
-
- Video_Update();
}
void Video_Update(void)
Video_Update();
}
-// --- WM Render Routines
-// TODO: Move to another file?
-void WM_Render_FillRect(tWindow *Window, int X, int Y, int W, int H, tColour Colour)
-{
- uint32_t *dest;
- int i;
-// _SysDebug("WM_Render_FilledRect(%p, 0x%x...", Window, Colour);
-// _SysDebug(" (%i,%i), %ix%i)", X, Y, W, H);
- // Clip to window dimensions
- if(X < 0) { W += X; X = 0; }
- if(Y < 0) { H += Y; Y = 0; }
- if(X >= Window->W) return;
- if(Y >= Window->H) return;
- if(X + W > Window->W) W = Window->W - X;
- if(Y + H > Window->H) H = Window->H - Y;
-// _SysDebug(" Clipped to (%i,%i), %ix%i", X, Y, W, H);
-
- // Render to buffer
- // Create if needed?
-
- if(!Window->RenderBuffer) {
- Window->RenderBuffer = malloc(Window->W*Window->H*4);
- }
-
- dest = (uint32_t*)Window->RenderBuffer + Y*Window->W + X;
- while( H -- )
- {
- for( i = W; i --; )
- *dest++ = Colour;
- dest += Window->W - 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
- _SysDebug("WM_Render_DrawText - 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;
- }
-}
-
struct sIPCMsg_SendMsg
{
uint32_t Dest;
- int ID;
+ uint16_t ID;
uint16_t Length;
char Data[];
};
enum
{
- MSG_WIDGET_CREATE,
+ MSG_WIDGET_CREATE = 0x1000,
MSG_WIDGET_DELETE,
- MSG_WIDGET_SETTEXT
+ MSG_WIDGET_SETSIZE,
+ MSG_WIDGET_SETTEXT,
+ MSG_WIDGET_SETCOLOUR
};
{
uint32_t Parent;
uint32_t NewID;
+ uint32_t Type;
+ uint32_t Flags;
char DebugName[];
} tWidgetMsg_Create;
+typedef struct
+{
+ uint32_t WidgetID;
+} tWidgetMsg_Delete;
+
+typedef struct
+{
+ uint32_t WidgetID;
+ uint32_t Value;
+} tWidgetMsg_SetSize;
+
+typedef struct
+{
+ uint32_t WidgetID;
+ char Text[];
+} tWidgetMsg_SetText;
+
+typedef struct
+{
+ uint32_t WidgetID;
+ uint32_t Index;
+ uint32_t Colour;
+} tWidgetMsg_SetColour;
+
#endif
#include "include/internal.h"
#include <stdlib.h>
#include <widget_messages.h>
+#include <string.h>
// === STRUCTURES ===
struct sAxWin3_Widget
int nElements;
tAxWin3_Widget **Elements;
int FirstFreeID;
+ tAxWin3_Widget RootElement;
// Callbacks for each element
} tWidgetWindowInfo;
);
info = AxWin3_int_GetDataPtr(ret);
- info->nElements = 1;
- info->Elements = malloc(sizeof(tAxWin3_Widget*));
- info->Elements[0] = (void*)(info + 1); // Get end of *info
- info->FirstFreeID = 1;
+ info->RootElement.Window = ret;
+ info->RootElement.ID = -1;
AxWin3_ResizeWindow(ret, W, H);
tAxWin3_Widget *AxWin3_Widget_GetRoot(tHWND Window)
{
tWidgetWindowInfo *info = AxWin3_int_GetDataPtr(Window);
- return info->Elements[0];
+ return &info->RootElement;
}
tAxWin3_Widget *AxWin3_Widget_AddWidget(tAxWin3_Widget *Parent, int Type, int Flags, const char *DebugName)
if( info->Elements[newID] == NULL )
break;
}
- if( info->Elements[newID] )
+ if( info->nElements == 0 || info->Elements[newID] )
{
info->nElements ++;
info->Elements = realloc(info->Elements, sizeof(*info->Elements)*info->nElements);
return ret;
}
+
+void AxWin3_Widget_DelWidget(tAxWin3_Widget *Widget)
+{
+ tWidgetMsg_Delete msg;
+ tWidgetWindowInfo *info = AxWin3_int_GetDataPtr(Widget->Window);
+
+ msg.WidgetID = Widget->ID;
+ AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_DELETE, sizeof(msg), &msg);
+
+ info->Elements[Widget->ID] = NULL;
+ if(Widget->ID < info->FirstFreeID)
+ info->FirstFreeID = Widget->ID;
+ free(Widget);
+}
+
+void AxWin3_Widget_SetSize(tAxWin3_Widget *Widget, int Size)
+{
+ tWidgetMsg_SetSize msg;
+
+ msg.WidgetID = Widget->ID;
+ msg.Value = Size;
+ AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETSIZE, sizeof(msg), &msg);
+}
+
+void AxWin3_Widget_SetText(tAxWin3_Widget *Widget, const char *Text)
+{
+ char buf[sizeof(tWidgetMsg_SetText) + strlen(Text) + 1];
+ tWidgetMsg_SetText *msg = (void*)buf;
+
+ msg->WidgetID = Widget->ID;
+ strcpy(msg->Text, Text);
+
+ AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETTEXT, sizeof(buf), buf);
+}
+
+void AxWin3_Widget_SetColour(tAxWin3_Widget *Widget, int Index, tAxWin3_Colour Colour)
+{
+ tWidgetMsg_SetColour msg;
+
+ msg.WidgetID = Widget->ID;
+ msg.Index = Index;
+ msg.Colour = Colour;
+ AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETCOLOUR, sizeof(msg), &msg);
+}
void *AxWin3_int_GetDataPtr(tHWND Window)
{
- return &Window->Data;
+ return Window->Data;
}
void AxWin3_SendMessage(tHWND Window, tHWND Destination, int Message, int Length, void *Data)
msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SENDMSG, 0, sizeof(*info)+Length);
info = (void*)msg->Data;
info->Dest = AxWin3_int_GetWindowID(Destination);
+ info->ID = Message;
+ info->Length = Length;
+ memcpy(info->Data, Data, Length);
+
+ AxWin3_int_SendIPCMessage(msg);
+ free(msg);
}
void AxWin3_ShowWindow(tHWND Window, int bShow)