636 lines
29 KiB
Python
636 lines
29 KiB
Python
"""
|
||
高级样式编辑器模块
|
||
|
||
提供专业的样式编辑和实时预览功能,让用户能够创建和定制个性化的文档样式。
|
||
"""
|
||
|
||
import tkinter as tk
|
||
from tkinter import ttk, colorchooser, messagebox, simpledialog
|
||
from typing import Optional, Dict, Any
|
||
import copy
|
||
|
||
from style_manager import style_manager, DocumentStyle, FontStyle, ParagraphStyle
|
||
from config import Config
|
||
|
||
|
||
def open_advanced_editor(parent, style_name):
|
||
"""
|
||
打开高级样式编辑器
|
||
|
||
Args:
|
||
parent: 父窗口
|
||
style_name: 要编辑的样式名称
|
||
"""
|
||
if not style_name:
|
||
messagebox.showwarning("警告", "请先选择一个样式")
|
||
return None
|
||
|
||
# 获取样式
|
||
original_style = style_manager.get_style(style_name)
|
||
if not original_style:
|
||
messagebox.showerror("错误", f"找不到样式 '{style_name}'")
|
||
return None
|
||
|
||
editor = AdvancedStyleEditor(parent, original_style)
|
||
return editor
|
||
|
||
|
||
class AdvancedStyleEditor:
|
||
"""
|
||
高级样式编辑器类
|
||
"""
|
||
|
||
def __init__(self, parent, original_style):
|
||
self.parent = parent
|
||
self.original_style = original_style
|
||
self.current_style = copy.deepcopy(original_style)
|
||
|
||
# 确保样式对象完整
|
||
self._ensure_style_completeness()
|
||
|
||
# 创建编辑窗口
|
||
self.window = tk.Toplevel(parent)
|
||
self.window.title(f'高级样式编辑 - {self.current_style.name}')
|
||
self.window.geometry('1000x700')
|
||
self.window.transient(parent)
|
||
self.window.grab_set()
|
||
|
||
# 样式变量
|
||
self.style_vars = {}
|
||
self.heading_vars = {}
|
||
|
||
self._create_interface()
|
||
self._bind_events()
|
||
self._update_preview()
|
||
|
||
def _ensure_style_completeness(self):
|
||
"""确保样式对象的完整性"""
|
||
if not self.current_style.body_font:
|
||
self.current_style.body_font = FontStyle()
|
||
if not self.current_style.body_paragraph:
|
||
self.current_style.body_paragraph = ParagraphStyle()
|
||
if not self.current_style.heading_styles:
|
||
self.current_style.heading_styles = {}
|
||
|
||
# 确保至少有3级标题 - 使用正确的HeadingStyle对象
|
||
from style_manager import HeadingStyle
|
||
for level in range(1, 4):
|
||
if level not in self.current_style.heading_styles:
|
||
font_size = max(20 - level * 2, 12)
|
||
self.current_style.heading_styles[level] = HeadingStyle(
|
||
font=FontStyle(name="微软雅黑", size=font_size, bold=True),
|
||
paragraph=ParagraphStyle(line_spacing=1.3, space_before=12, space_after=6),
|
||
outline_level=level
|
||
)
|
||
|
||
def _create_interface(self):
|
||
"""创建界面"""
|
||
# 创建主布局
|
||
main_frame = ttk.Frame(self.window)
|
||
main_frame.pack(fill='both', expand=True, padx=10, pady=10)
|
||
|
||
# 左侧编辑区域
|
||
edit_frame = ttk.Frame(main_frame)
|
||
edit_frame.pack(side='left', fill='both', expand=True, padx=(0, 10))
|
||
|
||
# 右侧预览区域
|
||
preview_frame = ttk.LabelFrame(main_frame, text='实时预览', padding="10")
|
||
preview_frame.pack(side='right', fill='both', expand=True)
|
||
|
||
self._create_edit_area(edit_frame)
|
||
self._create_preview_area(preview_frame)
|
||
self._create_bottom_buttons()
|
||
|
||
def _create_edit_area(self, parent):
|
||
"""创建编辑区域"""
|
||
# 创建笔记本控件
|
||
notebook = ttk.Notebook(parent)
|
||
notebook.pack(fill='both', expand=True)
|
||
|
||
# 基本信息选项卡
|
||
basic_frame = ttk.Frame(notebook)
|
||
notebook.add(basic_frame, text='基本信息')
|
||
self._create_basic_tab(basic_frame)
|
||
|
||
# 正文样式选项卡
|
||
body_frame = ttk.Frame(notebook)
|
||
notebook.add(body_frame, text='正文样式')
|
||
self._create_body_tab(body_frame)
|
||
|
||
# 标题样式选项卡
|
||
heading_frame = ttk.Frame(notebook)
|
||
notebook.add(heading_frame, text='标题样式')
|
||
self._create_heading_tab(heading_frame)
|
||
|
||
def _create_basic_tab(self, parent):
|
||
"""创建基本信息选项卡"""
|
||
# 样式名称
|
||
name_frame = ttk.Frame(parent)
|
||
name_frame.pack(fill='x', padx=10, pady=5)
|
||
ttk.Label(name_frame, text='样式名称:', width=12).pack(side='left')
|
||
self.name_var = tk.StringVar(value=self.current_style.name)
|
||
name_entry = ttk.Entry(name_frame, textvariable=self.name_var)
|
||
name_entry.pack(side='left', fill='x', expand=True, padx=(5, 0))
|
||
|
||
# 样式描述
|
||
desc_frame = ttk.Frame(parent)
|
||
desc_frame.pack(fill='x', padx=10, pady=5)
|
||
ttk.Label(desc_frame, text='描述:', width=12).pack(side='left')
|
||
self.desc_var = tk.StringVar(value=self.current_style.description)
|
||
desc_entry = ttk.Entry(desc_frame, textvariable=self.desc_var)
|
||
desc_entry.pack(side='left', fill='x', expand=True, padx=(5, 0))
|
||
|
||
def _create_body_tab(self, parent):
|
||
"""创建正文样式选项卡"""
|
||
# 正文字体设置
|
||
font_frame = ttk.LabelFrame(parent, text='正文字体', padding="10")
|
||
font_frame.pack(fill='x', padx=10, pady=5)
|
||
|
||
# 字体名称
|
||
name_frame = ttk.Frame(font_frame)
|
||
name_frame.pack(fill='x', pady=2)
|
||
ttk.Label(name_frame, text='字体:', width=10).pack(side='left')
|
||
self.style_vars['font_name'] = tk.StringVar(value=self.current_style.body_font.name)
|
||
font_combo = ttk.Combobox(name_frame, textvariable=self.style_vars['font_name'], width=15,
|
||
values=['宋体', '微软雅黑', '黑体', '楷体', '华文细黑', 'Arial', 'Times New Roman'])
|
||
font_combo.pack(side='left', padx=(5, 10))
|
||
|
||
# 字号
|
||
ttk.Label(name_frame, text='大小:', width=5).pack(side='left')
|
||
self.style_vars['font_size'] = tk.IntVar(value=self.current_style.body_font.size)
|
||
size_spin = ttk.Spinbox(name_frame, from_=8, to=72, textvariable=self.style_vars['font_size'], width=5)
|
||
size_spin.pack(side='left', padx=(5, 0))
|
||
|
||
# 字体样式
|
||
style_frame = ttk.Frame(font_frame)
|
||
style_frame.pack(fill='x', pady=2)
|
||
|
||
self.style_vars['font_bold'] = tk.BooleanVar(value=self.current_style.body_font.bold)
|
||
ttk.Checkbutton(style_frame, text='粗体', variable=self.style_vars['font_bold']).pack(side='left', padx=(0, 10))
|
||
|
||
self.style_vars['font_italic'] = tk.BooleanVar(value=self.current_style.body_font.italic)
|
||
ttk.Checkbutton(style_frame, text='斜体', variable=self.style_vars['font_italic']).pack(side='left', padx=(0, 10))
|
||
|
||
# 字体颜色
|
||
ttk.Label(style_frame, text='颜色:', width=5).pack(side='left')
|
||
self.style_vars['font_color'] = tk.StringVar(value=self.current_style.body_font.color)
|
||
self.color_label = tk.Label(style_frame, text=' ', bg=self.style_vars['font_color'].get(), relief='solid', width=3)
|
||
self.color_label.pack(side='left', padx=(5, 5))
|
||
|
||
ttk.Button(style_frame, text='选择', command=self._choose_font_color).pack(side='left')
|
||
|
||
# 正文段落设置
|
||
para_frame = ttk.LabelFrame(parent, text='正文段落', padding="10")
|
||
para_frame.pack(fill='x', padx=10, pady=5)
|
||
|
||
# 行距
|
||
spacing_frame = ttk.Frame(para_frame)
|
||
spacing_frame.pack(fill='x', pady=2)
|
||
ttk.Label(spacing_frame, text='行距:', width=10).pack(side='left')
|
||
self.style_vars['line_spacing'] = tk.DoubleVar(value=self.current_style.body_paragraph.line_spacing)
|
||
line_spacing_spin = ttk.Spinbox(spacing_frame, from_=0.5, to=3.0, increment=0.1,
|
||
textvariable=self.style_vars['line_spacing'], width=8)
|
||
line_spacing_spin.pack(side='left', padx=(5, 10))
|
||
|
||
# 首行缩进
|
||
ttk.Label(spacing_frame, text='首行缩进:', width=10).pack(side='left')
|
||
self.style_vars['indent'] = tk.DoubleVar(value=self.current_style.body_paragraph.first_line_indent)
|
||
indent_spin = ttk.Spinbox(spacing_frame, from_=0.0, to=10.0, increment=0.5,
|
||
textvariable=self.style_vars['indent'], width=8)
|
||
indent_spin.pack(side='left', padx=(5, 0))
|
||
|
||
# 段间距
|
||
margin_frame = ttk.Frame(para_frame)
|
||
margin_frame.pack(fill='x', pady=2)
|
||
ttk.Label(margin_frame, text='段前:', width=10).pack(side='left')
|
||
self.style_vars['space_before'] = tk.IntVar(value=self.current_style.body_paragraph.space_before)
|
||
before_spin = ttk.Spinbox(margin_frame, from_=0, to=50, textvariable=self.style_vars['space_before'], width=8)
|
||
before_spin.pack(side='left', padx=(5, 10))
|
||
|
||
ttk.Label(margin_frame, text='段后:', width=10).pack(side='left')
|
||
self.style_vars['space_after'] = tk.IntVar(value=self.current_style.body_paragraph.space_after)
|
||
after_spin = ttk.Spinbox(margin_frame, from_=0, to=50, textvariable=self.style_vars['space_after'], width=8)
|
||
after_spin.pack(side='left', padx=(5, 0))
|
||
|
||
def _create_heading_tab(self, parent):
|
||
"""创建标题样式选项卡"""
|
||
# 创建滚动区域
|
||
canvas = tk.Canvas(parent)
|
||
scrollbar = ttk.Scrollbar(parent, orient="vertical", command=canvas.yview)
|
||
scrollable_frame = ttk.Frame(canvas)
|
||
|
||
scrollable_frame.bind(
|
||
"<Configure>",
|
||
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
|
||
)
|
||
|
||
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
|
||
canvas.configure(yscrollcommand=scrollbar.set)
|
||
|
||
# 为每个标题级别创建控件
|
||
for level in range(1, 4):
|
||
level_frame = ttk.LabelFrame(scrollable_frame, text=f'{level}级标题', padding="10")
|
||
level_frame.pack(fill='x', padx=10, pady=5)
|
||
|
||
heading_style = self.current_style.heading_styles.get(level)
|
||
if not heading_style:
|
||
continue
|
||
|
||
# 标题字体名称和大小
|
||
h_name_frame = ttk.Frame(level_frame)
|
||
h_name_frame.pack(fill='x', pady=2)
|
||
ttk.Label(h_name_frame, text='字体:', width=8).pack(side='left')
|
||
h_name_var = tk.StringVar(value=heading_style.font.name)
|
||
h_combo = ttk.Combobox(h_name_frame, textvariable=h_name_var, width=12,
|
||
values=['宋体', '微软雅黑', '黑体', '楷体'])
|
||
h_combo.pack(side='left', padx=(5, 10))
|
||
|
||
ttk.Label(h_name_frame, text='大小:', width=5).pack(side='left')
|
||
h_size_var = tk.IntVar(value=heading_style.font.size)
|
||
h_size_spin = ttk.Spinbox(h_name_frame, from_=8, to=72, textvariable=h_size_var, width=5)
|
||
h_size_spin.pack(side='left', padx=(5, 0))
|
||
|
||
# 标题颜色
|
||
h_color_frame = ttk.Frame(level_frame)
|
||
h_color_frame.pack(fill='x', pady=2)
|
||
ttk.Label(h_color_frame, text='颜色:', width=8).pack(side='left')
|
||
h_color_var = tk.StringVar(value=heading_style.font.color)
|
||
h_color_label = tk.Label(h_color_frame, text=' ', bg=h_color_var.get(), relief='solid', width=3)
|
||
h_color_label.pack(side='left', padx=(5, 5))
|
||
|
||
def make_choose_heading_color(var, label):
|
||
def choose_color():
|
||
color = colorchooser.askcolor(color=var.get())[1]
|
||
if color:
|
||
var.set(color)
|
||
label.config(bg=color)
|
||
self._update_preview()
|
||
return choose_color
|
||
|
||
ttk.Button(h_color_frame, text='选择',
|
||
command=make_choose_heading_color(h_color_var, h_color_label)).pack(side='left')
|
||
|
||
self.heading_vars[level] = {
|
||
'name': h_name_var,
|
||
'size': h_size_var,
|
||
'color': h_color_var
|
||
}
|
||
|
||
canvas.pack(side="left", fill="both", expand=True)
|
||
scrollbar.pack(side="right", fill="y")
|
||
|
||
def _create_preview_area(self, parent):
|
||
"""创建预览区域"""
|
||
# 创建预览容器
|
||
preview_container = ttk.Frame(parent)
|
||
preview_container.pack(fill='both', expand=True)
|
||
|
||
# 预览模式选择
|
||
mode_frame = ttk.Frame(preview_container)
|
||
mode_frame.pack(fill='x', pady=(0, 5))
|
||
|
||
self.preview_mode = tk.StringVar(value="rich")
|
||
ttk.Radiobutton(mode_frame, text="丰富预览", variable=self.preview_mode,
|
||
value="rich", command=self._update_preview).pack(side='left')
|
||
ttk.Radiobutton(mode_frame, text="文本预览", variable=self.preview_mode,
|
||
value="text", command=self._update_preview).pack(side='left', padx=(10, 0))
|
||
|
||
# 预览文本区域
|
||
text_frame = ttk.Frame(preview_container)
|
||
text_frame.pack(fill='both', expand=True)
|
||
|
||
self.preview_text = tk.Text(text_frame, wrap=tk.WORD, state='disabled',
|
||
font=('微软雅黑', 12), bg='white')
|
||
self.preview_text.pack(side='left', fill='both', expand=True)
|
||
|
||
# 滚动条
|
||
preview_scroll = ttk.Scrollbar(text_frame, orient="vertical", command=self.preview_text.yview)
|
||
preview_scroll.pack(side="right", fill="y")
|
||
self.preview_text.configure(yscrollcommand=preview_scroll.set)
|
||
|
||
# 初始化文本标签
|
||
self._init_text_tags()
|
||
|
||
def _create_bottom_buttons(self):
|
||
"""创建底部按钮"""
|
||
button_frame = ttk.Frame(self.window)
|
||
button_frame.pack(fill='x', padx=10, pady=10)
|
||
|
||
ttk.Button(button_frame, text='保存样式', command=self._save_style).pack(side='left', padx=5)
|
||
ttk.Button(button_frame, text='另存为', command=self._save_as_style).pack(side='left', padx=5)
|
||
ttk.Button(button_frame, text='重置', command=self._reset_style).pack(side='left', padx=5)
|
||
|
||
ttk.Button(button_frame, text='关闭', command=self.window.destroy).pack(side='right', padx=5)
|
||
ttk.Button(button_frame, text='应用并关闭', command=self._apply_and_close).pack(side='right', padx=5)
|
||
|
||
def _choose_font_color(self):
|
||
"""选择字体颜色"""
|
||
color = colorchooser.askcolor(color=self.style_vars['font_color'].get())[1]
|
||
if color:
|
||
self.style_vars['font_color'].set(color)
|
||
self.color_label.config(bg=color)
|
||
self._update_preview() # 立即更新预览
|
||
|
||
def _bind_events(self):
|
||
"""绑定事件"""
|
||
# 绑定所有变量的变化事件
|
||
for var in self.style_vars.values():
|
||
if hasattr(var, 'trace'):
|
||
var.trace('w', lambda *args: self._update_preview())
|
||
|
||
for level_vars in self.heading_vars.values():
|
||
for var in level_vars.values():
|
||
if hasattr(var, 'trace'):
|
||
var.trace('w', lambda *args: self._update_preview())
|
||
|
||
# 基本信息变量
|
||
self.name_var.trace('w', lambda *args: self._update_preview())
|
||
self.desc_var.trace('w', lambda *args: self._update_preview())
|
||
|
||
# 预览模式变化事件(在_create_preview_area中已绑定)
|
||
|
||
def _update_current_style(self):
|
||
"""更新当前样式对象"""
|
||
# 更新基本信息
|
||
self.current_style.name = self.name_var.get()
|
||
self.current_style.description = self.desc_var.get()
|
||
|
||
# 更新正文字体
|
||
self.current_style.body_font.name = self.style_vars['font_name'].get()
|
||
self.current_style.body_font.size = self.style_vars['font_size'].get()
|
||
self.current_style.body_font.bold = self.style_vars['font_bold'].get()
|
||
self.current_style.body_font.italic = self.style_vars['font_italic'].get()
|
||
self.current_style.body_font.color = self.style_vars['font_color'].get()
|
||
|
||
# 更新正文段落
|
||
self.current_style.body_paragraph.line_spacing = self.style_vars['line_spacing'].get()
|
||
self.current_style.body_paragraph.first_line_indent = self.style_vars['indent'].get()
|
||
self.current_style.body_paragraph.space_before = self.style_vars['space_before'].get()
|
||
self.current_style.body_paragraph.space_after = self.style_vars['space_after'].get()
|
||
|
||
# 更新标题样式
|
||
for level, vars_dict in self.heading_vars.items():
|
||
if level in self.current_style.heading_styles:
|
||
heading_style = self.current_style.heading_styles[level]
|
||
# 现在heading_style应该始终是HeadingStyle对象
|
||
heading_style.font.name = vars_dict['name'].get()
|
||
heading_style.font.size = vars_dict['size'].get()
|
||
heading_style.font.color = vars_dict['color'].get()
|
||
|
||
def _init_text_tags(self):
|
||
"""初始化文本标签样式"""
|
||
# 配置各种文本标签
|
||
self.preview_text.tag_configure('title', font=('微软雅黑', 14, 'bold'), foreground='#2E86AB')
|
||
self.preview_text.tag_configure('separator', foreground='#666666')
|
||
self.preview_text.tag_configure('heading1', font=('黑体', 18, 'bold'), foreground='#E74C3C')
|
||
self.preview_text.tag_configure('heading2', font=('微软雅黑', 16, 'bold'), foreground='#3498DB')
|
||
self.preview_text.tag_configure('heading3', font=('微软雅黑', 14, 'bold'), foreground='#2ECC71')
|
||
self.preview_text.tag_configure('body', font=('宋体', 12), foreground='#333333')
|
||
self.preview_text.tag_configure('bold', font=('微软雅黑', 12, 'bold'))
|
||
self.preview_text.tag_configure('italic', font=('微软雅黑', 12, 'italic'))
|
||
self.preview_text.tag_configure('quote', font=('楷体', 11, 'italic'), foreground='#7F8C8D',
|
||
background='#F8F9FA')
|
||
self.preview_text.tag_configure('code', font=('Courier New', 10),
|
||
background='#F4F4F4', foreground='#C0392B')
|
||
self.preview_text.tag_configure('info', font=('微软雅黑', 10), foreground='#95A5A6')
|
||
|
||
def _update_preview(self):
|
||
"""更新预览"""
|
||
self._update_current_style()
|
||
|
||
# 清空预览区域
|
||
self.preview_text.config(state='normal')
|
||
self.preview_text.delete(1.0, tk.END)
|
||
|
||
if self.preview_mode.get() == "rich":
|
||
self._create_rich_preview()
|
||
else:
|
||
self._create_text_preview()
|
||
|
||
self.preview_text.config(state='disabled')
|
||
|
||
def _create_rich_preview(self):
|
||
"""创建丰富的样式预览"""
|
||
# 样式标题
|
||
self.preview_text.insert(tk.END, f"样式预览:{self.current_style.name}\n", 'title')
|
||
self.preview_text.insert(tk.END, f"描述:{self.current_style.description}\n\n", 'info')
|
||
|
||
# 分隔线
|
||
self.preview_text.insert(tk.END, "═" * 50 + "\n\n", 'separator')
|
||
|
||
# 动态更新标题样式标签
|
||
self._update_heading_tags()
|
||
|
||
# 一级标题预览
|
||
self.preview_text.insert(tk.END, "一级标题样式预览\n\n", 'heading1_live')
|
||
|
||
# 二级标题预览
|
||
self.preview_text.insert(tk.END, "二级标题样式预览\n\n", 'heading2_live')
|
||
|
||
# 三级标题预览
|
||
self.preview_text.insert(tk.END, "三级标题样式预览\n\n", 'heading3_live')
|
||
|
||
# 动态更新正文样式标签
|
||
self._update_body_tag()
|
||
|
||
# 正文段落预览
|
||
body_text = f"""正文段落样式预览:
|
||
这是正文内容的示例,展示当前选择的字体和格式效果。
|
||
|
||
字体:{self.current_style.body_font.name} {self.current_style.body_font.size}pt
|
||
行距:{self.current_style.body_paragraph.line_spacing}倍
|
||
首行缩进:{self.current_style.body_paragraph.first_line_indent}字符
|
||
段前间距:{self.current_style.body_paragraph.space_before}pt
|
||
段后间距:{self.current_style.body_paragraph.space_after}pt
|
||
|
||
这是包含"""
|
||
|
||
self.preview_text.insert(tk.END, body_text, 'body_live')
|
||
|
||
# 粗体和斜体示例
|
||
self.preview_text.insert(tk.END, "粗体文字", 'bold_live')
|
||
self.preview_text.insert(tk.END, "和", 'body_live')
|
||
self.preview_text.insert(tk.END, "斜体文字", 'italic_live')
|
||
self.preview_text.insert(tk.END, "的段落示例。\n\n", 'body_live')
|
||
|
||
# 引用块示例
|
||
self.preview_text.insert(tk.END, "引用块样式预览:\n", 'body_live')
|
||
self.preview_text.insert(tk.END, " 这是引用块的示例内容,展示引用文字的特殊格式效果。\n\n", 'quote')
|
||
|
||
# 代码块示例
|
||
self.preview_text.insert(tk.END, "代码块样式预览:\n", 'body_live')
|
||
self.preview_text.insert(tk.END, ' print("Hello, World!")\n # 这是代码块的示例\n\n', 'code')
|
||
|
||
# 列表示例
|
||
self.preview_text.insert(tk.END, "列表样式预览:\n", 'body_live')
|
||
self.preview_text.insert(tk.END, "• 无序列表项目1\n• 无序列表项目2\n• 无序列表项目3\n\n", 'body_live')
|
||
self.preview_text.insert(tk.END, "1. 有序列表项目1\n2. 有序列表项目2\n3. 有序列表项目3\n\n", 'body_live')
|
||
|
||
# 样式详情
|
||
details = f"""当前样式设置详情:
|
||
• 字体名称:{self.current_style.body_font.name}
|
||
• 字体大小:{self.current_style.body_font.size}pt
|
||
• 字体颜色:{self.current_style.body_font.color}
|
||
• 是否粗体:{'是' if self.current_style.body_font.bold else '否'}
|
||
• 是否斜体:{'是' if self.current_style.body_font.italic else '否'}
|
||
• 行距:{self.current_style.body_paragraph.line_spacing}倍
|
||
• 首行缩进:{self.current_style.body_paragraph.first_line_indent}字符"""
|
||
|
||
self.preview_text.insert(tk.END, details, 'info')
|
||
|
||
def _create_text_preview(self):
|
||
"""创建简单文本预览"""
|
||
preview_content = f"""样式预览:{self.current_style.name}
|
||
描述:{self.current_style.description}
|
||
|
||
─────────────────────────────
|
||
|
||
# 一级标题样式预览
|
||
|
||
## 二级标题样式预览
|
||
|
||
### 三级标题样式预览
|
||
|
||
正文段落样式预览:
|
||
这是正文内容的示例。使用{self.current_style.body_font.name} {self.current_style.body_font.size}pt字体,
|
||
行距为{self.current_style.body_paragraph.line_spacing}倍,首行缩进{self.current_style.body_paragraph.first_line_indent}字符。
|
||
段前间距{self.current_style.body_paragraph.space_before}pt,段后间距{self.current_style.body_paragraph.space_after}pt。
|
||
|
||
这是包含**粗体文字**和*斜体文字*的段落,用于展示内联样式效果。
|
||
|
||
引用块样式预览:
|
||
> 这是引用块的示例内容,展示引用文字的特殊格式效果。
|
||
|
||
代码块样式预览:
|
||
```
|
||
print("Hello, World!")
|
||
# 这是代码块的示例
|
||
```
|
||
|
||
列表样式预览:
|
||
• 无序列表项目1
|
||
• 无序列表项目2
|
||
• 无序列表项目3
|
||
|
||
1. 有序列表项目1
|
||
2. 有序列表项目2
|
||
3. 有序列表项目3
|
||
|
||
字体设置详情:
|
||
• 字体名称:{self.current_style.body_font.name}
|
||
• 字体大小:{self.current_style.body_font.size}pt
|
||
• 字体颜色:{self.current_style.body_font.color}
|
||
• 粗体:{'是' if self.current_style.body_font.bold else '否'}
|
||
• 斜体:{'是' if self.current_style.body_font.italic else '否'}
|
||
"""
|
||
|
||
self.preview_text.insert(tk.END, preview_content)
|
||
|
||
def _update_heading_tags(self):
|
||
"""动态更新标题样式标签"""
|
||
for level in range(1, 4):
|
||
tag_name = f'heading{level}_live'
|
||
if level in self.current_style.heading_styles:
|
||
heading_style = self.current_style.heading_styles[level]
|
||
font_name = heading_style.font.name
|
||
font_size = heading_style.font.size
|
||
font_weight = 'bold' if heading_style.font.bold else 'normal'
|
||
font_color = heading_style.font.color
|
||
|
||
self.preview_text.tag_configure(tag_name,
|
||
font=(font_name, font_size, font_weight),
|
||
foreground=font_color)
|
||
|
||
def _update_body_tag(self):
|
||
"""动态更新正文样式标签"""
|
||
font_name = self.current_style.body_font.name
|
||
font_size = self.current_style.body_font.size
|
||
font_weight = 'bold' if self.current_style.body_font.bold else 'normal'
|
||
font_slant = 'italic' if self.current_style.body_font.italic else 'roman'
|
||
font_color = self.current_style.body_font.color
|
||
|
||
# 更新正文标签
|
||
self.preview_text.tag_configure('body_live',
|
||
font=(font_name, font_size, font_weight, font_slant),
|
||
foreground=font_color)
|
||
|
||
# 更新粗体标签
|
||
self.preview_text.tag_configure('bold_live',
|
||
font=(font_name, font_size, 'bold', font_slant),
|
||
foreground=font_color)
|
||
|
||
# 更新斜体标签
|
||
self.preview_text.tag_configure('italic_live',
|
||
font=(font_name, font_size, font_weight, 'italic'),
|
||
foreground=font_color)
|
||
|
||
def _save_style(self):
|
||
"""保存样式"""
|
||
try:
|
||
if not self.current_style.name.strip():
|
||
messagebox.showerror("错误", "请输入样式名称")
|
||
return
|
||
|
||
self._update_current_style()
|
||
|
||
# 尝试更新现有样式,如果失败则创建新样式
|
||
if self.current_style.name in style_manager.custom_styles:
|
||
success = style_manager.update_custom_style(self.current_style)
|
||
else:
|
||
success = style_manager.create_custom_style(self.current_style)
|
||
|
||
if success:
|
||
messagebox.showinfo("成功", f"样式 '{self.current_style.name}' 保存成功")
|
||
config.current_style = self.current_style.name
|
||
else:
|
||
if self.current_style.name in style_manager.builtin_styles:
|
||
messagebox.showerror("错误", "不能覆盖内置样式!请使用不同的样式名称或'另存为'功能。")
|
||
else:
|
||
messagebox.showerror("保存失败", "保存样式失败!请检查文件权限或磁盘空间。")
|
||
|
||
except Exception as e:
|
||
messagebox.showerror("错误", f"保存过程中发生异常: {str(e)}")
|
||
|
||
def _save_as_style(self):
|
||
"""另存为新样式"""
|
||
try:
|
||
new_name = simpledialog.askstring("另存为", "请输入新样式名称:")
|
||
if not new_name:
|
||
return
|
||
|
||
if new_name in style_manager.get_style_names():
|
||
if new_name in style_manager.builtin_styles:
|
||
messagebox.showerror("名称冲突", "不能使用内置样式名称!请使用不同的样式名称。")
|
||
else:
|
||
messagebox.showerror("名称已存在", f"样式名称 '{new_name}' 已经存在!请使用不同的名称。")
|
||
return
|
||
|
||
# 修改样式信息
|
||
self.current_style.name = new_name
|
||
self.current_style.description = "基于 " + self.original_style.name + " 定制"
|
||
self._update_current_style()
|
||
|
||
if style_manager.create_custom_style(self.current_style):
|
||
messagebox.showinfo("创建成功", f"样式 '{new_name}' 已成功创建!")
|
||
config_manager = Config()
|
||
config_manager.set('current_style', new_name)
|
||
self.window.destroy()
|
||
else:
|
||
messagebox.showerror("创建失败", "创建样式失败!请检查文件权限或磁盘空间。")
|
||
|
||
except Exception as e:
|
||
messagebox.showerror("错误", f"另存为过程中发生异常: {str(e)}")
|
||
|
||
def _reset_style(self):
|
||
"""重置样式"""
|
||
if messagebox.askyesno("确认重置", "确定要重置为原始样式吗?"):
|
||
self.current_style = copy.deepcopy(self.original_style)
|
||
self._ensure_style_completeness()
|
||
# 重新创建界面(简单的重置方法)
|
||
self.window.destroy()
|
||
self.__init__(self.parent, self.original_style)
|
||
|
||
def _apply_and_close(self):
|
||
"""应用并关闭"""
|
||
self._save_style()
|
||
self.window.destroy() |