Optimize AlignmentButtons component with improved documentation, code structure, and performance

This commit is contained in:
2025-03-22 19:37:54 +01:00
parent 9bb1bf2cdb
commit b76b34a332
+137 -151
View File
@@ -1,3 +1,10 @@
/**
* @file AlignmentButtons.tsx
* @description Component that provides functionality to align selected shapes
* in PowerPoint presentations. Supports horizontal alignment (left, center, right)
* and vertical alignment (top, middle, bottom).
*/
import * as React from "react"; import * as React from "react";
import { import {
Button, Button,
@@ -14,6 +21,35 @@ import {
import { useStatusContext } from "./App"; import { useStatusContext } from "./App";
import { useCommonStyles } from "./commonStyles"; import { useCommonStyles } from "./commonStyles";
/**
* Configuration constants for alignment positions
*/
const ALIGNMENT_CONFIG = {
// Horizontal alignment positions
HORIZONTAL: {
LEFT: 81.1,
CENTER: 480, // Center point of slide
RIGHT: 879.75
},
// Vertical alignment positions
VERTICAL: {
TOP: 136.75,
MIDDLE: 321, // Middle point of slide
BOTTOM: 505.25
},
// Warning message when no shapes are selected
NO_SELECTION_WARNING: "No shapes are selected. Please select shapes first."
};
/**
* Alignment types for horizontal and vertical alignment
*/
type HorizontalAlignmentType = 'left' | 'center' | 'right';
type VerticalAlignmentType = 'top' | 'middle' | 'bottom';
/**
* Component-specific styles
*/
const useStyles = makeStyles({ const useStyles = makeStyles({
alignmentGrid: { alignmentGrid: {
display: "grid", display: "grid",
@@ -31,16 +67,41 @@ const useStyles = makeStyles({
} }
}); });
/**
* AlignmentButtons component provides UI and functionality to align
* selected shapes in PowerPoint presentations.
*
* @returns React component
*/
export const AlignmentButtons: React.FC = () => { export const AlignmentButtons: React.FC = () => {
const styles = useStyles(); const styles = useStyles();
const commonStyles = useCommonStyles(); const commonStyles = useCommonStyles();
const { const {
statusMessage, setStatusMessage, setStatusMessage,
statusType, setStatusType, setStatusType,
isProcessing, setIsProcessing isProcessing,
setIsProcessing
} = useStatusContext(); } = useStatusContext();
const alignLeft = async () => { /**
* Handles errors and updates the status message
*
* @param error - The error object
* @param operation - The operation being performed (for logging)
*/
const handleError = (error: any, operation: string): void => {
setStatusMessage(`Error: ${error.message || "Unknown error occurred"}`);
setStatusType("error");
console.error(`${operation} error:`, error);
setIsProcessing(false);
};
/**
* Generic function to handle horizontal alignment of shapes
*
* @param alignmentType - The type of horizontal alignment to apply
*/
const handleHorizontalAlignment = async (alignmentType: HorizontalAlignmentType): Promise<void> => {
setIsProcessing(true); setIsProcessing(true);
try { try {
await PowerPoint.run(async (context) => { await PowerPoint.run(async (context) => {
@@ -51,31 +112,45 @@ export const AlignmentButtons: React.FC = () => {
// Check if shapes are selected // Check if shapes are selected
if (shapes.items.length === 0) { if (shapes.items.length === 0) {
setStatusMessage("No shapes are selected. Please select shapes first."); setStatusMessage(ALIGNMENT_CONFIG.NO_SELECTION_WARNING);
setStatusType("warning"); setStatusType("warning");
return; return;
} }
// Set alignment for all shapes at once // Set alignment for all shapes at once based on alignment type
shapes.items.forEach(shape => { shapes.items.forEach(shape => {
shape.left = 81.1; switch (alignmentType) {
case 'left':
shape.left = ALIGNMENT_CONFIG.HORIZONTAL.LEFT;
break;
case 'center':
shape.left = ALIGNMENT_CONFIG.HORIZONTAL.CENTER - (shape.width / 2);
break;
case 'right':
shape.left = ALIGNMENT_CONFIG.HORIZONTAL.RIGHT - shape.width;
break;
}
}); });
// Single sync after all updates // Single sync after all updates
await context.sync(); await context.sync();
setStatusMessage("Objects aligned to left."); setStatusMessage(`Objects aligned to ${alignmentType}.`);
setStatusType("success"); setStatusType("success");
}); });
} catch (error) { } catch (error) {
setStatusMessage(`Error: ${error.message}`); handleError(error, `Align ${alignmentType}`);
setStatusType("error");
console.error("Align left error:", error);
} finally { } finally {
setIsProcessing(false); setIsProcessing(false);
} }
}; };
const alignCenter = async () => { /**
* Generic function to handle vertical alignment of shapes
*
* @param alignmentType - The type of vertical alignment to apply
*/
const handleVerticalAlignment = async (alignmentType: VerticalAlignmentType): Promise<void> => {
setIsProcessing(true); setIsProcessing(true);
try { try {
await PowerPoint.run(async (context) => { await PowerPoint.run(async (context) => {
@@ -86,168 +161,79 @@ export const AlignmentButtons: React.FC = () => {
// Check if shapes are selected // Check if shapes are selected
if (shapes.items.length === 0) { if (shapes.items.length === 0) {
setStatusMessage("No shapes are selected. Please select shapes first."); setStatusMessage(ALIGNMENT_CONFIG.NO_SELECTION_WARNING);
setStatusType("warning"); setStatusType("warning");
return; return;
} }
// Set alignment for all shapes at once // Set alignment for all shapes at once based on alignment type
shapes.items.forEach(shape => { shapes.items.forEach(shape => {
shape.left = 480 - (shape.width / 2); switch (alignmentType) {
case 'top':
shape.top = ALIGNMENT_CONFIG.VERTICAL.TOP;
break;
case 'middle':
shape.top = ALIGNMENT_CONFIG.VERTICAL.MIDDLE - (shape.height / 2);
break;
case 'bottom':
shape.top = ALIGNMENT_CONFIG.VERTICAL.BOTTOM - shape.height;
break;
}
}); });
// Single sync after all updates // Single sync after all updates
await context.sync(); await context.sync();
setStatusMessage("Objects aligned to center."); setStatusMessage(`Objects aligned to ${alignmentType}.`);
setStatusType("success"); setStatusType("success");
}); });
} catch (error) { } catch (error) {
setStatusMessage(`Error: ${error.message}`); handleError(error, `Align ${alignmentType}`);
setStatusType("error");
console.error("Align center error:", error);
} finally { } finally {
setIsProcessing(false); setIsProcessing(false);
} }
}; };
const alignRight = async () => { /**
setIsProcessing(true); * Aligns selected shapes to the left edge of the slide
try { */
await PowerPoint.run(async (context) => { const alignLeft = async (): Promise<void> => {
// Get the selected shapes await handleHorizontalAlignment('left');
const shapes = context.presentation.getSelectedShapes();
shapes.load("items");
await context.sync();
// Check if shapes are selected
if (shapes.items.length === 0) {
setStatusMessage("No shapes are selected. Please select shapes first.");
setStatusType("warning");
return;
}
// Set alignment for all shapes at once
shapes.items.forEach(shape => {
shape.left = 879.75 - shape.width;
});
// Single sync after all updates
await context.sync();
setStatusMessage("Objects aligned to right.");
setStatusType("success");
});
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
setStatusType("error");
console.error("Align right error:", error);
} finally {
setIsProcessing(false);
}
}; };
const alignTop = async () => { /**
setIsProcessing(true); * Aligns selected shapes to the horizontal center of the slide
try { */
await PowerPoint.run(async (context) => { const alignCenter = async (): Promise<void> => {
// Get the selected shapes await handleHorizontalAlignment('center');
const shapes = context.presentation.getSelectedShapes();
shapes.load("items");
await context.sync();
// Check if shapes are selected
if (shapes.items.length === 0) {
setStatusMessage("No shapes are selected. Please select shapes first.");
setStatusType("warning");
return;
}
// Set alignment for all shapes at once
shapes.items.forEach(shape => {
shape.top = 136.75;
});
// Single sync after all updates
await context.sync();
setStatusMessage("Objects aligned to top.");
setStatusType("success");
});
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
setStatusType("error");
console.error("Align top error:", error);
} finally {
setIsProcessing(false);
}
}; };
const alignMiddle = async () => { /**
setIsProcessing(true); * Aligns selected shapes to the right edge of the slide
try { */
await PowerPoint.run(async (context) => { const alignRight = async (): Promise<void> => {
// Get the selected shapes await handleHorizontalAlignment('right');
const shapes = context.presentation.getSelectedShapes();
shapes.load("items");
await context.sync();
// Check if shapes are selected
if (shapes.items.length === 0) {
setStatusMessage("No shapes are selected. Please select shapes first.");
setStatusType("warning");
return;
}
// Set alignment for all shapes at once
shapes.items.forEach(shape => {
shape.top = 321 - (shape.height / 2);
});
// Single sync after all updates
await context.sync();
setStatusMessage("Objects aligned to middle.");
setStatusType("success");
});
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
setStatusType("error");
console.error("Align middle error:", error);
} finally {
setIsProcessing(false);
}
}; };
const alignBottom = async () => { /**
setIsProcessing(true); * Aligns selected shapes to the top edge of the slide
try { */
await PowerPoint.run(async (context) => { const alignTop = async (): Promise<void> => {
// Get the selected shapes await handleVerticalAlignment('top');
const shapes = context.presentation.getSelectedShapes(); };
shapes.load("items");
await context.sync();
// Check if shapes are selected /**
if (shapes.items.length === 0) { * Aligns selected shapes to the vertical middle of the slide
setStatusMessage("No shapes are selected. Please select shapes first."); */
setStatusType("warning"); const alignMiddle = async (): Promise<void> => {
return; await handleVerticalAlignment('middle');
} };
// Set alignment for all shapes at once /**
shapes.items.forEach(shape => { * Aligns selected shapes to the bottom edge of the slide
shape.top = 505.25 - shape.height; */
}); const alignBottom = async (): Promise<void> => {
// Single sync after all updates await handleVerticalAlignment('bottom');
await context.sync();
setStatusMessage("Objects aligned to bottom.");
setStatusType("success");
});
} catch (error) {
setStatusMessage(`Error: ${error.message}`);
setStatusType("error");
console.error("Align bottom error:", error);
} finally {
setIsProcessing(false);
}
}; };
return ( return (
@@ -318,4 +304,4 @@ export const AlignmentButtons: React.FC = () => {
); );
}; };
export default AlignmentButtons; export default AlignmentButtons;