Optimize AlignmentButtons component with improved documentation, code structure, and performance
This commit is contained in:
@@ -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 {
|
||||
Button,
|
||||
@@ -14,6 +21,35 @@ import {
|
||||
import { useStatusContext } from "./App";
|
||||
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({
|
||||
alignmentGrid: {
|
||||
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 = () => {
|
||||
const styles = useStyles();
|
||||
const commonStyles = useCommonStyles();
|
||||
const {
|
||||
statusMessage, setStatusMessage,
|
||||
statusType, setStatusType,
|
||||
isProcessing, setIsProcessing
|
||||
setStatusMessage,
|
||||
setStatusType,
|
||||
isProcessing,
|
||||
setIsProcessing
|
||||
} = 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);
|
||||
try {
|
||||
await PowerPoint.run(async (context) => {
|
||||
@@ -51,31 +112,45 @@ export const AlignmentButtons: React.FC = () => {
|
||||
|
||||
// Check if shapes are selected
|
||||
if (shapes.items.length === 0) {
|
||||
setStatusMessage("No shapes are selected. Please select shapes first.");
|
||||
setStatusMessage(ALIGNMENT_CONFIG.NO_SELECTION_WARNING);
|
||||
setStatusType("warning");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set alignment for all shapes at once
|
||||
// Set alignment for all shapes at once based on alignment type
|
||||
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
|
||||
await context.sync();
|
||||
|
||||
setStatusMessage("Objects aligned to left.");
|
||||
setStatusMessage(`Objects aligned to ${alignmentType}.`);
|
||||
setStatusType("success");
|
||||
});
|
||||
} catch (error) {
|
||||
setStatusMessage(`Error: ${error.message}`);
|
||||
setStatusType("error");
|
||||
console.error("Align left error:", error);
|
||||
handleError(error, `Align ${alignmentType}`);
|
||||
} finally {
|
||||
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);
|
||||
try {
|
||||
await PowerPoint.run(async (context) => {
|
||||
@@ -86,168 +161,79 @@ export const AlignmentButtons: React.FC = () => {
|
||||
|
||||
// Check if shapes are selected
|
||||
if (shapes.items.length === 0) {
|
||||
setStatusMessage("No shapes are selected. Please select shapes first.");
|
||||
setStatusMessage(ALIGNMENT_CONFIG.NO_SELECTION_WARNING);
|
||||
setStatusType("warning");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set alignment for all shapes at once
|
||||
// Set alignment for all shapes at once based on alignment type
|
||||
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
|
||||
await context.sync();
|
||||
|
||||
setStatusMessage("Objects aligned to center.");
|
||||
|
||||
setStatusMessage(`Objects aligned to ${alignmentType}.`);
|
||||
setStatusType("success");
|
||||
});
|
||||
} catch (error) {
|
||||
setStatusMessage(`Error: ${error.message}`);
|
||||
setStatusType("error");
|
||||
console.error("Align center error:", error);
|
||||
handleError(error, `Align ${alignmentType}`);
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const alignRight = async () => {
|
||||
setIsProcessing(true);
|
||||
try {
|
||||
await PowerPoint.run(async (context) => {
|
||||
// Get the selected shapes
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Aligns selected shapes to the left edge of the slide
|
||||
*/
|
||||
const alignLeft = async (): Promise<void> => {
|
||||
await handleHorizontalAlignment('left');
|
||||
};
|
||||
|
||||
const alignTop = async () => {
|
||||
setIsProcessing(true);
|
||||
try {
|
||||
await PowerPoint.run(async (context) => {
|
||||
// Get the selected shapes
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Aligns selected shapes to the horizontal center of the slide
|
||||
*/
|
||||
const alignCenter = async (): Promise<void> => {
|
||||
await handleHorizontalAlignment('center');
|
||||
};
|
||||
|
||||
const alignMiddle = async () => {
|
||||
setIsProcessing(true);
|
||||
try {
|
||||
await PowerPoint.run(async (context) => {
|
||||
// Get the selected shapes
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Aligns selected shapes to the right edge of the slide
|
||||
*/
|
||||
const alignRight = async (): Promise<void> => {
|
||||
await handleHorizontalAlignment('right');
|
||||
};
|
||||
|
||||
const alignBottom = async () => {
|
||||
setIsProcessing(true);
|
||||
try {
|
||||
await PowerPoint.run(async (context) => {
|
||||
// Get the selected shapes
|
||||
const shapes = context.presentation.getSelectedShapes();
|
||||
shapes.load("items");
|
||||
await context.sync();
|
||||
/**
|
||||
* Aligns selected shapes to the top edge of the slide
|
||||
*/
|
||||
const alignTop = async (): Promise<void> => {
|
||||
await handleVerticalAlignment('top');
|
||||
};
|
||||
|
||||
// Check if shapes are selected
|
||||
if (shapes.items.length === 0) {
|
||||
setStatusMessage("No shapes are selected. Please select shapes first.");
|
||||
setStatusType("warning");
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Aligns selected shapes to the vertical middle of the slide
|
||||
*/
|
||||
const alignMiddle = async (): Promise<void> => {
|
||||
await handleVerticalAlignment('middle');
|
||||
};
|
||||
|
||||
// Set alignment for all shapes at once
|
||||
shapes.items.forEach(shape => {
|
||||
shape.top = 505.25 - shape.height;
|
||||
});
|
||||
// Single sync after all updates
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Aligns selected shapes to the bottom edge of the slide
|
||||
*/
|
||||
const alignBottom = async (): Promise<void> => {
|
||||
await handleVerticalAlignment('bottom');
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -318,4 +304,4 @@ export const AlignmentButtons: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default AlignmentButtons;
|
||||
export default AlignmentButtons;
|
||||
|
||||
Reference in New Issue
Block a user