static workspace_file_lister_action *W_FileListerActionCopy(arena *Arena, workspace_file_lister_action *Action)
{
	workspace_file_lister_action *Result = PushStruct(Arena, workspace_file_lister_action);
	Result->HasRequestedFile = Action->HasRequestedFile;
	Result->Path = PushString(Arena, Action->Path);
	Result->Name = PushString(Arena, Action->Name);
	return(Result);
}

UI_CUSTOM_DRAW_CALLBACK(W_FileListerInputCallback)
{
	workspace_view_file_lister *Lister = (workspace_view_file_lister *)Data;
	s64 ClampedCursor = Clamp(0, Box->String.Count, Lister->InputEditState.Cursor);
	s64 ClampedMark = Clamp(0, Box->String.Count, Lister->InputEditState.Mark);
	string ToCursor = MakeString(Box->String.Data, ClampedCursor);
	string ToMark = MakeString(Box->String.Data, ClampedMark);
	
	r32 TargetCursorX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToCursor);
	r32 TargetMarkerX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToMark);
	
	r32 CursorX = AC_AnimateValueF(TargetCursorX, 0, 0.175, "Workspace View Input Cursor %p", Box);
	r32 MarkerX = AC_AnimateValueF(TargetMarkerX, 0, 0.175, "Workspace View Input Mark %p", Box);
	
	v2 BoxDim = DimOfRange(Box->Rect);
	
	// sixten: Draw selection
	{
		v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2);
		v2 Dim = V2(0, Box->FontSize);
		if(CursorX > MarkerX)
		{
			Offset.x += MarkerX;
			Dim.x = CursorX - MarkerX;
		}
		else
		{
			Offset.x += CursorX;
			Dim.x = MarkerX - CursorX;
		}
		
		v2 P = Box->Rect.Min + Offset;
		v4 Color = V4(0.4, 0.7, 0.8, 0.3);
		PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
	}
	
	// sixten: Draw cursor
	{
		range1_r32 CursorSpan = Range1R32(CursorX, TargetCursorX);
		r32 Height = Box->FontSize + 4;
		v2 Offset = V2(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2);
		v2 Dim = V2(1.25F + CursorSpan.Max - CursorSpan.Min, Height);
		
		v2 P = Box->Rect.Min + Offset;
		v4 Color = V4(0.3, 1, 0.3, 0.7);
		PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
	}
}

static b32 W_BuildFileListerItem(string Text, u32 Icon, b32 Selected, b32 EnterPressed)
{
	b32 Result = false;
	UI_SetNextLayoutAxis(Axis2_X);
	UI_SetNextHoverCursor(PlatformCursor_Hand);
	r32 SelectedT = AC_AnimateValueF(Selected, 0, 0.3f, "Lister Item %S", Text);
	UI_SetNextBackgroundColor(LinearBlend(Theme_BackgroundColor, Theme_HighlightBorderColor, SelectedT*0.5));
	UI_SetNextBorderColor(LinearBlend(Theme_BorderColor, Theme_HighlightBorderColor, SelectedT));
	ui_box *Container = UI_MakeBoxF(UI_BoxFlag_DrawBorder     |
																																	UI_BoxFlag_DrawBackground |
																																	UI_BoxFlag_Clickable      |
																																	UI_BoxFlag_HotAnimation   |
																																	UI_BoxFlag_ActiveAnimation|
																																	UI_BoxFlag_DrawDropShadow,
																																	"File Lister %S", Text);
	UI_Parent(Container)
	{
		UI_Width(UI_Em(2, 1)) UI_Font(Font_Icons) UI_LabelF("%U", Icon);
		UI_Width(UI_TextContent(0, 1)) UI_Label(Text);
	}
	
	ui_signal Signal = UI_SignalFromBox(Container);
	if(Signal.Clicked || Selected&&EnterPressed)
	{
		Result = true;
	}
	return(Result);
}

static workspace_file_lister_action W_BuildFileLister(workspace_view *View)
{
	workspace_file_lister_action ListerAction = {};
	
	workspace_view_file_lister *Lister = (workspace_view_file_lister *)View->Data;
	
	b32 EnterPressed = Platform_KeyPress(UI_EventList(), Key_Return);
	s32 SelectedItemDelta = 0;
	s32 ListerCount = 0;
	s64 LastSlash = LastIndexOf(Lister->Path, '/');
	b32 RequestedParentDirectory = false;
	
	temp Scratch = GetScratch();
	UI_Size(UI_Percent(1, 1), UI_Percent(1, 1))
	{
		//- sixten: filename input field
		if(W_ViewIsCurrent(View))
		{
			for(platform_event *Event = UI_EventList()->First; Event != 0; Event = Event->Next)
			{
				if(Event->Type == PlatformEvent_Press && (Event->Key == Key_Up || Event->Key == Key_Down))
				{
					SelectedItemDelta = Event->Key == Key_Up ? -1 : 1;
				}
				if(Event->Type == PlatformEvent_Press && Event->Key == Key_Backspace && Lister->InputEditState.Cursor == 0)
				{
					RequestedParentDirectory = true;
				}
			}
		}
		
		//- sixten: build navbar
		UI_Height(UI_Em(2, 1)) UI_Row(UI_BoxFlag_DrawBorder)
		{
			
			UI_SetNextBackgroundColor(ColorFromHex(0x2D5790FF));
			UI_SetNextWidth(UI_TextContent(20, 1));
			UI_MakeBox(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawText, Lister->Path);
			
			UI_Width(UI_Percent(1, 0))
				UI_LineEdit(&Lister->InputEditState, ArrayCount(Lister->Input), Lister->Input, &Lister->InputUsed, StrLit("File Lister Text Input"), W_ViewIsCurrent(View));
			
			UI_SetNextWidth(UI_TextContent(20, 1));
			if(UI_ButtonF("Open/Create").Clicked || EnterPressed)
			{
				ListerAction.HasRequestedFile = true;
				ListerAction.Name = MakeString(Lister->Input, Lister->InputUsed);
				ListerAction.Path = Lister->Path;
			}
		}
		
		UI_Scroll(0, &Lister->Scroll)
		{
			UI_Height(UI_Em(2, 1))
			{
				//- sixten: display "parent directory button" 
				if(LastSlash != -1)
				{
					if(W_BuildFileListerItem(StrLit("Parent Directory"), FontIcon_Reply, Lister->SelectedItem == ListerCount, EnterPressed))
					{
						RequestedParentDirectory = true;
						ListerAction.HasRequestedFile = false; // sixten: if we have selected a folder, but typed a name we want to open the folder.
					}
					ListerCount += 1;
				}
				platform_file_info FileInfo;
				platform_file_iter *FileIter;
				
				string Name = MakeString(Lister->Input, Lister->InputUsed);
				string FullPath = PushFormat(Scratch.Arena, "%S/%S", Lister->Path, Name);
				
				//- sixten: display directories
				{
					FileIter = Platform.BeginFileIter(Scratch.Arena, FullPath);
					for(;Platform.AdvanceFileIter(Scratch.Arena, FileIter, &FileInfo);)
					{
						if(FileInfo.IsDirectory)
						{
							if(W_BuildFileListerItem(FileInfo.Name, FontIcon_Folder, Lister->SelectedItem == ListerCount, EnterPressed))
							{
								Lister->Path = PushFormat(View->Arena, "%S/%S", Lister->Path, FileInfo.Name);
								Lister->InputUsed = 0;
								Lister->SelectedItem = -1;
								ListerAction.HasRequestedFile = false; // sixten: if we have selected a folder, but typed a name we want to open the folder.
							}
							ListerCount += 1;
						}
					}
				}
				Platform.EndFileIter(FileIter);
				
				//- sixten: display files
				{
					FileIter = Platform.BeginFileIter(Scratch.Arena, FullPath);
					for(;Platform.AdvanceFileIter(Scratch.Arena, FileIter, &FileInfo);)
					{
						if(!FileInfo.IsDirectory)
						{
							if(W_BuildFileListerItem(FileInfo.Name, FontIcon_Document, Lister->SelectedItem == ListerCount, EnterPressed))
							{
								ListerAction.HasRequestedFile = true;
								Lister->SelectedItem = -1;
								ListerAction.Name = PushString(View->Arena, FileInfo.Name);
								ListerAction.Path = Lister->Path;
							}
							ListerCount += 1;
						}
					}
				}
				
				//- sixten: update selected item
				if(SelectedItemDelta != 0)
				{
					Lister->SelectedItem += SelectedItemDelta;
					if(Lister->SelectedItem < 0)
					{
						Lister->SelectedItem = ListerCount - 1;
					}
					else if(Lister->SelectedItem >= ListerCount)
					{
						Lister->SelectedItem -= ListerCount;
					}
				}
				
				Platform.EndFileIter(FileIter);
			}
		}
	}
	
	//- sixten: goto parent directory
	if(RequestedParentDirectory && LastSlash != -1)
	{
		Lister->Path = Prefix(Lister->Path, LastSlash);
		Lister->InputUsed = 0;
		Lister->SelectedItem = -1;
	}
	
	ReleaseScratch(Scratch);
	return(ListerAction);
}
