-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
703 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *\ | ||
* Part of the Tit Solver project, under the MIT License. | ||
* See /LICENSE.md for license information. SPDX-License-Identifier: MIT | ||
\* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | ||
|
||
import React from "react"; | ||
import { FiWind, FiPieChart, FiMove } from "react-icons/fi"; | ||
|
||
import { MyCanvas } from "./view/Canvas"; | ||
import { PhysicsPanel } from "./PhysicsPanel"; | ||
import { Panel, Sidebar } from "./common/Sidebar"; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
const Footer: React.FC = () => { | ||
return <div className="h-6 bg-gradient-to-t from-gray-100 to-gray-200" />; | ||
}; | ||
|
||
const Viewport: React.FC = () => { | ||
return ( | ||
<div className="w-full h-full transition-none"> | ||
<MyCanvas /> | ||
</div> | ||
); | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
export const App: React.FC = () => { | ||
return ( | ||
<div className="flex flex-col h-screen w-screen"> | ||
<div className="flex-1 flex"> | ||
{/* Left sidebar. */} | ||
<Sidebar> | ||
<Panel label="Scene" icon={<FiMove />}> | ||
Scene | ||
</Panel> | ||
<Panel label="Physics" icon={<FiWind />}> | ||
<PhysicsPanel /> | ||
</Panel> | ||
<Panel label="Visual" icon={<FiPieChart />}> | ||
View | ||
</Panel> | ||
</Sidebar> | ||
<div className="flex-grow relative"> | ||
{/* Main viewport. */} | ||
<Viewport /> | ||
</div> | ||
</div> | ||
{/* Footer. */} | ||
<Footer /> | ||
</div> | ||
); | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *\ | ||
* Part of the Tit Solver project, under the MIT License. | ||
* See /LICENSE.md for license information. SPDX-License-Identifier: MIT | ||
\* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | ||
|
||
import React from "react"; | ||
import { TreeView2 } from "./common/TreeView"; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
const treeData = [ | ||
{ | ||
id: "14", | ||
name: "Kernel", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
}, | ||
{ | ||
id: "1", | ||
name: "Parent 1", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
children: [ | ||
{ | ||
id: "2", | ||
value: "123", | ||
name: "Child 1-1", | ||
}, | ||
{ | ||
id: "3", | ||
name: "Child 1-2", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
children: [ | ||
{ | ||
id: "4", | ||
name: "Child 1-2-1", | ||
descr: | ||
"A very very very **very** very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
{ | ||
id: "5", | ||
name: "Parent 2", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
children: [ | ||
{ | ||
id: "6", | ||
name: "Child 2-1", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
}, | ||
], | ||
}, | ||
{ | ||
id: "7", | ||
name: "Parent 3", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
children: [ | ||
{ | ||
id: "8", | ||
name: "Child 3-1", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
}, | ||
{ | ||
id: "9", | ||
name: "Child 3-2", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
children: [ | ||
{ | ||
id: "10", | ||
name: "Child 3-2-1", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
children: [ | ||
{ | ||
id: "11", | ||
name: "Child 3-2-1-1", | ||
descr: | ||
"A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long description.", | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
]; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
export const PhysicsPanel: React.FC = () => { | ||
return <TreeView2 nodes={treeData} />; | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *\ | ||
* Part of the Tit Solver project, under the MIT License. | ||
* See /LICENSE.md for license information. SPDX-License-Identifier: MIT | ||
\* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | ||
|
||
import React, { useState } from "react"; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
export const HorizontalResizableDiv = ({ | ||
children, | ||
minWidth = 120, | ||
maxWidth = 720, | ||
initWidth = 320, | ||
}: { | ||
children: React.ReactNode; | ||
minWidth?: number; | ||
maxWidth?: number; | ||
initWidth?: number; | ||
}) => { | ||
const [widthState, setWidthState] = useState(initWidth); | ||
|
||
const resizeHandler = (e: React.MouseEvent) => { | ||
e.preventDefault(); | ||
|
||
// Save the initial mouse position. | ||
const initX = e.clientX; | ||
|
||
// Update the width of the sidebar once the mouse is moved. | ||
const onMouseMove = (e: MouseEvent) => { | ||
const delta = e.clientX - initX; | ||
const newWidth = Math.max( | ||
minWidth, | ||
Math.min(maxWidth, widthState + delta) | ||
); | ||
setWidthState(newWidth); | ||
}; | ||
|
||
// Remove the event listener once the mouse is released. | ||
const onMouseUp = () => { | ||
// Reset the cursor back to the default. | ||
document.body.style.cursor = "default"; | ||
// Remove the event listener. | ||
window.removeEventListener("mousemove", onMouseMove); | ||
window.removeEventListener("mouseup", onMouseUp); | ||
}; | ||
|
||
// Change the cursor to the resize cursor. | ||
document.body.style.cursor = "ew-resize"; | ||
|
||
// Setup the event listener. | ||
window.addEventListener("mousemove", onMouseMove); | ||
window.addEventListener("mouseup", onMouseUp); | ||
}; | ||
|
||
return ( | ||
<div className="flex w-full"> | ||
<div | ||
className="flex-grow overflow-auto" | ||
style={{ width: `${widthState}px` }} | ||
> | ||
{children} | ||
</div> | ||
<div | ||
className="w-0.5 hover:cursor-ew-resize bg-gray-300" | ||
onMouseDown={resizeHandler} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
export const VerticalResizableDiv = ({ | ||
children, | ||
minHeight = 120, | ||
maxHeight = 720, | ||
initHeight = 320, | ||
}: { | ||
children: React.ReactNode; | ||
minHeight?: number; | ||
maxHeight?: number; | ||
initHeight?: number; | ||
}) => { | ||
const [heightState, setHeightState] = useState(initHeight); | ||
|
||
const resizeHandler = (e: React.MouseEvent) => { | ||
e.preventDefault(); | ||
|
||
// Save the initial mouse position. | ||
const initY = e.clientY; | ||
|
||
// Update the height of the sidebar once the mouse is moved. | ||
const onMouseMove = (e: MouseEvent) => { | ||
const delta = e.clientY - initY; | ||
const newHeight = Math.max( | ||
minHeight, | ||
Math.min(maxHeight, heightState + delta) | ||
); | ||
setHeightState(newHeight); | ||
}; | ||
|
||
// Remove the event listener once the mouse is released. | ||
const onMouseUp = () => { | ||
// Reset the cursor back to the default. | ||
document.body.style.cursor = "default"; | ||
// Remove the event listener. | ||
window.removeEventListener("mousemove", onMouseMove); | ||
window.removeEventListener("mouseup", onMouseUp); | ||
}; | ||
|
||
// Change the cursor to the resize cursor. | ||
document.body.style.cursor = "ns-resize"; | ||
|
||
// Setup the event listener. | ||
window.addEventListener("mousemove", onMouseMove); | ||
window.addEventListener("mouseup", onMouseUp); | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-col"> | ||
<div | ||
className="flex-grow overflow-auto" | ||
style={{ height: `${heightState}px` }} | ||
> | ||
{children} | ||
</div> | ||
<div | ||
className="h-0.5 hover:cursor-ns-resize bg-gray-300" | ||
onMouseDown={resizeHandler} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *\ | ||
* Part of the Tit Solver project, under the MIT License. | ||
* See /LICENSE.md for license information. SPDX-License-Identifier: MIT | ||
\* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | ||
|
||
import React, { useState } from "react"; | ||
|
||
import { HorizontalResizableDiv, VerticalResizableDiv } from "./ResizableDiv"; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
interface TabProps { | ||
label: string; | ||
end?: boolean; | ||
icon: React.ReactNode; | ||
children: React.ReactNode; | ||
} | ||
|
||
export const Panel: React.FC<TabProps> = ({ children }) => { | ||
return <div>{children}</div>; | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
export const Sidebar = ({ | ||
children, | ||
}: { | ||
children: React.ReactElement<TabProps>[]; | ||
}) => { | ||
// Handle the active panel. | ||
const [activePanelIndex, setActivePanelIndex] = useState(1); | ||
|
||
const togglePanel = (index: number) => { | ||
setActivePanelIndex((prev) => (prev === index ? -1 : index)); | ||
}; | ||
|
||
return ( | ||
<div className="flex h-full"> | ||
{/* Sidebar panel icons. */} | ||
<div | ||
className="w-12 pt-2 flex flex-col items-center | ||
shadow-inner bg-gradient-to-r from-gray-100 to-gray-200" | ||
> | ||
{children.map((panel, index) => ( | ||
<div | ||
key={index} | ||
className={`p-2 mb-4 w-10 h-10 flex items-center justify-center | ||
rounded text-6xl text-gray-800 ${ | ||
index === activePanelIndex | ||
? "bg-gray-400 shadow text-black" | ||
: "hover:bg-gray-300" | ||
}`} | ||
onClick={() => togglePanel(index)} | ||
> | ||
{panel.props.icon} | ||
</div> | ||
))} | ||
</div> | ||
{/* Sidebar active panel. */} | ||
{activePanelIndex !== -1 && ( | ||
<HorizontalResizableDiv> | ||
<div | ||
className="flex items-center h-10 border-b-2 | ||
border-gray-300 bg-gray-200" | ||
> | ||
<span className="p-3 text-sm font-bold"> | ||
{children[activePanelIndex].props.label} | ||
</span> | ||
</div> | ||
<VerticalResizableDiv> | ||
<div className="p-1 inner-shadow-xl"> | ||
{children[activePanelIndex]} | ||
</div> | ||
</VerticalResizableDiv> | ||
</HorizontalResizableDiv> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Oops, something went wrong.