Update all three section dialogs to support hide/show toggle: SectionAxisDialogManager: - onHideToggle now calls hideSection()/recoverSection() SectionBoxDialogManager: - onHideToggle now calls hideSection()/recoverSection() SectionPlanePanel: - Add isHidden state tracking - Change onHide to onHideToggle(isHidden) - Add setHiddenState/getHiddenState methods - Update button to toggle active state SectionPlaneDialogManager: - Switch to onHideToggle callback - Call hideSection()/recoverSection() based on toggle state Behavior: Click hide button to hide section, click again to recover.
193 lines
5.7 KiB
TypeScript
193 lines
5.7 KiB
TypeScript
import './index.css';
|
|
import type { ThemeConfig } from '../../themes/types';
|
|
import { IBimComponent } from '../../types/component';
|
|
import { localeManager, t } from '../../services/locale';
|
|
import { themeManager } from '../../services/theme';
|
|
import type { SectionPlanePanelOptions } from './types';
|
|
import { getIcon } from '../../utils/icon-manager';
|
|
|
|
/**
|
|
* 拾取面剖切面板组件
|
|
* 包含三个操作按钮:隐藏、反向、重置
|
|
*/
|
|
export class SectionPlanePanel implements IBimComponent {
|
|
public element: HTMLElement;
|
|
private options: SectionPlanePanelOptions;
|
|
|
|
private isHidden: boolean = false;
|
|
|
|
// DOM 引用
|
|
private hideBtn!: HTMLButtonElement;
|
|
private reverseBtn!: HTMLButtonElement;
|
|
private resetBtn!: HTMLButtonElement;
|
|
private hideLabelEl!: HTMLElement;
|
|
private reverseLabelEl!: HTMLElement;
|
|
private resetLabelEl!: HTMLElement;
|
|
|
|
// 订阅清理
|
|
private unsubscribeLocale: (() => void) | null = null;
|
|
private unsubscribeTheme: (() => void) | null = null;
|
|
|
|
constructor(options: SectionPlanePanelOptions = {}) {
|
|
this.options = options;
|
|
this.isHidden = options.defaultHidden ?? false;
|
|
this.element = this.createDom();
|
|
}
|
|
|
|
public setHiddenState(isHidden: boolean): void {
|
|
this.isHidden = isHidden;
|
|
this.updateButtonStates();
|
|
}
|
|
|
|
public getHiddenState(): boolean {
|
|
return this.isHidden;
|
|
}
|
|
|
|
private updateButtonStates(): void {
|
|
this.hideBtn?.classList.toggle('active', this.isHidden);
|
|
}
|
|
|
|
/**
|
|
* 初始化组件
|
|
*/
|
|
public init(): void {
|
|
// 订阅语言变更
|
|
this.unsubscribeLocale = localeManager.subscribe(() => {
|
|
this.setLocales();
|
|
});
|
|
|
|
// 订阅主题变更
|
|
this.unsubscribeTheme = themeManager.subscribe((theme) => {
|
|
this.setTheme(theme);
|
|
});
|
|
|
|
// 初始应用
|
|
this.setLocales();
|
|
this.setTheme(themeManager.getTheme());
|
|
}
|
|
|
|
/**
|
|
* 设置主题
|
|
*/
|
|
public setTheme(theme: ThemeConfig): void {
|
|
const style = this.element.style;
|
|
style.setProperty('--bim-bg-inset', theme.bgInset ?? '#152232');
|
|
style.setProperty('--bim-border-default', theme.borderDefault ?? '#334155');
|
|
style.setProperty('--bim-border-strong', theme.borderStrong ?? '#475569');
|
|
style.setProperty('--bim-primary', theme.primary ?? '#3b82f6');
|
|
style.setProperty('--bim-primary-subtle', theme.primarySubtle ?? 'rgba(59, 130, 246, 0.15)');
|
|
style.setProperty('--bim-icon-default', theme.iconDefault ?? '#ffffff');
|
|
style.setProperty('--bim-text-primary', theme.textPrimary ?? '#ffffff');
|
|
style.setProperty('--bim-component-bg-hover', theme.componentBgHover ?? 'rgba(248, 250, 252, 0.06)');
|
|
}
|
|
|
|
/**
|
|
* 设置语言
|
|
*/
|
|
public setLocales(): void {
|
|
this.hideLabelEl.textContent = t('sectionPlane.actions.hide');
|
|
this.reverseLabelEl.textContent = t('sectionPlane.actions.reverse');
|
|
this.resetLabelEl.textContent = t('sectionPlane.actions.reset');
|
|
|
|
this.hideBtn.title = t('sectionPlane.actions.hide');
|
|
this.reverseBtn.title = t('sectionPlane.actions.reverse');
|
|
this.resetBtn.title = t('sectionPlane.actions.reset');
|
|
}
|
|
|
|
/**
|
|
* 销毁组件
|
|
*/
|
|
public destroy(): void {
|
|
if (this.unsubscribeLocale) {
|
|
this.unsubscribeLocale();
|
|
this.unsubscribeLocale = null;
|
|
}
|
|
if (this.unsubscribeTheme) {
|
|
this.unsubscribeTheme();
|
|
this.unsubscribeTheme = null;
|
|
}
|
|
this.element.remove();
|
|
}
|
|
|
|
/**
|
|
* 创建 DOM
|
|
*/
|
|
private createDom(): HTMLElement {
|
|
const root = document.createElement('div');
|
|
root.className = 'section-plane-panel';
|
|
|
|
// 隐藏按钮
|
|
this.hideBtn = this.createButton(
|
|
'hide',
|
|
getIcon('隐藏'),
|
|
() => {
|
|
this.isHidden = !this.isHidden;
|
|
this.updateButtonStates();
|
|
this.options.onHideToggle?.(this.isHidden);
|
|
}
|
|
);
|
|
|
|
// 反向按钮
|
|
this.reverseBtn = this.createButton(
|
|
'reverse',
|
|
getIcon('反向'),
|
|
() => {
|
|
if (this.options.onReverse) {
|
|
this.options.onReverse();
|
|
}
|
|
}
|
|
);
|
|
|
|
// 重置按钮
|
|
this.resetBtn = this.createButton(
|
|
'reset',
|
|
getIcon('重置'),
|
|
() => {
|
|
if (this.options.onReset) {
|
|
this.options.onReset();
|
|
}
|
|
}
|
|
);
|
|
|
|
root.appendChild(this.hideBtn);
|
|
root.appendChild(this.reverseBtn);
|
|
root.appendChild(this.resetBtn);
|
|
|
|
return root;
|
|
}
|
|
|
|
/**
|
|
* 创建按钮
|
|
*/
|
|
private createButton(type: 'hide' | 'reverse' | 'reset', iconSvg: string, onClick: () => void): HTMLButtonElement {
|
|
const btn = document.createElement('button');
|
|
btn.type = 'button';
|
|
btn.className = 'section-plane-btn';
|
|
|
|
// 图标
|
|
const icon = document.createElement('div');
|
|
icon.className = 'section-plane-btn-icon';
|
|
icon.innerHTML = iconSvg;
|
|
btn.appendChild(icon);
|
|
|
|
// 标签
|
|
const label = document.createElement('div');
|
|
label.className = 'section-plane-btn-label';
|
|
btn.appendChild(label);
|
|
|
|
// 保存 label 引用
|
|
if (type === 'hide') {
|
|
this.hideLabelEl = label;
|
|
} else if (type === 'reverse') {
|
|
this.reverseLabelEl = label;
|
|
} else {
|
|
this.resetLabelEl = label;
|
|
}
|
|
|
|
// 点击事件
|
|
btn.addEventListener('click', onClick);
|
|
|
|
return btn;
|
|
}
|
|
}
|