Add handling for buttons
This commit is contained in:
parent
4d3113dc99
commit
591ed62ccd
@ -9,6 +9,7 @@ export interface ButtonDefinition {
|
|||||||
text: string|JSX.Element;
|
text: string|JSX.Element;
|
||||||
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
cssProps: CSSProperties;
|
cssProps: CSSProperties;
|
||||||
|
buttonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>
|
||||||
}
|
}
|
||||||
|
|
||||||
const ButtonGroup = ({buttons, buttonStyleProps}: ButtonGroupProps) => {
|
const ButtonGroup = ({buttons, buttonStyleProps}: ButtonGroupProps) => {
|
||||||
@ -23,6 +24,7 @@ const ButtonGroup = ({buttons, buttonStyleProps}: ButtonGroupProps) => {
|
|||||||
...buttonStyleProps,
|
...buttonStyleProps,
|
||||||
...btn.cssProps
|
...btn.cssProps
|
||||||
}}
|
}}
|
||||||
|
{...(btn.buttonProps ?? {})}
|
||||||
>
|
>
|
||||||
<>{btn.text}</>
|
<>{btn.text}</>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -1,26 +1,54 @@
|
|||||||
import {ButtonDefinition, ButtonGroup} from '../button';
|
import {ButtonDefinition, ButtonGroup} from '../button';
|
||||||
import {AiOutlineClear, BsFillPlayFill, BsFillStopFill, CiSettings, TbArrowsRandom} from 'react-icons/all';
|
import {
|
||||||
import React, {useMemo} from 'react';
|
AiOutlineClear,
|
||||||
|
BsFillPlayFill,
|
||||||
|
BsFillStopFill,
|
||||||
|
CiSettings,
|
||||||
|
IoAdd,
|
||||||
|
IoRemove,
|
||||||
|
TbArrowsRandom
|
||||||
|
} from 'react-icons/all';
|
||||||
|
import React, {useCallback, useMemo} from 'react';
|
||||||
|
import {GameOptions, GameState} from './Game';
|
||||||
|
|
||||||
interface ControlPanelProps {
|
interface ControlPanelProps {
|
||||||
|
gameOptions: GameOptions;
|
||||||
handleStart: React.MouseEventHandler<HTMLButtonElement>;
|
handleStart: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
handleStop: React.MouseEventHandler<HTMLButtonElement>;
|
handleStop: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
handleRandomFill: React.MouseEventHandler<HTMLButtonElement>;
|
handleRandomFill: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
handleClear: React.MouseEventHandler<HTMLButtonElement>;
|
handleClear: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
handleUpdateSpeed: (newVal: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ControlPanel = ({
|
const ControlPanel = ({
|
||||||
|
gameOptions,
|
||||||
handleStart,
|
handleStart,
|
||||||
handleStop,
|
handleStop,
|
||||||
handleRandomFill,
|
handleRandomFill,
|
||||||
handleClear
|
handleClear,
|
||||||
|
handleUpdateSpeed
|
||||||
}: ControlPanelProps) => {
|
}: ControlPanelProps) => {
|
||||||
const controlButtons: ButtonDefinition[] = useMemo(() => [
|
const controlButtons: ButtonDefinition[] = useMemo(() => [
|
||||||
{text: <BsFillPlayFill />, onClick: handleStart, cssProps: {}},
|
{text: <BsFillPlayFill />, onClick: handleStart, cssProps: {}, buttonProps: {disabled: gameOptions.gameState === GameState.Running}},
|
||||||
{text: <BsFillStopFill />, onClick: handleStop, cssProps: {}},
|
{text: <BsFillStopFill />, onClick: handleStop, cssProps: {}, buttonProps: {disabled: gameOptions.gameState === GameState.Stopped}},
|
||||||
{text: <TbArrowsRandom />, onClick: handleRandomFill, cssProps: {}},
|
{text: <TbArrowsRandom />, onClick: handleRandomFill, cssProps: {}},
|
||||||
{text: <AiOutlineClear />, onClick: handleClear, cssProps: {}}
|
{text: <AiOutlineClear />, onClick: handleClear, cssProps: {}}
|
||||||
], [handleStart, handleStop, handleRandomFill, handleClear]);
|
], [handleStart, handleStop, handleRandomFill, handleClear, gameOptions]);
|
||||||
|
|
||||||
|
const handleSpeedChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
handleUpdateSpeed(Number(value));
|
||||||
|
}, [handleUpdateSpeed]);
|
||||||
|
|
||||||
|
const handleSpeedUp = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
const newVal = gameOptions.speed + 100;
|
||||||
|
handleUpdateSpeed(newVal);
|
||||||
|
}, [handleUpdateSpeed, gameOptions]);
|
||||||
|
|
||||||
|
const handleSpeedDown = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
const newVal = gameOptions.speed - 100;
|
||||||
|
handleUpdateSpeed(newVal);
|
||||||
|
}, [handleUpdateSpeed, gameOptions]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='control-panel'>
|
<div className='control-panel'>
|
||||||
@ -30,6 +58,16 @@ const ControlPanel = ({
|
|||||||
width: '50px'
|
width: '50px'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className='speed-selector'>
|
||||||
|
<button onClick={handleSpeedUp}><IoAdd /></button>
|
||||||
|
<input
|
||||||
|
value={gameOptions.speed}
|
||||||
|
onChange={handleSpeedChange}
|
||||||
|
/>
|
||||||
|
<button onClick={handleSpeedDown}><IoRemove /></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button><CiSettings/></button>
|
<button><CiSettings/></button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,30 +8,66 @@ interface GameProps {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GameOptions {
|
export enum GameState {
|
||||||
|
Stopped,
|
||||||
|
Running
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GameOptions {
|
||||||
|
gameState: GameState;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
speed: number;
|
||||||
|
minSpeed: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultGameOptions: GameOptions = {
|
const defaultGameOptions: GameOptions = {
|
||||||
|
gameState: GameState.Stopped,
|
||||||
width: 25,
|
width: 25,
|
||||||
height: 25
|
height: 25,
|
||||||
|
speed: 1000,
|
||||||
|
minSpeed: 100
|
||||||
}
|
}
|
||||||
|
|
||||||
const Game = ({}: GameProps) => {
|
const Game = ({}: GameProps) => {
|
||||||
const [gameOptions, setGameOptions] = useState<GameOptions>(defaultGameOptions);
|
const [gameOptions, setGameOptions] = useState<GameOptions>(defaultGameOptions);
|
||||||
const [cells, setCells] = useState<boolean[]>([]);
|
const [cells, setCells] = useState<boolean[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
const handleStart = useCallback(() => {
|
||||||
|
setGameOptions(prev => {
|
||||||
|
prev.gameState = GameState.Running;
|
||||||
|
return {...prev};
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleStop = useCallback(() => {
|
||||||
|
setGameOptions(prev => {
|
||||||
|
prev.gameState = GameState.Stopped;
|
||||||
|
return {...prev};
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleRandomFill = useCallback(() => {
|
||||||
const newCells: boolean[] = [];
|
const newCells: boolean[] = [];
|
||||||
const totalCells = gameOptions.width * gameOptions.height;
|
const totalCells = gameOptions.width * gameOptions.height;
|
||||||
|
|
||||||
for(let i = 0; i < totalCells; i++) {
|
for(let i = 0; i < totalCells; i++) {
|
||||||
newCells.push(false);
|
newCells.push(Math.random() < 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
setCells(newCells);
|
setCells(newCells);
|
||||||
}, [gameOptions]);
|
}, []);
|
||||||
|
|
||||||
|
const handleClear = useCallback(() => {
|
||||||
|
const newCells: boolean[] = [];
|
||||||
|
const totalCells = gameOptions.width * gameOptions.height;
|
||||||
|
|
||||||
|
for(let i = 0; i < totalCells; i++) {
|
||||||
|
newCells.push(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCells(newCells);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleCellUpdate = useCallback((newVal: boolean, position: number) => {
|
const handleCellUpdate = useCallback((newVal: boolean, position: number) => {
|
||||||
setCells(prev => {
|
setCells(prev => {
|
||||||
@ -40,13 +76,30 @@ const Game = ({}: GameProps) => {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleUpdateSpeed = useCallback((newVal: number) => {
|
||||||
|
if(newVal < gameOptions.minSpeed) {
|
||||||
|
newVal = gameOptions.minSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
setGameOptions(prev => {
|
||||||
|
prev.speed = newVal;
|
||||||
|
return {...prev};
|
||||||
|
})
|
||||||
|
}, [gameOptions]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleClear();
|
||||||
|
}, [handleClear]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='game-container'>
|
<div className='game-container'>
|
||||||
<ControlPanel
|
<ControlPanel
|
||||||
handleStart={() => {}}
|
gameOptions={gameOptions}
|
||||||
handleStop={() => {}}
|
handleStart={handleStart}
|
||||||
handleRandomFill={() => {}}
|
handleStop={handleStop}
|
||||||
handleClear={() => {}}
|
handleRandomFill={handleRandomFill}
|
||||||
|
handleClear={handleClear}
|
||||||
|
handleUpdateSpeed={handleUpdateSpeed}
|
||||||
/>
|
/>
|
||||||
<CellContainer
|
<CellContainer
|
||||||
cells={cells}
|
cells={cells}
|
||||||
|
|||||||
@ -10,6 +10,18 @@
|
|||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.speed-selector {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.cell-container {
|
.cell-container {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ button {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|
||||||
align-content: center;
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user