#include "vn_workspace_view.cpp"
#include "vn_workspace_editor.cpp"
#include "vn_workspace_text_editor.cpp"
#include "vn_workspace_character_editor.cpp"
#include "vn_workspace_commands.cpp"

//- sixten: State management
per_thread workspace *ThreadLocal_Workspace;

static workspace_keybind Workspace_Keybinds[] =
{
    {Key_P, PlatformModifier_Ctrl, W_Command_SplitPanelHorizontal},
    {Key_L, PlatformModifier_Ctrl, W_Command_SplitPanelVertical},
    
    {Key_O, PlatformModifier_Ctrl, W_Command_OpenView, W_View_TextEditor},
    {Key_T, PlatformModifier_Ctrl, W_Command_Test},
    
#if VN_INTERNAL
    {Key_U, PlatformModifier_Ctrl|PlatformModifier_Shift, W_Command_ToggleRenderUIDebugRects},
#endif
};

static void W_SetState(workspace *Workspace)
{
    ThreadLocal_Workspace = Workspace;
}

static workspace *W_GetState(void)
{
    return(ThreadLocal_Workspace);
}

static memory_arena *W_FrameArena(void)
{
    return(ThreadLocal_Workspace->FrameArena);
}

//- sixten: Commands
static void W_IssueCommand(workspace_command_sig *Sig, u64 Argument = 0)
{
    workspace_command *Result = 0;
    
    workspace *Workspace = W_GetState();
    
    if(Workspace->FirstFreeCommand)
    {
        Result = Workspace->FirstFreeCommand;
        DLLRemove(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, Result);
    }
    
    if(!Result)
    {
        Result = PushStruct(Workspace->CommandArena, workspace_command);
    }
    
    Result->Command = Sig;
    Result->Argument = Argument;
    DLLInsertLast(Workspace->FirstCommand, Workspace->LastCommand, Result);
}

static void W_ProcessCommands(void)
{
    workspace *Workspace = W_GetState();
    
    workspace_command *Command = Workspace->FirstCommand;
    while(Command != 0)
    {
        Command->Command(Command->Argument);
        
        workspace_command *ToRemove = Command;
        Command = Command->Next;
        
        DLLRemove(Workspace->FirstCommand, Workspace->LastCommand, ToRemove);
        Fill(ToRemove, 0, sizeof(workspace_command));
        DLLInsertLast(Workspace->FirstFreeCommand, Workspace->LastFreeCommand, ToRemove);
    }
}

static void W_ProcessKeyBinds()
{
    workspace *Workspace = W_GetState();
    
    platform_event_list *EventList = Workspace->EventList;
    
    for(platform_event *Event = EventList->First;
        Event != 0;
        Event = Event->Next)
    {
        if(Event->Type == PlatformEvent_Press)
        {
            for(s32 KeybindIndex = 0;
                KeybindIndex < ArrayCount(Workspace_Keybinds);
                ++KeybindIndex)
            {
                workspace_keybind *Keybind = Workspace_Keybinds + KeybindIndex;
                if((Event->Key == Keybind->Key) && (Event->Modifiers == Keybind->Modifiers))
                {
                    W_IssueCommand(Keybind->Command, Keybind->Argument);
                }
            }
        }
    }
}


//- sixten: Builder code
static ui_signal W_BuildToolbarButton(char *Text, toolbar_menu Menu)
{
    workspace *Workspace = W_GetState();
    
    UI_SetNextWidth(UI_TextContent(20, 1));
    UI_SetNextHeight(UI_Pixels(30, 1));
    UI_SetNextCornerRadius(4);
    UI_SetNextBackgroundColor(ColorFromHex(0x252728FF));
    
    ui_box *Box = UI_MakeBoxF(UI_BoxFlag_DrawBackground   |
                              UI_BoxFlag_DrawBorder       |
                              UI_BoxFlag_DrawText         | 
                              UI_BoxFlag_HotAnimation     |
                              UI_BoxFlag_ActiveAnimation  |
                              UI_BoxFlag_Clickable,
                              Text);
    
    ui_signal Signal = UI_SignalFromBox(Box);
    
    if(Workspace->Menu == ToolbarMenu_None)
    {
        if(Signal.Clicked)
        {
            Workspace->Menu = Menu;
            Workspace->MenuTransition = 0;
        }
    }
    else
    {
        if(Signal.Hovering)
        {
            if(Workspace->Menu != Menu)
            {
                Workspace->MenuTransition = 0;
            }
            
            Workspace->Menu = Menu;
            Workspace->MenuP = V2(Box->Rect.Min.x, Box->Rect.Max.y);
        }
    }
    
    return(Signal);
}

static ui_signal W_BuildMenuItem(u32 Icon, char *Text, char *Shortcut)
{
    temporary_memory Scratch = GetScratch(0, 0);
    
    UI_SetNextLayoutAxis(Axis2_X);
    UI_SetNextHoverCursor(PlatformCursor_Hand);
    
    ui_box *Box = UI_MakeBoxF(UI_BoxFlag_DrawBackground  |
                              UI_BoxFlag_DrawBorder      |
                              UI_BoxFlag_HotAnimation    |
                              UI_BoxFlag_ActiveAnimation |
                              UI_BoxFlag_Clickable,
                              "Menu Item %s", Text);
    
    UI_Parent(Box)
    {
        UI_Width(UI_Pixels(25, 1)) UI_Font(Font_Icons) UI_MakeBoxF(UI_BoxFlag_DrawText, "%U", Icon);
        UI_Width(UI_TextContent(5, 1)) UI_MakeBoxF(UI_BoxFlag_DrawText, Text);
        UI_Spacer(UI_Percent(1, 0));
        
        UI_TextColor(V4(0.5, 0.5, 0.5, 1.0)) UI_Width(UI_TextContent(15, 1))
            UI_MakeBoxF(UI_BoxFlag_DrawText, Shortcut);
    }
    
    ReleaseScratch(Scratch);
    
    ui_signal Signal = UI_SignalFromBox(Box);
    return(Signal);
}

static void W_BuildToolbar()
{
    workspace *Workspace = W_GetState();
    
    UI_SetNextLayoutAxis(Axis2_X);
    UI_SetNextHeight(UI_Pixels(30, 1));
    UI_SetNextBackgroundColor(Theme_BackgroundColor);
    
    ui_box *ToolbarBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder,
                                     "Workspace Toolbar");
    
    UI_Parent(ToolbarBox)
    {
        W_BuildToolbarButton("Panel",  ToolbarMenu_Panel);
        W_BuildToolbarButton("View",   ToolbarMenu_View);
        W_BuildToolbarButton("Window", ToolbarMenu_Window);
    }
    
    if(Workspace->Menu != ToolbarMenu_None)
    {
        r32 MenuTransition = Workspace->MenuTransition;
        
        UI_SetNextTooltip();
        UI_SetNextFixedX(Workspace->MenuP.x);
        UI_SetNextFixedY(Workspace->MenuP.y);
        UI_SetNextLayoutAxis(Axis2_Y);
        UI_SetNextWidth(UI_Pixels(250, 1));
        UI_SetNextHeight(UI_ChildrenSum(MenuTransition, 1));
        ui_box *Dropdown = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
                                       UI_BoxFlag_DrawDropShadow |
                                       UI_BoxFlag_Clip           |
                                       UI_BoxFlag_FloatingX      |
                                       UI_BoxFlag_FloatingY,
                                       "Workspace Dropdown");
        
        UI_Parent(Dropdown)
            UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1))
            UI_BorderColor(V4(0.45, 0.45, 0.45, 1))
            UI_CornerRadius(2)
            UI_Size(UI_Percent(1, 1), UI_Pixels(25, 1))
        {
            if(Workspace->Menu == ToolbarMenu_Panel)
            {
                if(W_BuildMenuItem(FontIcon_ResizeHorizontal, "Split Horizontal", "Ctrl + P").Clicked)
                {
                    W_IssueCommand(W_Command_SplitPanelHorizontal);
                    Workspace->Menu = ToolbarMenu_None;
                }
                if(W_BuildMenuItem(FontIcon_ResizeVertical, "Split Vertical", "Ctrl + L").Clicked)
                {
                    W_IssueCommand(W_Command_SplitPanelVertical);
                    Workspace->Menu = ToolbarMenu_None;
                }
            }
            else if(Workspace->Menu == ToolbarMenu_View)
            {
                workspace_panel *CurrentPanel = Workspace->CurrentPanel;
                
                // sixten(TODO): The views should be created at the end of the frame i.e. this should be done via
                // commmands instead. (since we want all things that deals with major state changes to occur at a fixed
                // point in our programs execution)
                
                if(W_BuildMenuItem(FontIcon_None, "Welcome", "").Clicked)
                {
                    W_CreateNewView(W_View_Startup, CurrentPanel);
                    Workspace->Menu = ToolbarMenu_None;
                }
                if(W_BuildMenuItem(FontIcon_Pencil, "Script Editor", "Ctrl + O").Clicked)
                {
                    W_CreateNewView(W_View_TextEditor, CurrentPanel);
                    Workspace->Menu = ToolbarMenu_None;
                }
                if(W_BuildMenuItem(FontIcon_Terminal, "Scene View", "").Clicked)
                {
                    W_CreateNewView(W_View_SceneView, CurrentPanel);
                    Workspace->Menu = ToolbarMenu_None;
                }
                if(W_BuildMenuItem(FontIcon_User, "Character Editor", "").Clicked)
                {
                    W_CreateNewView(W_View_CharacterEditor, CurrentPanel);
                    Workspace->Menu = ToolbarMenu_None;
                }
                if(W_BuildMenuItem(FontIcon_Wrench, "Settings", "").Clicked)
                {
                    W_CreateNewView(W_View_Settings, CurrentPanel);
                    Workspace->Menu = ToolbarMenu_None;
                }
            }
            else if(Workspace->Menu == ToolbarMenu_Window)
            {
                if(W_BuildMenuItem(FontIcon_WindowMaximize, "ToggleFullscreen", "Alt + Enter").Clicked)
                {
                    Platform.ToggleFullscreen();
                    Workspace->Menu = ToolbarMenu_None;
                }
            }
            
            AC_AnimateValueDirect(1, 0.1, &Workspace->MenuTransition);
        }
        
        // sixten: Unless the mouse press was captured, we close the menu.
        if(Platform_KeyPress(Workspace->EventList, Key_MouseLeft))
        {
            Workspace->Menu = ToolbarMenu_None;
        }
    }
}

//- sixten: Panels
static workspace_panel *W_CreateNewPanel(workspace_panel *Parent)
{
    workspace_panel *Result = 0;
    
    workspace *Workspace = W_GetState();
    
    if(DLLIsEmpty(Workspace->FirstFreePanel))
    {
        Result = PushStruct(Workspace->PanelArena, workspace_panel);
    }
    else
    {
        Result = Workspace->FirstFreePanel;
        DLLRemove(Workspace->FirstFreePanel, Workspace->LastFreePanel, Result);
        
        *Result = {};
    }
    
    Result->Parent = Parent;
    
    return(Result);
}

static void W_DeletePanel(workspace_panel *Panel) 
{
    workspace *Workspace = W_GetState();
    
    if(Workspace->CurrentPanel == Panel)
    {
        Workspace->CurrentPanel = 0;
    }
    
    *Panel = {};
    DLLInsertLast(Workspace->FirstFreePanel, Workspace->LastFreePanel, Panel);
}

static void W_SplitPanel(workspace_panel *Panel, axis2 Axis)
{
    workspace *Workspace = W_GetState();
    
    if(Panel)
    {
        workspace_panel *Parent = Panel->Parent;
        
        if(Parent && (Parent->SplitAxis == Axis))
        {
            workspace_panel *NewPanel = W_CreateNewPanel(Parent);
            NewPanel->PercentOfParent = Panel->PercentOfParent = Panel->PercentOfParent * 0.5;
            
            DLLInsert_NP(Parent->First, Parent->Last, Panel, NewPanel, Next, Prev);
        }
        else
        {
            workspace_panel *NewPanel = W_CreateNewPanel(Panel);
            NewPanel->FirstView = Panel->FirstView;
            NewPanel->LastView = Panel->LastView;
            
            // sixten: Update the parents of the children.
            for(workspace_view *Child = NewPanel->FirstView;
                Child != 0;
                Child = Child->Next)
            {
                Child->Parent = NewPanel;
            }
            
            NewPanel->CurrentView = Panel->CurrentView;
            NewPanel->PercentOfParent = 0.5;
            DLLInsertLast(Panel->First, Panel->Last, NewPanel);
            
            NewPanel = W_CreateNewPanel(Panel);
            NewPanel->PercentOfParent = 0.5;
            DLLInsertLast(Panel->First, Panel->Last, NewPanel);
            
            Panel->FirstView = 0;
            Panel->LastView = 0;
            Panel->CurrentView = 0;
            Panel->SplitAxis = Axis;
            
            if(Workspace->CurrentPanel == Panel)
            {
                Workspace->CurrentPanel = Panel->First;
            }
        }
    }
}

inline void W_BeginDrag(workspace_drag_payload *Payload)
{
    workspace *Workspace = W_GetState();
    
    // sixten(TODO): Right now, if you spam-click a draggable item, you can trigger this
    // assertion. I don't know what I want to do about this at the moment, but I'm sure
    // future me will have a soulution at hand. ^.^
    Assert(Workspace->DragPayloadState == W_DragPayload_Inactive);
    
    Workspace->DragPayload = *Payload;
    Workspace->DragPayloadState = W_DragPayload_Active;
}

inline b32 W_GetDragPayload(workspace_drag_payload *Dest)
{
    workspace *Workspace = W_GetState();
    
    b32 Result = (Workspace->DragPayloadState != W_DragPayload_Inactive);
    *Dest = Workspace->DragPayload;
    return(Result);
}

static void W_BuildTabItem(workspace_panel *Panel, workspace_view *View)
{
    workspace *Workspace = W_GetState();
    
    b32 ViewIsCurrent = (Panel->CurrentView == View);
    b32 PanelIsCurrent = (Workspace->CurrentPanel == Panel);
    
    string Name = W_GetViewName(View);
    
    v4 BackgroundColor = ViewIsCurrent ? (PanelIsCurrent ? Theme_HighlightBorderColor : Theme_BorderColor) : ColorFromHex(0x353738FF);
    
    UI_SetNextWidth(UI_ChildrenSum(1, 1));
    UI_SetNextHeight(UI_Percent(1, 1));
    UI_SetNextBackgroundColor(BackgroundColor);
    UI_SetNextBorderColor(LinearBlend(UI_TopBackgroundColor(), Color_Grey, 0.5));
    UI_SetNextLayoutAxis(Axis2_X);
    UI_SetNextCornerRadius(0.0);
    
    ui_box *TabBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground  |
                                 UI_BoxFlag_DrawDropShadow  |
                                 UI_BoxFlag_HotAnimation    |
                                 UI_BoxFlag_ActiveAnimation |
                                 UI_BoxFlag_Clickable,
                                 "Workspace Panel Tab Item %S#%p", Name, View);
    
    UI_Parent(TabBox)
        UI_Padding(UI_Pixels(5, 1))
    {
        UI_Size(UI_TextContent(1, 1), UI_Percent(1, 1)) UI_Label(Name);
        UI_Spacer(UI_Pixels(5, 1));
        
        // sixten: Build close button
        {
            UI_SetNextFont(Font_Icons);
            UI_SetNextSize(UI_TextContent(1, 1), UI_Percent(1, 1));
            UI_SetNextHoverCursor(PlatformCursor_Hand);
            
            ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%U", FontIcon_Cancel);
            
            CloseBox->TextColor = LinearBlend(TabBox->BackgroundColor, Color_Black, 0.3 - CloseBox->HotTransition*0.8);
            
            ui_signal Signal = UI_SignalFromBox(CloseBox);
            if(Signal.Clicked)
            {
                W_IssueCommand(W_Command_CloseView, PointerToU64(View));
            }
        }
    }
    
    ui_signal Signal = UI_SignalFromBox(TabBox);
    if(Signal.Clicked)
    {
        Workspace->CurrentPanel = Panel;
        Panel->CurrentView = View;
    }
    
    // sixten: Handle dragging the view.
    if(Signal.Dragging)
    {
        if(Signal.Pressed)
        {
            workspace_drag_payload Payload = {};
            Payload.View = View;
            Payload.Key = TabBox->Key;
            
            W_BeginDrag(&Payload);
        }
    }
}

static void W_BuildPanelHeader(workspace_panel *Panel)
{
    workspace *Workspace = W_GetState();
    
    UI_SetNextLayoutAxis(Axis2_X);
    UI_SetNextBackgroundColor(ColorFromHex(0x252728FF));
    UI_SetNextCornerRadius(0);
    UI_SetNextSize(UI_Percent(1, 1), UI_Pixels(30, 1));
    
    UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "Workspace Panel Header"))
    {
        for(workspace_view *View = Panel->FirstView;
            View != 0;
            View = View->Next)
        {
            W_BuildTabItem(Panel, View);
        }
        
        // sixten: Panel Close Button
        if(Panel != Workspace->RootPanel)
        {
            UI_Spacer(UI_Percent(1, 0));
            
            UI_SetNextSize(UI_Pixels(30, 1), UI_Pixels(30, 1));
            UI_SetNextFont(Font_Icons);
            UI_SetNextBorderColor(ColorFromHex(0xA6514288));
            UI_SetNextBackgroundColor(ColorFromHex(0xC24630BB));
            UI_SetNextCornerRadius(4);
            UI_SetNextHoverCursor(PlatformCursor_Hand);
            
            ui_box *CloseBox = UI_MakeBoxF(UI_BoxFlag_HotAnimation    |
                                           UI_BoxFlag_ActiveAnimation |
                                           //UI_BoxFlag_DrawBackground  |
                                           //UI_BoxFlag_DrawBorder      |
                                           UI_BoxFlag_DrawText        |
                                           UI_BoxFlag_Clickable,
                                           "%U", FontIcon_Cancel);
            
            ui_signal Signal = UI_SignalFromBox(CloseBox);
            if(Signal.Clicked)
            {
                W_IssueCommand(W_Command_ClosePanel, PointerToU64(Panel));
            }
        }
        
        UI_Spacer(UI_Pixels(2, 1));
    }
}

static void W_BuildPanel(workspace_panel *Panel)
{
    workspace *Workspace = W_GetState();
    
    // sixten: Fill remaining percent of parent.
    workspace_panel *Parent = Panel->Parent;
    if(Parent && Panel != Parent->First)
    {
        r32 TotalOfParent = 0;
        for(workspace_panel *Child = Parent->First;
            Child != 0;
            Child = Child->Next)
        {
            if(Child != Panel)
            {
                TotalOfParent += Child->PercentOfParent;
            }
        }
        
        Panel->PercentOfParent = 1.0 - TotalOfParent;
    }
    
    ui_box *PanelBox = UI_MakeBoxF(0, "Workspace Panel %p", Panel);
    UI_Parent(PanelBox)
    {
        if(DLLIsEmpty(Panel->First))
        {
            W_BuildPanelHeader(Panel);
            
            // sixten: Main body
            {
                b32 PanelIsCurrent = (Workspace->CurrentPanel == Panel);
                
                UI_PushSize(UI_Percent(1, 0), UI_Percent(1, 0));
                
                r32 HighlightTransition = AC_AnimateValueF(PanelIsCurrent, 0, 0.25, "Workspace Panel Highlight %p", Panel);
                UI_SetNextBorderColor(LinearBlend(Theme_BorderColor, Theme_HighlightBorderColor, HighlightTransition));
                UI_SetNextBackgroundColor(Theme_BackgroundColor);
                
                ui_box *BodyBox = UI_MakeBoxF(UI_BoxFlag_DrawBorder     |
                                              UI_BoxFlag_DrawBackground |
                                              UI_BoxFlag_Clip           |
                                              UI_BoxFlag_Clickable,
                                              "Workspace Panel Body");
                UI_Parent(BodyBox)
                {
                    if(Panel->FirstView)
                    {
                        if(!Panel->CurrentView)
                        {
                            Panel->CurrentView = Panel->FirstView;
                        }
                    }
                    else
                    {
                        UI_Column() UI_Padding(UI_Percent(1, 0))
                            UI_Height(UI_ChildrenSum(1, 1)) UI_Row() UI_Padding(UI_Percent(1, 0))
                        {
                            UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1))
                            {
                                UI_LabelF("- empty -");
                            }
                        }
                    }
                    
                    if(Panel->CurrentView)
                    {
                        ui_key CurrentActive = UI_GetActive();
                        
                        W_BuildView(Panel->CurrentView);
                        
                        if(!AreEqual(CurrentActive, UI_GetActive()))
                        {
                            Workspace->CurrentPanel = Panel;
                        }
                    }
                    
                    // sixten: Draw dragged view overlay.
                    {
                        workspace_drag_payload Payload;
                        b32 DragActive = W_GetDragPayload(&Payload);
                        
                        b32 OverlayActive = (DragActive && (Payload.View->Parent != Panel) &&
                                             InRange(BodyBox->Rect, UI_GetState()->MouseP));
                        
                        if(OverlayActive && Workspace->DragPayloadState == W_DragPayload_Released)
                        {
                            // sixten(NOTE): I need to be careful here. If something else sees that a payload has
                            // been released and tries to act upon on it may lead to unwanted behaviour. Just
                            // keep that in mind.
                            
                            // sixten(NOTE): On that previous note, I could just:
                            Workspace->DragPayloadState = W_DragPayload_Inactive;
                            
                            // sixten(TODO): Pull out the code below into separate functions.
                            
                            // sixten: Move view
                            workspace_view *View = Payload.View;
                            {
                                workspace_panel *OldParent = View->Parent;
                                b32 ViewWasCurrent = ((OldParent->CurrentView == View) &&
                                                      (Workspace->CurrentPanel == OldParent));
                                
                                // sixten: Detatch view
                                {
                                    Assert(OldParent);
                                    
                                    if(OldParent->CurrentView == View)
                                    {
                                        OldParent->CurrentView = 0;
                                    }
                                    DLLRemove(OldParent->FirstView, OldParent->LastView, View);
                                }
                                
                                View->Parent = Panel;
                                DLLInsertLast(Panel->FirstView, Panel->LastView, View);
                                
                                if(ViewWasCurrent)
                                {
                                    Workspace->CurrentPanel = Panel;
                                    Panel->CurrentView = View;
                                }
                            }
                        }
                        
                        r32 OverlayTransition = AC_AnimateValueF(OverlayActive, 0, 0.25, "Panel Drag Overlay %p", Panel);
                        
                        v4 OverlayColor = LinearBlend(Color_Grey, Theme_HighlightBorderColor, 0.75);
                        OverlayColor.a = 0.5*OverlayTransition;
                        
                        UI_SetNextBackgroundColor(OverlayColor);
                        UI_SetNextSize(UI_Percent(1, 1), UI_Percent(1, 1));
                        
                        UI_MakeBoxF(UI_BoxFlag_DrawBackground |
                                    UI_BoxFlag_FloatingX      |
                                    UI_BoxFlag_FloatingY,
                                    "Workspace Panel Drag Hover");
                    }
                }
                
                ui_signal Signal = UI_SignalFromBox(BodyBox);
                if(Signal.Pressed)
                {
                    Workspace->CurrentPanel = Panel;
                }
                
                UI_PopSize();
            }
        }
        else
        {
            UI_SetNextSize(UI_Percent(1, 0), UI_Percent(1, 0));
            UI_SetNextLayoutAxis(Panel->SplitAxis);
            
            UI_Parent(UI_MakeBoxF(0, ""))
            {
                s32 ChildCount = 0;
                for(workspace_panel *Child = Panel->First;
                    Child != 0;
                    Child = Child->Next)
                {
                    ++ChildCount;
                }
                
                v2 PanelDim = DimOfRange(PanelBox->Rect);
                
                r32 PaddingSize = 5;
                r32 PaddedSpace = (ChildCount - 1)*PaddingSize;
                r32 PercentPaddedSpace = PaddedSpace / PanelDim.E[Panel->SplitAxis];
                r32 SizeScalar = 1.0 - PercentPaddedSpace;
                
                for(workspace_panel *Child = Panel->First;
                    Child != 0;
                    Child = Child->Next)
                {
                    UI_SetNextAxisSize(Panel->SplitAxis, UI_Percent(Child->PercentOfParent*SizeScalar, 0));
                    UI_SetNextAxisSize(Opposite(Panel->SplitAxis), UI_Percent(1, 0));
                    W_BuildPanel(Child);
                    
                    // sixten: Create drag area
                    if(Child->Next)
                    {
                        UI_SetNextAxisSize(Panel->SplitAxis, UI_Pixels(PaddingSize, 1));
                        UI_SetNextAxisSize(Opposite(Panel->SplitAxis), UI_Percent(1, 0));
                        ui_box *DragBox = UI_MakeBoxF(UI_BoxFlag_Clickable, "Workspace Panel Drag %p", Child);
                        
                        ui_signal Signal = UI_SignalFromBox(DragBox);
                        if(Signal.Hovering || Signal.Dragging)
                        {
                            Platform.SetCursor((Panel->SplitAxis == Axis2_X) ?
                                               PlatformCursor_ArrowHorizontal :
                                               PlatformCursor_ArrowVertical);
                        }
                        
                        if(Signal.Dragging)
                        {
                            if(Signal.Pressed)
                            {
                                UI_StoreDragR32(Child->PercentOfParent);
                            }
                            
                            r32 Delta = Signal.DragDelta.E[Panel->SplitAxis]/PanelDim.E[Panel->SplitAxis];
                            
                            r32 StartOffset = UI_GetDragR32();
                            r32 EndOffset = StartOffset + Delta;
                            
                            Child->PercentOfParent = Clamp(EndOffset, 0.05, 0.95);
                        }
                    }
                }
            }
        }
    }
}

static void W_BuildDragPayload()
{
    workspace *Workspace = W_GetState();
    
    workspace_drag_payload Payload;
    if(W_GetDragPayload(&Payload))
    {
        if(Workspace->DragPayloadState == W_DragPayload_Released)
        {
            Workspace->DragPayloadState = W_DragPayload_Inactive;
        }
        
        if(AreEqual(Payload.Key, UI_GetActive()))
        {
            workspace_view *DraggedView = Payload.View;
            UI_SetNextCornerRadius(4);
            UI_TooltipLabel(W_GetViewName(DraggedView), UI_MouseP());
        }
        else
        {
            if(Workspace->DragPayloadState == W_DragPayload_Active)
            {
                Workspace->DragPayloadState = W_DragPayload_Released;
            }
        }
    }
}

//- sixten: Workspace
static void W_Init(workspace *Workspace)
{
    W_SetState(Workspace);
    
    Workspace->FrameArena = ArenaAllocate(Gigabytes(1));
    Workspace->CommandArena = ArenaAllocate(Gigabytes(1));
    Workspace->PanelArena = ArenaAllocate(Gigabytes(1));
    
    Workspace->RootPanel = Workspace->CurrentPanel = W_CreateNewPanel(0);
    
    if(DEBUG_DebugSettings->ShowWelcomeMessage)
    {
        W_CreateNewView(W_View_Startup, Workspace->RootPanel);
    }
    
    // sixten: build text editor / scene view layout
    if(0)
    {
        W_CreateNewView(W_View_TextEditor, Workspace->RootPanel);
        W_SplitPanel(Workspace->RootPanel, Axis2_X);
        W_CreateNewView(W_View_SceneView, Workspace->RootPanel->Last);
    }
    
    W_CreateNewView(W_View_CharacterEditor, Workspace->RootPanel);
}

static void W_Update(workspace *Workspace, vn_render_commands *RenderCommands,
                     vn_input *Input, glyph_atlas *GlyphAtlas)
{
    W_SetState(Workspace);
    ArenaClear(Workspace->FrameArena);
    
    Workspace->Input = Input;
    Workspace->EventList = Input->EventList;
    
    // sixten: Process the keybinds and commands.
    W_ProcessKeyBinds();
    W_ProcessCommands();
    
    // sixten: Make sure that a view/panel is always selected.
    if(!Workspace->CurrentPanel)
    {
        Workspace->CurrentPanel = Workspace->RootPanel;
        while(Workspace->CurrentPanel->First != 0)
        {
            Workspace->CurrentPanel = Workspace->CurrentPanel->First;
        }
    }
    
    // sixten: Build the UI.
    {
        W_BuildToolbar();
        
        UI_SetNextSize(UI_Percent(1, 1), UI_Percent(1, 0));
        W_BuildPanel(Workspace->RootPanel);
        
        W_BuildDragPayload();
    }
    
}