From bdf9ab46704c0b707d4a6803bf388ab6fe4645ec Mon Sep 17 00:00:00 2001 From: Ali Al-Ramadan <55710790+aalramadan@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:12:05 -0400 Subject: [PATCH] Few fixes - Fixed an issue related to a popping console window from audio-extract. - Fixed a Few GUI glitches. --- compile/Inno_Setup_Script.iss | 4 +- compile/build.txt | 12 ++---- main.py | 6 ++- main.ui | 10 ++--- ui_functions.py | 39 +++++++++++------ ui_main.py | 80 +++++++++++++++++------------------ 6 files changed, 80 insertions(+), 71 deletions(-) diff --git a/compile/Inno_Setup_Script.iss b/compile/Inno_Setup_Script.iss index a1bade2..07bb186 100644 --- a/compile/Inno_Setup_Script.iss +++ b/compile/Inno_Setup_Script.iss @@ -50,8 +50,8 @@ Name: "english"; MessagesFile: "compiler:Default.isl" Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked [Files] -Source: "C:\Users\Ali\Desktop\TransVisio\main.dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion -Source: "C:\Users\Ali\Desktop\TransVisio\main.dist\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "C:\Users\Ali\Desktop\TransVisio\dist\main\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Ali\Desktop\TransVisio\dist\main\_internal\*"; DestDir: "{app}\_internal"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Registry] diff --git a/compile/build.txt b/compile/build.txt index 12ea133..8b212fa 100644 --- a/compile/build.txt +++ b/compile/build.txt @@ -1,14 +1,10 @@ Build (Windows): -pyinstaller --windowed --hidden-import=tiktoken_ext.openai_public --hidden-import=tiktoken_ext --icon="C:\Users\Ali\Desktop\TransVisio\images\images\icon.ico" main.py -nuitka --standalone --windows-console-mode=disable --msvc=latest --enable-plugin=pyside6 --module-parameter=torch-disable-jit=no --module-parameter=numba-disable-jit=no --noinclude-numba-mode=nofollow --windows-icon-from-ico="C:\Users\Ali\Desktop\TransVisio\images\images\icon.ico" main.py +pyinstaller --noconsole --icon="C:\Users\Ali\Desktop\TransVisio\images\images\icon.ico" main.py Build (Mac OS): -pyinstaller --onefile --windowed --hidden-import=tiktoken_ext.openai_public --hidden-import=tiktoken_ext --icon="/Users/Ali/Desktop/TransVisio/images/images/icon.icns" main.py -nuitka3 --standalone --windows-console-mode=disable --clang --macos-create-app-bundle --enable-plugin=pyside6 --module-parameter=torch-disable-jit=no --module-parameter=numba-disable-jit=no --noinclude-numba-mode=nofollow --macos-app-icon="/Users/Ali/Desktop/TransVisio/images/images/icon.icns" --windows-icon-from-ico="/Users/Ali/Desktop/TransVisio/images/images/icon.icns" main.py +pyinstaller --onefile --windowed --icon="/Users/Ali/Desktop/TransVisio/images/images/icon.icns" main.py -You might need to manually download ccache-4.2.1.zip and move it to: -/Users/ali/library/Caches/Nuitka/downloads/ccache/v4.2.1 - -* Use for debugging --> --console instead of --windowed +* Use for debugging: +--console instead of --windowed diff --git a/main.py b/main.py index 8d2b48c..a101d27 100644 --- a/main.py +++ b/main.py @@ -19,11 +19,13 @@ def __init__(self): self.btn_save_transcription.clicked.connect(lambda: ui_functions.save_template_file(self, True)) self.btn_next.clicked.connect(lambda: ui_functions.check_inputs(self)) self.btn_start.clicked.connect(lambda: ui_functions.communicate_with_api(self)) - self.btn_back.clicked.connect(lambda: ui_functions.button_click(self, self.btn_back)) + self.btn_back.clicked.connect(lambda: ui_functions.button_click(self, self.btn_back)) + self.btn_settings.clicked.connect(lambda: ui_functions.expand_settings(self)) + self.btn_info.clicked.connect(lambda: ui_functions.expand_about(self)) + self.data_table.itemSelectionChanged.connect(lambda: ui_functions.items_selected(self)) self.btn_delete_row.clicked.connect(lambda: ui_functions.delete_row(self)) - self.btn_info.clicked.connect(lambda: ui_functions.expand_about(self)) self.btn_reverse.clicked.connect(lambda: ui_functions.change_text_direction(self)) self.chk_box_dark.clicked.connect(lambda: ui_functions.theme_switch(self, self.chk_box_dark)) self.chk_box_light.clicked.connect(lambda: ui_functions.theme_switch(self, self.chk_box_light)) diff --git a/main.ui b/main.ui index 2e80d03..4afa14f 100644 --- a/main.ui +++ b/main.ui @@ -8,11 +8,11 @@ 0 0 1024 - 728 + 734 - + 0 0 @@ -20,7 +20,7 @@ 1024 - 728 + 734 @@ -511,9 +511,9 @@ QTextBrowser { 0 - -236 + 0 380 - 1056 + 1062 diff --git a/ui_functions.py b/ui_functions.py index 462cbdd..36a817b 100644 --- a/ui_functions.py +++ b/ui_functions.py @@ -1,6 +1,6 @@ from PySide6.QtWidgets import (QMessageBox, QFileDialog, QTableWidgetItem, QHeaderView,QAbstractItemView, QStyledItemDelegate, QTableWidgetItem) -from PySide6.QtCore import QSize, QEasingCurve, QPropertyAnimation, Qt, QFile, QTextStream +from PySide6.QtCore import QSize, QEasingCurve, QPropertyAnimation, Qt, QFile, QTextStream, QTimer from PySide6.QtGui import QIcon, QMovie from srt import parse as parse_srt, compose as compose_srt from ass import parse as parse_ass @@ -10,14 +10,12 @@ from audio_extract import extract_audio from faster_whisper import WhisperModel from datetime import timedelta -from torch import cuda -from pandas import ExcelFile, read_csv, DataFrame +from pandas import read_excel, read_csv, DataFrame from json import loads, dumps -from re import findall from google.generativeai import GenerativeModel, configure, types from os import environ, remove from uuid import uuid4 - +from torch import cuda environ["KMP_DUPLICATE_LIB_OK"]="TRUE" # Needed to get faster-whisper to work @@ -116,7 +114,7 @@ def switch_whisper_models(main_window): main_window.api_key_whisper.setEnabled(True) main_window.combo_model_size.setEnabled(False) -def animate_widget(main_window, widget, next_widget=None): +def animate_widget(main_window, widget, next_widget=None): width = widget.width() width_extended = SETTINGS.EXPAND_WIDTH if width == 0 else 0 main_window.animate_expand = QPropertyAnimation(widget, b"minimumWidth") @@ -126,18 +124,31 @@ def animate_widget(main_window, widget, next_widget=None): main_window.animate_expand.setEasingCurve(QEasingCurve.InOutQuart) main_window.animate_expand.finished.connect(lambda: animate_widget(main_window, next_widget) if next_widget else None) main_window.animate_expand.start() + def expand_settings(main_window): + main_window.btn_settings.setEnabled(False) + main_window.btn_info.setEnabled(False) if main_window.AboutFrame.width() == SETTINGS.EXPAND_WIDTH: animate_widget(main_window, main_window.AboutFrame, main_window.SettingsExpand) + QTimer.singleShot(2 * SETTINGS.TIME_ANIMATION, lambda: enable_buttons(main_window)) else: animate_widget(main_window, main_window.SettingsExpand) + QTimer.singleShot(SETTINGS.TIME_ANIMATION, lambda: enable_buttons(main_window)) def expand_about(main_window): + main_window.btn_settings.setEnabled(False) + main_window.btn_info.setEnabled(False) if main_window.SettingsExpand.width() == SETTINGS.EXPAND_WIDTH: animate_widget(main_window, main_window.SettingsExpand, main_window.AboutFrame) + QTimer.singleShot(2 * SETTINGS.TIME_ANIMATION, lambda: enable_buttons(main_window)) else: animate_widget(main_window, main_window.AboutFrame) + QTimer.singleShot(SETTINGS.TIME_ANIMATION, lambda: enable_buttons(main_window)) + +def enable_buttons(main_window): + main_window.btn_settings.setEnabled(True) + main_window.btn_info.setEnabled(True) def issue_warning_error(main_window, title, text): @@ -147,6 +158,7 @@ def issue_warning_error(main_window, title, text): async def load_template_file(main_window): loading_gif(main_window, 'start') main_window.btn_next.setEnabled(False) + main_window.btn_save.setEnabled(False) global template_loaded global template_file global template_file_format @@ -168,13 +180,12 @@ async def load_template_file(main_window): template_file = parse_ass(file) template_file_format = 'ass-ssa' elif selected_file.endswith('.xlsx'): - xl = ExcelFile(selected_file) - df = xl.parse(xl.sheet_names[0]) # Get first sheet only - template_file = df.iloc[:, 0].tolist() # Get all rows of the first column as a list + xl = read_excel(selected_file, sheet_name=0, header=None) # First sheet only + template_file = xl.iloc[:, 0].tolist() # Get all rows of the first column as a list template_file_format = 'excel' elif selected_file.endswith('.csv'): - df = read_csv(selected_file, header=None) - template_file = df.iloc[:, 0].tolist() + xl = read_csv(selected_file) + template_file = xl.iloc[:, 0].tolist() template_file_format = 'excel' else: api_key_whisper = main_window.api_key_whisper.text().strip() @@ -241,7 +252,7 @@ def save_template_file(main_window, transcriptions): global template_file options = QFileDialog.Options() - if template_file_format == 'ass-ssa' and not transcriptions: + if template_file_format == 'ass-ssa': filter = "SubStation Alpha (*.ssa);;Advacned SubStation Alpha (*.ass)" fileName, _ = QFileDialog.getSaveFileName(None,"Save File", "", filter, options=options) if fileName: @@ -291,7 +302,7 @@ def save_template_file(main_window, transcriptions): def check_inputs(main_window): global template_loaded - if not main_window.input.text() : + if not main_window.input.text(): issue_warning_error(main_window, "Warning", "Specify a template file") else: main_window.StackedWidget.setCurrentWidget(main_window.PostProcessing) @@ -412,7 +423,7 @@ def create_sentences_dictionaries(main_window, input_size): return sentences_list def generate_prompt(main_window): - prompt = f"""The target language of translation is {main_window.target_language.currentText()}. + prompt = f"""The target language of translation is {main_window.target_language.currentText()} The content genre is: {main_window.box_genre.currentText()} The Target Demographic is: {main_window.box_demo.currentText()} The Localization Approach is: {main_window.box_localization.currentText()} diff --git a/ui_main.py b/ui_main.py index 06a05b3..379e686 100644 --- a/ui_main.py +++ b/ui_main.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ################################################################################ -## Form generated from reading UI file 'mainjmHrzX.ui' +## Form generated from reading UI file 'mainiKfOcl.ui' ## ## Created by: Qt User Interface Compiler version 6.7.2 ## @@ -27,13 +27,13 @@ class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") - MainWindow.resize(1024, 728) - sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) + MainWindow.resize(1024, 734) + sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) MainWindow.setSizePolicy(sizePolicy) - MainWindow.setMinimumSize(QSize(1024, 728)) + MainWindow.setMinimumSize(QSize(1024, 734)) font = QFont() font.setFamilies([u"Tahoma"]) MainWindow.setFont(font) @@ -301,11 +301,8 @@ def setupUi(self, MainWindow): self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") self.loading_gif = QLabel(self.frame) self.loading_gif.setObjectName(u"loading_gif") - sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) - sizePolicy1.setHorizontalStretch(0) - sizePolicy1.setVerticalStretch(0) - sizePolicy1.setHeightForWidth(self.loading_gif.sizePolicy().hasHeightForWidth()) - self.loading_gif.setSizePolicy(sizePolicy1) + sizePolicy.setHeightForWidth(self.loading_gif.sizePolicy().hasHeightForWidth()) + self.loading_gif.setSizePolicy(sizePolicy) self.loading_gif.setMinimumSize(QSize(50, 50)) self.horizontalLayout_5.addWidget(self.loading_gif) @@ -323,8 +320,11 @@ def setupUi(self, MainWindow): self.verticalLayout_6.setContentsMargins(0, 0, 0, 0) self.btn_settings = QPushButton(self.MenuFrame) self.btn_settings.setObjectName(u"btn_settings") - sizePolicy.setHeightForWidth(self.btn_settings.sizePolicy().hasHeightForWidth()) - self.btn_settings.setSizePolicy(sizePolicy) + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.btn_settings.sizePolicy().hasHeightForWidth()) + self.btn_settings.setSizePolicy(sizePolicy1) self.btn_settings.setMinimumSize(QSize(45, 45)) self.btn_settings.setFont(font1) self.btn_settings.setCursor(QCursor(Qt.CursorShape.ArrowCursor)) @@ -338,8 +338,8 @@ def setupUi(self, MainWindow): self.btn_info = QPushButton(self.MenuFrame) self.btn_info.setObjectName(u"btn_info") - sizePolicy.setHeightForWidth(self.btn_info.sizePolicy().hasHeightForWidth()) - self.btn_info.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_info.sizePolicy().hasHeightForWidth()) + self.btn_info.setSizePolicy(sizePolicy1) self.btn_info.setMinimumSize(QSize(0, 45)) self.btn_info.setStyleSheet(u"") icon2 = QIcon() @@ -356,8 +356,8 @@ def setupUi(self, MainWindow): self.SettingsExpand = QFrame(self.CentralWidget) self.SettingsExpand.setObjectName(u"SettingsExpand") - sizePolicy.setHeightForWidth(self.SettingsExpand.sizePolicy().hasHeightForWidth()) - self.SettingsExpand.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.SettingsExpand.sizePolicy().hasHeightForWidth()) + self.SettingsExpand.setSizePolicy(sizePolicy1) self.SettingsExpand.setMinimumSize(QSize(0, 0)) self.SettingsExpand.setMaximumSize(QSize(0, 16777215)) self.SettingsExpand.setStyleSheet(u"") @@ -373,15 +373,15 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, -236, 380, 1056)) + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 380, 1062)) self.verticalLayout_8 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_8.setSpacing(0) self.verticalLayout_8.setObjectName(u"verticalLayout_8") self.verticalLayout_8.setContentsMargins(0, 0, 0, 0) self.ModelFrame = QFrame(self.scrollAreaWidgetContents) self.ModelFrame.setObjectName(u"ModelFrame") - sizePolicy.setHeightForWidth(self.ModelFrame.sizePolicy().hasHeightForWidth()) - self.ModelFrame.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.ModelFrame.sizePolicy().hasHeightForWidth()) + self.ModelFrame.setSizePolicy(sizePolicy1) self.ModelFrame.setMinimumSize(QSize(380, 0)) self.ModelFrame.setMaximumSize(QSize(16777215, 16777215)) self.ModelFrame.setFrameShape(QFrame.Shape.StyledPanel) @@ -706,8 +706,8 @@ def setupUi(self, MainWindow): self.StackedWidget.setMinimumSize(QSize(0, 0)) self.Home = QWidget() self.Home.setObjectName(u"Home") - sizePolicy.setHeightForWidth(self.Home.sizePolicy().hasHeightForWidth()) - self.Home.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.Home.sizePolicy().hasHeightForWidth()) + self.Home.setSizePolicy(sizePolicy1) self.Home.setMaximumSize(QSize(16777215, 16777215)) self.verticalLayout = QVBoxLayout(self.Home) self.verticalLayout.setSpacing(0) @@ -720,8 +720,8 @@ def setupUi(self, MainWindow): self.input = QLineEdit(self.Home) self.input.setObjectName(u"input") self.input.setEnabled(True) - sizePolicy.setHeightForWidth(self.input.sizePolicy().hasHeightForWidth()) - self.input.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.input.sizePolicy().hasHeightForWidth()) + self.input.setSizePolicy(sizePolicy1) self.input.setMinimumSize(QSize(0, 50)) self.input.setMaximumSize(QSize(16777215, 50)) self.input.setDragEnabled(True) @@ -740,8 +740,8 @@ def setupUi(self, MainWindow): self.btn_open = QPushButton(self.Home) self.btn_open.setObjectName(u"btn_open") - sizePolicy.setHeightForWidth(self.btn_open.sizePolicy().hasHeightForWidth()) - self.btn_open.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_open.sizePolicy().hasHeightForWidth()) + self.btn_open.setSizePolicy(sizePolicy1) self.btn_open.setMinimumSize(QSize(0, 50)) self.btn_open.setMaximumSize(QSize(150, 16777215)) self.btn_open.setLayoutDirection(Qt.LayoutDirection.LeftToRight) @@ -974,8 +974,8 @@ def setupUi(self, MainWindow): self.btn_next = QPushButton(self.NextBox) self.btn_next.setObjectName(u"btn_next") self.btn_next.setEnabled(False) - sizePolicy.setHeightForWidth(self.btn_next.sizePolicy().hasHeightForWidth()) - self.btn_next.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_next.sizePolicy().hasHeightForWidth()) + self.btn_next.setSizePolicy(sizePolicy1) self.btn_next.setMinimumSize(QSize(150, 40)) self.btn_next.setMaximumSize(QSize(150, 40)) icon4 = QIcon() @@ -1008,8 +1008,8 @@ def setupUi(self, MainWindow): self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) self.data_table = QTableWidget(self.ScrollAreaWidgetContents) self.data_table.setObjectName(u"data_table") - sizePolicy.setHeightForWidth(self.data_table.sizePolicy().hasHeightForWidth()) - self.data_table.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.data_table.sizePolicy().hasHeightForWidth()) + self.data_table.setSizePolicy(sizePolicy1) self.data_table.setMinimumSize(QSize(0, 0)) self.data_table.horizontalHeader().setStretchLastSection(False) self.data_table.verticalHeader().setVisible(True) @@ -1023,8 +1023,8 @@ def setupUi(self, MainWindow): self.NavBox = QFrame(self.PostProcessing) self.NavBox.setObjectName(u"NavBox") - sizePolicy.setHeightForWidth(self.NavBox.sizePolicy().hasHeightForWidth()) - self.NavBox.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.NavBox.sizePolicy().hasHeightForWidth()) + self.NavBox.setSizePolicy(sizePolicy1) self.NavBox.setMinimumSize(QSize(0, 40)) self.NavBox.setFrameShape(QFrame.Shape.StyledPanel) self.NavBox.setFrameShadow(QFrame.Shadow.Raised) @@ -1034,8 +1034,8 @@ def setupUi(self, MainWindow): self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) self.btn_back = QPushButton(self.NavBox) self.btn_back.setObjectName(u"btn_back") - sizePolicy.setHeightForWidth(self.btn_back.sizePolicy().hasHeightForWidth()) - self.btn_back.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_back.sizePolicy().hasHeightForWidth()) + self.btn_back.setSizePolicy(sizePolicy1) self.btn_back.setMinimumSize(QSize(0, 40)) self.btn_back.setMaximumSize(QSize(155, 40)) icon5 = QIcon() @@ -1047,8 +1047,8 @@ def setupUi(self, MainWindow): self.btn_delete_row = QPushButton(self.NavBox) self.btn_delete_row.setObjectName(u"btn_delete_row") self.btn_delete_row.setEnabled(False) - sizePolicy.setHeightForWidth(self.btn_delete_row.sizePolicy().hasHeightForWidth()) - self.btn_delete_row.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_delete_row.sizePolicy().hasHeightForWidth()) + self.btn_delete_row.setSizePolicy(sizePolicy1) self.btn_delete_row.setMinimumSize(QSize(0, 40)) self.btn_delete_row.setMaximumSize(QSize(155, 40)) icon6 = QIcon() @@ -1059,8 +1059,8 @@ def setupUi(self, MainWindow): self.btn_start = QPushButton(self.NavBox) self.btn_start.setObjectName(u"btn_start") - sizePolicy.setHeightForWidth(self.btn_start.sizePolicy().hasHeightForWidth()) - self.btn_start.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_start.sizePolicy().hasHeightForWidth()) + self.btn_start.setSizePolicy(sizePolicy1) self.btn_start.setMinimumSize(QSize(0, 40)) self.btn_start.setMaximumSize(QSize(155, 40)) icon7 = QIcon() @@ -1093,8 +1093,8 @@ def setupUi(self, MainWindow): self.btn_save = QPushButton(self.NavBox) self.btn_save.setObjectName(u"btn_save") self.btn_save.setEnabled(False) - sizePolicy.setHeightForWidth(self.btn_save.sizePolicy().hasHeightForWidth()) - self.btn_save.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.btn_save.sizePolicy().hasHeightForWidth()) + self.btn_save.setSizePolicy(sizePolicy1) self.btn_save.setMinimumSize(QSize(0, 40)) self.btn_save.setMaximumSize(QSize(155, 40)) self.btn_save.setIcon(icon9) @@ -1116,8 +1116,8 @@ def setupUi(self, MainWindow): self.AboutFrame = QFrame(self.CentralWidget) self.AboutFrame.setObjectName(u"AboutFrame") - sizePolicy.setHeightForWidth(self.AboutFrame.sizePolicy().hasHeightForWidth()) - self.AboutFrame.setSizePolicy(sizePolicy) + sizePolicy1.setHeightForWidth(self.AboutFrame.sizePolicy().hasHeightForWidth()) + self.AboutFrame.setSizePolicy(sizePolicy1) self.AboutFrame.setMinimumSize(QSize(0, 0)) self.AboutFrame.setMaximumSize(QSize(0, 16777215)) self.AboutFrame.setFrameShape(QFrame.Shape.StyledPanel)